595
598
const char ruby_digitmap[] = "0123456789abcdefghijklmnopqrstuvwxyz";
600
static VALUE bigsqr(VALUE x);
601
static void bigdivmod(VALUE x, VALUE y, VALUE *divp, VALUE *modp);
603
#define POW2_P(x) (((x)&((x)-1))==0)
606
ones(register unsigned long x)
608
#if SIZEOF_ULONG == 8
609
# define MASK_55 0x5555555555555555UL
610
# define MASK_33 0x3333333333333333UL
611
# define MASK_0f 0x0f0f0f0f0f0f0f0fUL
613
# define MASK_55 0x55555555UL
614
# define MASK_33 0x33333333UL
615
# define MASK_0f 0x0f0f0f0fUL
617
x -= (x >> 1) & MASK_55;
618
x = ((x >> 2) & MASK_33) + (x & MASK_33);
619
x = ((x >> 4) + x) & MASK_0f;
622
#if SIZEOF_ULONG == 8
625
return (int)(x & 0x7f);
631
static inline unsigned long
632
next_pow2(register unsigned long x)
639
#if SIZEOF_ULONG == 8
646
floor_log2(register unsigned long x)
653
#if SIZEOF_ULONG == 8
656
return (int)ones(x) - 1;
660
ceil_log2(register unsigned long x)
662
return floor_log2(x) + !POW2_P(x);
665
#define LOG2_KARATSUBA_DIGITS 7
666
#define KARATSUBA_DIGITS (1L<<LOG2_KARATSUBA_DIGITS)
667
#define MAX_BIG2STR_TABLE_ENTRIES 64
669
static VALUE big2str_power_cache[35][MAX_BIG2STR_TABLE_ENTRIES];
672
power_cache_init(void)
675
for (i = 0; i < 35; ++i) {
676
big2str_power_cache[i][0] =
677
rb_big_pow(rb_int2big(i+2), INT2FIX(KARATSUBA_DIGITS));
678
rb_global_variable(&big2str_power_cache[i][0]);
679
for (j = 1; j < MAX_BIG2STR_TABLE_ENTRIES; ++j) {
680
big2str_power_cache[i][j] = Qnil;
686
power_cache_get_power0(int base, int i)
688
if (NIL_P(big2str_power_cache[base - 2][i])) {
689
big2str_power_cache[base - 2][i] =
690
bigsqr(power_cache_get_power0(base, i - 1));
691
rb_global_variable(&big2str_power_cache[base - 2][i]);
693
return big2str_power_cache[base - 2][i];
697
power_cache_get_power(int base, long n1, long* m1)
702
if (n1 <= KARATSUBA_DIGITS)
703
rb_bug("n1 > KARATSUBA_DIGITS");
706
if (m1) *m1 = 1 << m;
707
i = m - LOG2_KARATSUBA_DIGITS;
708
if (i >= MAX_BIG2STR_TABLE_ENTRIES)
709
i = MAX_BIG2STR_TABLE_ENTRIES - 1;
710
t = power_cache_get_power0(base, i);
712
j = KARATSUBA_DIGITS*(1 << i);
720
/* big2str_muraken_find_n1
722
* Let a natural number x is given by:
723
* x = 2^0 * x_0 + 2^1 * x_1 + ... + 2^(B*n_0 - 1) * x_{B*n_0 - 1},
724
* where B is BITSPERDIG (i.e. BDIGITS*CHAR_BIT) and n_0 is
727
* Now, we assume n_1 = min_n \{ n | 2^(B*n_0/2) <= b_1^(n_1) \}, so
728
* it is realized that 2^(B*n_0) <= {b_1}^{2*n_1}, where b_1 is a
729
* given radix number. And then, we have n_1 <= (B*n_0) /
730
* (2*log_2(b_1)), therefore n_1 is given by ceil((B*n_0) /
734
big2str_find_n1(VALUE x, int base)
736
static const double log_2[] = {
737
1.0, 1.58496250072116, 2.0,
738
2.32192809488736, 2.584962500721, 2.58496250072116,
739
2.8073549220576, 3.0, 3.16992500144231,
740
3.32192809488736, 3.4594316186373, 3.58496250072116,
741
3.70043971814109, 3.8073549220576, 3.90689059560852,
742
4.0, 4.08746284125034, 4.16992500144231,
743
4.24792751344359, 4.32192809488736, 4.39231742277876,
744
4.4594316186373, 4.52356195605701, 4.58496250072116,
745
4.64385618977472, 4.70043971814109, 4.75488750216347,
746
4.8073549220576, 4.85798099512757, 4.90689059560852,
747
4.95419631038688, 5.0, 5.04439411935845,
748
5.08746284125034, 5.12928301694497, 5.16992500144231
752
if (base < 2 && 36 < base)
753
rb_bug("illegal radix %d", base);
756
bits = (SIZEOF_LONG*CHAR_BIT - 1)/2 + 1;
758
else if (BIGZEROP(x)) {
762
bits = BITSPERDIG*RBIGNUM(x)->len;
765
return (long)ceil(bits/(2*log_2[base - 2]));
769
big2str_orig(VALUE x, int base, char* ptr, long len, long hbase, int trim)
771
long i = RBIGNUM(x)->len, j = len;
772
BDIGIT* ds = BDIGITS(x);
778
while (k--) { /* x / hbase */
779
num = BIGUP(num) + ds[k];
780
ds[k] = (BDIGIT)(num / hbase);
783
if (trim && ds[i-1] == 0) i--;
786
ptr[--j] = ruby_digitmap[num % base];
788
if (!trim && j <= 0) break;
789
if (trim && i == 0 && num == 0) break;
793
while (ptr[j] == '0') j++;
794
MEMMOVE(ptr, ptr + j, char, len - j);
801
big2str_karatsuba(VALUE x, int base, char* ptr,
802
long n1, long len, long hbase, int trim)
808
VALUE str = rb_fix2str(x, base);
809
char* str_ptr = RSTRING_PTR(str);
810
long str_len = RSTRING_LEN(str);
812
if (FIX2INT(x) == 0) return 0;
813
MEMCPY(ptr, str_ptr, char, str_len);
817
memset(ptr, '0', len - str_len);
818
MEMCPY(ptr + len - str_len, str_ptr, char, str_len);
825
memset(ptr, '0', len);
830
if (n1 <= KARATSUBA_DIGITS) {
831
return big2str_orig(x, base, ptr, len, hbase, trim);
834
b = power_cache_get_power(base, n1, &m1);
835
bigdivmod(x, b, &q, &r);
836
lh = big2str_karatsuba(q, base, ptr, (len - m1)/2,
837
len - m1, hbase, trim);
838
ll = big2str_karatsuba(r, base, ptr + lh, m1/2,
839
m1, hbase, !lh && trim);
597
845
rb_big2str0(VALUE x, int base, int trim)
605
852
if (FIXNUM_P(x)) {
606
return rb_fix2str(x, base);
853
return rb_fix2str(x, base);
608
855
if (BIGZEROP(x)) {
609
return rb_str_new2("0");
612
j = SIZEOF_BDIGITS*CHAR_BIT*i;
616
j = j * 53L / 84 + 1;
618
case 4: case 5: case 6: case 7:
624
case 10: case 11: case 12: case 13: case 14: case 15:
625
j = j * 28L / 93 + 1;
627
case 16: case 17: case 18: case 19: case 20: case 21:
628
case 22: case 23: case 24: case 25: case 26: case 27:
629
case 28: case 29: case 30: case 31:
632
case 32: case 33: case 34: case 35: case 36:
636
rb_raise(rb_eArgError, "illegal radix %d", base);
639
j++; /* space for sign */
856
return rb_str_new2("0");
859
if (base < 2 && 36 < base)
860
rb_raise(rb_eArgError, "illegal radix %d", base);
862
n1 = big2str_find_n1(x, base);
863
ss = rb_str_new(0, 2*n1 + 1); /* plus one for sign */
864
ptr = RSTRING_PTR(ss);
865
ptr[0] = RBIGNUM(x)->sign ? '+' : '-';
642
868
#if SIZEOF_BDIGITS > 2
648
ss = rb_str_new(0, j+1);
651
s[0] = RBIGNUM(x)->sign ? '+' : '-';
657
num = BIGUP(num) + ds[k];
658
ds[k] = (BDIGIT)(num / hbase);
661
if (trim && ds[i-1] == 0) i--;
664
s[--j] = ruby_digitmap[num % base];
666
if (!trim && j < 1) break;
667
if (trim && i == 0 && num == 0) break;
670
if (trim) {while (s[j] == '0') j++;}
671
i = RSTRING_LEN(ss) - j;
672
if (RBIGNUM(x)->sign) {
871
off = !(trim && RBIGNUM(x)->sign); /* erase plus sign if trim */
872
xx = rb_big_clone(x);
873
RBIGNUM(xx)->sign = 1;
874
if (n1 <= KARATSUBA_DIGITS) {
875
len = off + big2str_orig(xx, base, ptr + off, 2*n1, hbase, trim);
677
memmove(s+1, s+j, i);
878
len = off + big2str_karatsuba(xx, base, ptr + off, n1,
679
rb_str_set_len(ss, i);
883
rb_str_resize(ss, len);