summaryrefslogtreecommitdiff
path: root/bignum.c
diff options
context:
space:
mode:
authorakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-08-01 10:19:23 +0000
committerakr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-08-01 10:19:23 +0000
commit0ade4f39fd94b8294c66fb706f22f425f1e833c8 (patch)
treef25d602afd00171387f048bfb7881310ff74095e /bignum.c
parent9037b25dde0c9ef932b9cbc5eb65aafe0cf9cb8a (diff)
* bignum.c (rb_big2str1): Remove non-trim mode.
(rb_big2str0): Non-trim mode implemented here. (big2str_find_n1): Change the result type to long again. (big2str_base_powerof2): Don't take arguments: len and trim. (rb_big2str): Follow above change. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@42305 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'bignum.c')
-rw-r--r--bignum.c69
1 files changed, 44 insertions, 25 deletions
diff --git a/bignum.c b/bignum.c
index 2b56e1ce51..3bb77ace64 100644
--- a/bignum.c
+++ b/bignum.c
@@ -4160,7 +4160,10 @@ power_cache_get_power(int base, int power_level, size_t *numdigits_ret)
return big2str_power_cache[base - 2][power_level];
}
-/* big2str_muraken_find_n1
+/*
+ * deprecated. (used only from deprecated rb_big2str0)
+ *
+ * big2str_muraken_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},
@@ -4173,7 +4176,7 @@ power_cache_get_power(int base, int power_level, size_t *numdigits_ret)
* (2*log_2(b_1)), therefore n_1 is given by ceil((B*n_0) /
* (2*log_2(b_1))).
*/
-static size_t
+static long
big2str_find_n1(VALUE x, int base)
{
static const double log_2[] = {
@@ -4313,14 +4316,14 @@ big2str_karatsuba(struct big2str_struct *b2s, VALUE x,
}
static VALUE
-big2str_base_powerof2(VALUE x, size_t len, int base, int trim)
+big2str_base_powerof2(VALUE x, int base)
{
int word_numbits = ffs(base) - 1;
size_t numwords;
VALUE result;
char *ptr;
- numwords = trim ? rb_absint_numwords(x, word_numbits, NULL) : len;
- if (RBIGNUM_NEGATIVE_P(x) || !trim) {
+ numwords = rb_absint_numwords(x, word_numbits, NULL);
+ if (RBIGNUM_NEGATIVE_P(x)) {
if (LONG_MAX-1 < numwords)
rb_raise(rb_eArgError, "too big number");
result = rb_usascii_str_new(0, 1+numwords);
@@ -4344,10 +4347,10 @@ big2str_base_powerof2(VALUE x, size_t len, int base, int trim)
}
static VALUE
-rb_big2str1(VALUE x, int base, int trim)
+rb_big2str1(VALUE x, int base)
{
VALUE xx;
- size_t n2, len;
+ size_t len;
struct big2str_struct b2s_data;
int power_level;
VALUE power;
@@ -4362,11 +4365,9 @@ rb_big2str1(VALUE x, int base, int trim)
if (base < 2 || 36 < base)
rb_raise(rb_eArgError, "invalid radix %d", base);
- n2 = big2str_find_n1(x, base);
-
if (POW2_P(base)) {
/* base == 2 || base == 4 || base == 8 || base == 16 || base == 32 */
- return big2str_base_powerof2(x, n2, base, trim);
+ return big2str_base_powerof2(x, base);
}
power_level = 0;
@@ -4392,19 +4393,9 @@ rb_big2str1(VALUE x, int base, int trim)
b2s_data.hbase = maxpow_in_bdigit(base, &b2s_data.hbase_numdigits);
b2s_data.hbase2 = maxpow_in_bdigit_dbl(base, &b2s_data.hbase2_numdigits);
- if (trim) {
- b2s_data.result = Qnil;
- b2s_data.ptr = NULL;
- len = 0;
- }
- else {
- len = n2;
- if (LONG_MAX-1 < n2)
- rb_raise(rb_eArgError, "too big number");
- b2s_data.result = rb_usascii_str_new(0, (long)(n2 + 1)); /* plus one for sign */
- b2s_data.ptr = RSTRING_PTR(b2s_data.result);
- *b2s_data.ptr++ = b2s_data.negative ? '-' : '+';
- }
+ b2s_data.result = Qnil;
+ b2s_data.ptr = NULL;
+ len = 0;
xx = rb_big_clone(x);
RBIGNUM_SET_SIGN(xx, 1);
@@ -4426,13 +4417,41 @@ rb_big2str1(VALUE x, int base, int trim)
VALUE
rb_big2str0(VALUE x, int base, int trim)
{
- return rb_big2str1(x, base, trim);
+ VALUE str;
+ long oldlen;
+ long n2;
+
+ str = rb_big2str1(x, base);
+
+ if (trim || FIXNUM_P(x) || BIGZEROP(x))
+ return str;
+
+ oldlen = RSTRING_LEN(str);
+ if (oldlen && RSTRING_PTR(str)[0] != '-') {
+ rb_str_resize(str, oldlen+1);
+ MEMMOVE(RSTRING_PTR(str)+1, RSTRING_PTR(str), char, oldlen);
+ RSTRING_PTR(str)[0] = '+';
+ }
+
+ n2 = big2str_find_n1(x, base);
+
+ oldlen = RSTRING_LEN(str);
+ if (oldlen-1 < n2) {
+ long off = n2 - (oldlen-1);
+ rb_str_resize(str, n2+1);
+ MEMMOVE(RSTRING_PTR(str)+1+off, RSTRING_PTR(str)+1, char, oldlen-1);
+ memset(RSTRING_PTR(str)+1, '0', off);
+ }
+
+ RSTRING_PTR(str)[RSTRING_LEN(str)] = '\0';
+
+ return str;
}
VALUE
rb_big2str(VALUE x, int base)
{
- return rb_big2str1(x, base, 1);
+ return rb_big2str1(x, base);
}
/*