[#31320] Import RubyGems to Ruby 1.9 — "NAKAMURA, Hiroshi" <nakahiro@...>
-----BEGIN PGP SIGNED MESSAGE-----
なかだです。
まつもと ゆきひろです
-----BEGIN PGP SIGNED MESSAGE-----
-----BEGIN PGP SIGNED MESSAGE-----
-----BEGIN PGP SIGNED MESSAGE-----
-----BEGIN PGP SIGNED MESSAGE-----
まつもと ゆきひろです
-----BEGIN PGP SIGNED MESSAGE-----
まつもと ゆきひろです
-----BEGIN PGP SIGNED MESSAGE-----
まつもと ゆきひろです
-----BEGIN PGP SIGNED MESSAGE-----
まつもと ゆきひろです
-----BEGIN PGP SIGNED MESSAGE-----
まつもと ゆきひろです
-----BEGIN PGP SIGNED MESSAGE-----
まつもと ゆきひろです
In article <E1Ika5D-0007fc-GG@x31>,
-----BEGIN PGP SIGNED MESSAGE-----
まつもと ゆきひろです
-----BEGIN PGP SIGNED MESSAGE-----
Tuesday 16 October 2007 14:09:13 に NAKAMURA, Hiroshi さんは書きました:
-----BEGIN PGP SIGNED MESSAGE-----
押田です。
Sunday 21 October 2007 00:17:43 に NAKAMURA, Hiroshi さんは書きました:
In message <471447D5.5050902@sarion.co.jp>
咳といいます。
Rubygems は、基本的に他のパッケージシステムから包みやすい作り
In message <868x62huhe.knu@iDaemons.org>
At Wed, 17 Oct 2007 22:04:23 +0900,
> ちなみに「ruby/1.9.1の標準添付からどのライブラリを外すか?」という議論も
-----BEGIN PGP SIGNED MESSAGE-----
-----BEGIN PGP SIGNED MESSAGE-----
ささだです。
-----BEGIN PGP SIGNED MESSAGE-----
まつもと ゆきひろです
-----BEGIN PGP SIGNED MESSAGE-----
まつもと ゆきひろです
永井@知能.九工大です.
-----BEGIN PGP SIGNED MESSAGE-----
[#31323] Bignum#to_s の Karatsuba 基数変換による高速化 — "Kenta Murata" <muraken@...>
むらけんです.
まつもと ゆきひろです
むらけんです.
まつもと ゆきひろです
遠藤です。
むらたです.
遠藤です。
むらたです.
[#31333] Invalid error message by illegal regexp — KIMURA Koichi <kimura.koichi@...>
木村です。
[#31351] set_trace_func NULL pointer given — eklerni <eklerni@...>
From:eklerni
[#31357] invalid string for Date.parse — Yukihiro Matsumoto <matz@...>
まつもと ゆきひろです
> となります。どうも、junではじまっているので6月とみなしている
なかだです。
[#31371] simultaneous exceptions dump core — "Yusuke ENDOH" <mame@...>
遠藤と申します。
ささだです。
遠藤です。
[#31376] Re: [ ruby-Bugs-9490 ] Date module, step method, infinite loop if +step+ is 0 should raise an exception? — Urabe Shyouhei <shyouhei@...>
rubyforgeで表題の件が卜部にassignされてるのですが、どうしましょう。
Date のほうで、合せたらいいというのなら、それでいいと思います。
[#31377] Re: [ ruby-Patches-11719 ] add a :passive option to open-uri's open method — Urabe Shyouhei <shyouhei@...>
rubyforgeで表題の件が卜部にassignされてるのですが、どうしましょう。
In article <46BE0E9B.70309@ruby-lang.org>,
[#31397] File exists - /tmp/bootstraptest.tmpwd — Tanaka Akira <akr@...>
ひとつのマシンで、あるユーザが btest した後、他のユーザが
ささだです。
[#31407] [BUG] Stack consistency error (sp: 11, bp: 12) — Tanaka Akira <akr@...>
以下のようにすると Stack consistency error になります。
[#31448] Ruby's (new) Bizarre Operator(s) — Nobuyoshi Nakada <nobu@...>
なかだです。
まつもと ゆきひろです
バンサンです。
[#31462] Dir.mktmpdir for 1.8 — Tanaka Akira <akr@...>
Dir.mktmpdir を 1.8 に入れたいんですが、どうでしょう?
まつもと ゆきひろです
In article <E1IMCUq-00083X-Uo@x31>,
[#31470] nested fiber invocation — Yukihiro Matsumoto <matz@...>
まつもと ゆきひろです
[#31473] setter of $! — SASADA Koichi <ko1@...>
ささだです。
[#31475] lambda {|(v0,v1),v2|}.call([1],2) — Tanaka Akira <akr@...>
以下の例は ArgumentError になりません。
ささだです。
[#31492] SEGV: def m() yield [] end; m(&lambda {|*v| p v}) — Tanaka Akira <akr@...>
以下のようにすると SEGV になります。
[#31502] {|(a,a)|} — Tanaka Akira <akr@...>
以下がエラーになりません。
[#31522] a, a = 1, 2 — Tanaka Akira <akr@...>
ふと気がついたんですが、a, a = 1, 2 とすると、1.8 と 1.9 で
こんにちは、なかむら(う)です。
[#31525] いくつかのバグ報告と提案(5点) — eklerni <eklerni@...>
From:eklerni
まつもと ゆきひろです
[#31539] strtod の精度 — Satoshi Nakagawa <snakagawa@...>
中川といいます。
まつもと ゆきひろです
中川です。
中川です。
まつもと ゆきひろです
中川です。
中川です。
まつもと ゆきひろです
In article <EEC70971-AED4-4830-801B-A507561AEDCD@infoteria.co.jp>,
[#31576] test/win32ole — SASADA Koichi <ko1@...>
ささだです.
[#31583] Fiber reviesed — SASADA Koichi <ko1@...>
ささだです.
遠藤です。
ささだです.
遠藤です。
ささだです.
[#31625] IO.sysdup2, IO.sysdup, IO.sysclose — Tanaka Akira <akr@...>
redirect の処理をちょっと書いてみたところ、
まつもと ゆきひろです
In article <E1IOaVr-0001Yu-4H@x31>,
In article <87d4xc97ml.fsf@fsij.org>,
[#31646] Re: [ruby-cvs:20498] Ruby:r13261 (trunk): * encoding.c: provide basic features for M17N. — Tanaka Akira <akr@...>
In article <200708250329.l7P3TjNP004245@ci.ruby-lang.org>,
まつもと ゆきひろです
[#31651] rb_enc_mbclen — Tanaka Akira <akr@...>
rb_enc_mbclen のインターフェースは GB18030 などで困るんじゃ
[ruby-dev:31327] Re: Bignum#to_s の Karatsuba 基数変換による高速化
むらけんです.
# 私のところに ruby-dev:31312 が届いてないのが不思議・・・
On 8/1/07, Yukihiro Matsumoto <matz@ruby-lang.org> wrote:
> まつもと ゆきひろです
> ちょうど[ruby-dev:31312]を取り込もうと思っていた矢先だったの
> ですが、どっちがいいですかねえ。
同じ条件で処理時間を計測して,短い方を採用したらいいと思いました.
そこで,添付のようなパッチと,ベンチマークプログラムで計測したところ
以下のようになりました.
$ ./ruby -I lib karatsuba.rb
Rehearsal --------------------------------------------------
original 2.410000 0.000000 2.410000 ( 9.625259)
ruby-dev:31312 2.420000 0.000000 2.420000 ( 9.635740)
ruby-dev:31323 1.740000 0.000000 1.740000 ( 6.842046)
----------------------------------------- total: 6.570000sec
user system total real
original 2.420000 0.000000 2.420000 ( 9.931306)
ruby-dev:31312 2.420000 0.000000 2.420000 ( 9.627448)
ruby-dev:31323 1.740000 0.000000 1.740000 ( 6.842890)
なぜか ruby-dev:31312 が,オリジナルと比較して早くなってないのですが,
ベンチマークプログラムが悪いのでしょうか・・・
単純に[ruby-dev:31312] が速くなる条件と,私の [ruby-dev:31323] が
速くなる条件が違うという理解で良いものかどうか.
加えて,[ruby-dev:31323] で添付した私のパッチはバグがある状態のものでした.
正しくは,
+VALUE
+rb_big2str_karatsuba(VALUE x, VALUE base)
+{
+ return rb_big2str0_karatsuba(x, FIX2INT(base), Qtrue);
+}
+
この部分を以下のように修正してください.
+VALUE
+rb_big2str_karatsuba(VALUE x, int base)
+{
+ return rb_big2str0_karatsuba(x, base, Qtrue);
+}
> あと、Karatsubaといえばかけ算
> の高速化についても(アルゴリズムが理解できず)ほったらかしだっ
> たんですよねえ。
今すぐというわけにはいかないのですが,こちらも手をつけようと思っています.
Ruby にはできるだけ速くなってもらいたいです :)
--
Kenta Murata
OpenPGP FP = FA26 35D7 4F98 3498 0810 E0D5 F213 966F E9EB 0BCC
Attachments (2)
Index: bignum.c
===================================================================
--- bignum.c (revision 12859)
+++ bignum.c (working copy)
@@ -19,6 +19,8 @@
#include <ieeefp.h>
#endif
+#include <st.h>
+
VALUE rb_cBignum;
#if defined __MINGW32__
@@ -727,12 +729,467 @@
return ss;
}
+#define MAX_POWER_CACHE_ENTRIES 64
+
+struct power_cache_data
+{
+ VALUE power;
+ long magic;
+};
+
+struct power_cache_entry
+{
+ st_table* cache;
+ long len;
+};
+
+struct power_cache
+{
+ struct power_cache_entry entries[35];
+};
+
+static int
+mark_cache_entry(long n1, struct power_cache_data* data, void* _)
+{
+ rb_gc_mark(data->power);
+ return ST_CONTINUE;
+}
+
+static void
+power_cache_mark(struct power_cache* pc)
+{
+ int i;
+ for (i = 0; i < 35; ++i)
+ st_foreach(pc->entries[i].cache, mark_cache_entry, 0);
+}
+
+static int
+free_cache_entry(long n1, struct power_cache_data* data, void* _)
+{
+ if (data != 0)
+ free(data);
+ return ST_DELETE;
+}
+
+static void
+power_cache_free(struct power_cache* pc)
+{
+ int i;
+ for (i = 0; i < 35; ++i) {
+ st_foreach(pc->entries[i].cache, free_cache_entry, 0);
+ st_free_table(pc->entries[i].cache);
+ }
+ free(pc);
+}
+
+static VALUE big2str_power_cache = 0;
+
+static void
+power_cache_init(void)
+{
+ struct power_cache* pc;
+ int i;
+
+ big2str_power_cache = Data_Make_Struct(
+ rb_cData, struct power_cache, power_cache_mark, power_cache_free, pc);
+ rb_global_variable(&big2str_power_cache);
+ for (i = 0; i < 35; i++) {
+ pc->entries[i].cache = st_init_numtable();
+ pc->entries[i].len = 0;
+ }
+}
+
+struct power_cache_find_to_remove_data
+{
+ long n1;
+ long max_magic;
+};
+
+static int
+power_cache_find_to_remove(long n1, struct power_cache_data* pcd,
+ struct power_cache_find_to_remove_data* data)
+{
+ if (pcd->magic > data->max_magic) {
+ data->n1 = n1;
+ data->max_magic = pcd->magic++;
+ }
+ return ST_CONTINUE;
+}
+
+static VALUE
+power_cache_lookup(base, n1)
+ int base;
+ long n1;
+{
+ struct power_cache* pc;
+ struct power_cache_data* pcd = 0;
+
+ if (big2str_power_cache == 0) power_cache_init();
+ Data_Get_Struct(big2str_power_cache, struct power_cache, pc);
+ if (pc->entries[base - 2].len == 0 ||
+ !st_lookup(pc->entries[base - 2].cache, n1, (st_data_t*)&pcd))
+ return Qnil;
+ return pcd->power;
+}
+
+static void
+power_cache_insert(base, n1, power)
+ int base;
+ long n1;
+ VALUE power;
+{
+ struct power_cache* pc;
+ struct power_cache_data* pcd;
+
+ Data_Get_Struct(big2str_power_cache, struct power_cache, pc);
+ if (pc->entries[base - 2].len == MAX_POWER_CACHE_ENTRIES) {
+ struct power_cache_find_to_remove_data data = { 0, 0 };
+ st_foreach(pc->entries[base - 2].cache,
+ power_cache_find_to_remove, (st_data_t)&data);
+ st_delete(pc->entries[base - 2].cache, &data.n1, 0);
+ pc->entries[base - 2].len--;
+ }
+
+ pcd = ALLOC(struct power_cache_data);
+ pcd->power = power;
+ pcd->magic = 0;
+ st_insert(pc->entries[base - 2].cache, n1, (st_data_t)pcd);
+ pc->entries[base - 2].len++;
+}
+
+static VALUE
+power_cache_get_power(base, n1)
+ int base;
+ long n1;
+{
+ VALUE power = power_cache_lookup(base, n1);
+ if (NIL_P(power)) {
+ power = rb_big_pow(rb_int2big(base), LONG2NUM(n1));
+ power_cache_insert(base, n1, power);
+ }
+ return power;
+}
+
+/* big2str_karatsuba_find_n1
+ *
+ * Let a natural number x is given by:
+ * x = 2^0 * x_0 + 2^1 * x_1 + ... + 2^(B*n_0 - 1) * x_{B*n_0 - 1},
+ * where B is BITSPERDIG (i.e. BDIGITS*CHAR_BIT) and n_0 is
+ * RBIGNUM(x)->len.
+ *
+ * Now, we assume n_1 = min_n \{ n | 2^(B*n_0/2) <= b_1^(n_1) \}, so
+ * it is realized that 2^(B*n_0) <= {b_1}^{2*n_1}, where b_1 is a
+ * given radix number. And then, we have n_1 <= (B*n_0) /
+ * (2*log_2(b_1)), therefore n_1 is given by ceil((B*n_0) /
+ * (2*log_2(b_1))).
+ */
+static long
+big2str_karatsuba_find_n1(VALUE x, int base)
+{
+ static const double log_2[] = {
+ 1.0, 1.58496250072116, 2.0,
+ 2.32192809488736, 2.584962500721, 2.58496250072116,
+ 2.8073549220576, 3.0, 3.16992500144231,
+ 3.32192809488736, 3.4594316186373, 3.58496250072116,
+ 3.70043971814109, 3.8073549220576, 3.90689059560852,
+ 4.0, 4.08746284125034, 4.16992500144231,
+ 4.24792751344359, 4.32192809488736, 4.39231742277876,
+ 4.4594316186373, 4.52356195605701, 4.58496250072116,
+ 4.64385618977472, 4.70043971814109, 4.75488750216347,
+ 4.8073549220576, 4.85798099512757, 4.90689059560852,
+ 4.95419631038688, 5.0, 5.04439411935845,
+ 5.08746284125034, 5.12928301694497, 5.16992500144231
+ };
+ long bits;
+
+ if (base < 2 && 36 < base)
+ rb_bug("illegal radix %d", base);
+
+ if (FIXNUM_P(x)) {
+ bits = (SIZEOF_LONG*CHAR_BIT - 1)/2 + 1;
+ }
+ else if (BIGZEROP(x)) {
+ return 0;
+ }
+ else {
+ bits = BITSPERDIG*RBIGNUM(x)->len;
+ }
+
+ return (long)(bits/(2*log_2[base - 2]) + 1);
+}
+
+static long
+big2str_karatsuba_without_sign(x, base, ptr, n1)
+ VALUE x;
+ int base;
+ char* ptr;
+ long n1;
+{
+ long len = 2*n1;
+ VALUE b, qr;
+
+ if (FIXNUM_P(x)) {
+ VALUE str = rb_fix2str(x, base);
+ memset(ptr, '0', len - RSTRING(str)->len);
+ MEMCPY(ptr + len - RSTRING(str)->len, RSTRING(str)->ptr,
+ char, RSTRING(str)->len);
+ return;
+ }
+ if (BIGZEROP(x)) {
+ memset(ptr, '0', len);
+ return;
+ }
+
+ if (n1 % 2 == 1) ++n1;
+ b = power_cache_get_power(base, n1);
+ qr = rb_big_divmod(x, b);
+ big2str_karatsuba_without_sign(
+ RARRAY(qr)->ptr[0], base, ptr, (len - n1)/2);
+ big2str_karatsuba_without_sign(
+ RARRAY(qr)->ptr[1], base, ptr + (len - n1), n1/2);
+}
+
VALUE
+rb_big2str0_karatsuba(x, base, trim)
+ VALUE x;
+ int base;
+ int trim;
+{
+ VALUE ss, xx;
+ long n1;
+
+ if (FIXNUM_P(x)) {
+ return rb_fix2str(x, base);
+ }
+ if (BIGZEROP(x)) {
+ return rb_str_new2("0");
+ }
+
+ if (base < 2 && 36 < base)
+ rb_raise(rb_eArgError, "illegal radix %d", base);
+
+ xx = rb_big_clone(x);
+ n1 = big2str_karatsuba_find_n1(xx, base);
+ ss = rb_str_new(0, 2*n1 + 1); /* plus one for sign */
+ RSTRING(ss)->ptr[0] = RBIGNUM(xx)->sign ? '+' : '-';
+ RBIGNUM(xx)->sign = 1;
+
+ big2str_karatsuba_without_sign(
+ xx, base, RSTRING(ss)->ptr + 1, n1);
+ if (trim) {
+ int i = 1;
+ while (RSTRING(ss)->ptr[i] == '0') ++i;
+ if (RBIGNUM(x)->sign) {
+ MEMMOVE(RSTRING(ss)->ptr, RSTRING(ss)->ptr + i,
+ char, RSTRING(ss)->len - i); /* plus one for '\0' */
+ }
+ else {
+ MEMMOVE(RSTRING(ss)->ptr + 1, RSTRING(ss)->ptr + i,
+ char, RSTRING(ss)->len - i); /* plus one for '\0' */
+ }
+ RSTRING(ss)->len -= i - !RBIGNUM(x)->sign;
+ }
+ RSTRING(ss)->ptr[RSTRING(ss)->len] = '\0';
+
+ return ss;
+}
+
+static inline int
+big2str_normal(VALUE x, long j, int base, int hbase, char *s, int trim)
+{
+ long i = RBIGNUM(x)->len;
+ BDIGIT *ds = BDIGITS(x);
+
+ while (i && j > 1) {
+ long k = i;
+ BDIGIT_DBL num = 0;
+
+ while (k--) {
+ num = BIGUP(num) + ds[k];
+ ds[k] = (BDIGIT)(num / hbase);
+ num %= hbase;
+ }
+ if (trim && ds[i-1] == 0) i--;
+ k = SIZEOF_BDIGITS;
+ while (k--) {
+ s[--j] = ruby_digitmap[num % base];
+ num /= base;
+ if (!trim && j < 1) break;
+ if (trim && i == 0 && num == 0) break;
+ }
+ }
+ return j;
+}
+
+#define KARATSUBA_DIGITS 1024
+static VALUE big2str_table[37][16];
+
+static VALUE bigsqr(VALUE x);
+static void bigdivmod(VALUE x, VALUE y, VALUE *divp, VALUE *modp);
+
+static inline int
+big2str_karatsuba_31312(VALUE x, int n, int base, int hbase, char *s, int trim)
+{
+ long i, j, k, bs_len, sign = RBIGNUM(x)->sign;
+ volatile VALUE t = big2str_table[base][0], t2;
+ VALUE *as, *bs, q, r;
+
+ j = RBIGNUM(t)->len;
+ for (i=0; j <= RBIGNUM(x)->len; i++) j *= 2;
+
+ as = ALLOCA_N(VALUE, i);
+
+ for (i=0,j=1; ; i++,j*=2) {
+ as[i] = t;
+ if(big2str_table[base][i + 1]) {
+ t2 = big2str_table[base][i + 1];
+ }
+ else {
+ t2 = bigsqr(t);
+ if(i + 1 < 16) {
+ big2str_table[base][i + 1] = t2;
+ rb_global_variable(&big2str_table[base][i + 1]);
+ }
+ }
+ if(RBIGNUM(x)->len < RBIGNUM(t2)->len) break;
+ t = t2;
+ }
+
+ bs_len = j * 2;
+ bs = ALLOCA_N(VALUE, bs_len);
+ bs[0] = x;
+ RBIGNUM(x)->sign = 1;
+ for (; j>0; i--, j/=2) {
+ for (k=0; k<bs_len; k+=j*2) {
+ bigdivmod(bs[k], as[i], &q, &r);
+ bs[k] = q;
+ bs[k + j] = r;
+ }
+ }
+ RBIGNUM(x)->sign = sign;
+
+ j = 0;
+ while(RBIGNUM(bs[j])->len == 1 && BDIGITS(bs[j])[0] == 0) j++;
+ for (i=bs_len-1; i>j; i--) {
+ k = big2str_normal(
+ bs[i], KARATSUBA_DIGITS, base, hbase,
+ s + n - KARATSUBA_DIGITS, Qfalse);
+ n -= KARATSUBA_DIGITS - k;
+ }
+ n = big2str_normal(bs[j], n, base, hbase, s, trim);
+
+ return n;
+}
+
+VALUE
+rb_big2str0_31312(VALUE x, int base, int trim)
+{
+ volatile VALUE t;
+ long i, j, hbase;
+ VALUE ss;
+ char *s;
+
+ if (FIXNUM_P(x)) {
+ return rb_fix2str(x, base);
+ }
+ i = RBIGNUM(x)->len;
+ if (BIGZEROP(x)) {
+ return rb_str_new2("0");
+ }
+ j = SIZEOF_BDIGITS*CHAR_BIT*i;
+ switch (base) {
+ case 2: break;
+ case 3:
+ j = j * 53L / 84 + 1;
+ break;
+ case 4: case 5: case 6: case 7:
+ j = (j + 1) / 2;
+ break;
+ case 8: case 9:
+ j = (j + 2) / 3;
+ break;
+ case 10: case 11: case 12: case 13: case 14: case 15:
+ j = j * 28L / 93 + 1;
+ break;
+ case 16: case 17: case 18: case 19: case 20: case 21:
+ case 22: case 23: case 24: case 25: case 26: case 27:
+ case 28: case 29: case 30: case 31:
+ j = (j + 3) / 4;
+ break;
+ case 32: case 33: case 34: case 35: case 36:
+ j = (j + 4) / 5;
+ break;
+ default:
+ rb_raise(rb_eArgError, "illegal radix %d", base);
+ break;
+ }
+ j++; /* space for sign */
+
+ hbase = base * base;
+#if SIZEOF_BDIGITS > 2
+ hbase *= hbase;
+#endif
+
+ t = rb_big_clone(x);
+ ss = rb_str_new(0, j+1);
+ s = RSTRING(ss)->ptr;
+
+ s[0] = RBIGNUM(x)->sign ? '+' : '-';
+ if (RBIGNUM(x)->len > RBIGNUM(big2str_table[base][0])->len * 4) {
+ j = big2str_karatsuba_31312(t, j, base, hbase, s, trim);
+ }
+ else {
+ j = big2str_normal(t, j, base, hbase, s, trim);
+ }
+ if (trim) {while (s[j] == '0') j++;}
+ i = RSTRING(ss)->len - j;
+ if (RBIGNUM(x)->sign) {
+ memmove(s, s+j, i);
+ RSTRING(ss)->len = i-1;
+ }
+ else {
+ memmove(s+1, s+j, i);
+ RSTRING(ss)->len = i;
+ }
+ s[RSTRING(ss)->len] = '\0';
+
+ return ss;
+}
+
+static void
+init_big2str_table(void)
+{
+ int i, j;
+ VALUE v;
+
+ for (i=0; i<37; i++) {
+ v = rb_big_pow(rb_int2big(i), INT2FIX(KARATSUBA_DIGITS));
+ big2str_table[i][0] = v;
+ rb_global_variable(&big2str_table[i][0]);
+ for (j=1; j<16; j++) {
+ big2str_table[i][j] = Qfalse;
+ }
+ }
+}
+
+VALUE
rb_big2str(VALUE x, int base)
{
return rb_big2str0(x, base, Qtrue);
}
+VALUE
+rb_big2str_karatsuba(VALUE x, int base)
+{
+ return rb_big2str0_karatsuba(x, base, Qtrue);
+}
+
+VALUE
+rb_big2str_31312(VALUE x, int base)
+{
+ return rb_big2str0_31312(x, base, Qtrue);
+}
+
/*
* call-seq:
* big.to_s(base=10) => string
@@ -748,7 +1205,7 @@
*/
static VALUE
-rb_big_to_s(argc, argv, x)
+rb_big_to_s_orig(argc, argv, x)
int argc;
VALUE *argv;
VALUE x;
@@ -762,6 +1219,36 @@
return rb_big2str(x, base);
}
+static VALUE
+rb_big_to_s(argc, argv, x)
+ int argc;
+ VALUE *argv;
+ VALUE x;
+{
+ VALUE b;
+ int base;
+
+ rb_scan_args(argc, argv, "01", &b);
+ if (argc == 0) base = 10;
+ else base = NUM2INT(b);
+ return rb_big2str_karatsuba(x, base);
+}
+
+static VALUE
+rb_big_to_s_31312(argc, argv, x)
+ int argc;
+ VALUE *argv;
+ VALUE x;
+{
+ VALUE b;
+ int base;
+
+ rb_scan_args(argc, argv, "01", &b);
+ if (argc == 0) base = 10;
+ else base = NUM2INT(b);
+ return rb_big2str_31312(x, base);
+}
+
static unsigned long
big2ulong(x, type)
VALUE x;
@@ -2314,6 +2801,8 @@
{
rb_cBignum = rb_define_class("Bignum", rb_cInteger);
+ rb_define_method(rb_cBignum, "to_s_orig", rb_big_to_s_orig, -1);
+ rb_define_method(rb_cBignum, "to_s_31312", rb_big_to_s_31312, -1);
rb_define_method(rb_cBignum, "to_s", rb_big_to_s, -1);
rb_define_method(rb_cBignum, "coerce", rb_big_coerce, 1);
rb_define_method(rb_cBignum, "-@", rb_big_uminus, 0);
@@ -2344,4 +2833,6 @@
rb_define_method(rb_cBignum, "to_f", rb_big_to_f, 0);
rb_define_method(rb_cBignum, "abs", rb_big_abs, 0);
rb_define_method(rb_cBignum, "size", rb_big_size, 0);
+
+ init_big2str_table();
}
require 'benchmark'
$values = (1..100).to_a.collect{ rand(10**1024 - 1) }
def main
$values.each{|v| (2..36).each{|b| yield(v, b) }}
end
Benchmark.bmbm do |x|
x.report('original') do
main {|v, b| v.to_s_orig(b) }
end
x.report('ruby-dev:31312') do
main {|v, b| v.to_s_31312(b) }
end
x.report('ruby-dev:31323') do
main {|v, b| v.to_s(b) }
end
end