mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* bignum.c (integer_unpack_num_bdigits_small: Extracted from
rb_integer_unpack. (integer_unpack_num_bdigits_generic): Ditto. (integer_unpack_num_bdigits_bytes): New function. (rb_integer_unpack): Use above functions. Return a Bignum for INTEGER_PACK_FORCE_BIGNUM evenwhen the result is zero. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@41202 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
192085bad3
commit
8c239f35de
2 changed files with 99 additions and 24 deletions
10
ChangeLog
10
ChangeLog
|
@ -1,3 +1,13 @@
|
||||||
|
Mon Jun 10 12:10:06 2013 Tanaka Akira <akr@fsij.org>
|
||||||
|
|
||||||
|
* bignum.c (integer_unpack_num_bdigits_small: Extracted from
|
||||||
|
rb_integer_unpack.
|
||||||
|
(integer_unpack_num_bdigits_generic): Ditto.
|
||||||
|
(integer_unpack_num_bdigits_bytes): New function.
|
||||||
|
(rb_integer_unpack): Use above functions.
|
||||||
|
Return a Bignum for INTEGER_PACK_FORCE_BIGNUM evenwhen the result
|
||||||
|
is zero.
|
||||||
|
|
||||||
Mon Jun 10 05:38:23 2013 Tanaka Akira <akr@fsij.org>
|
Mon Jun 10 05:38:23 2013 Tanaka Akira <akr@fsij.org>
|
||||||
|
|
||||||
* bignum.c (absint_numwords_small): New function.
|
* bignum.c (absint_numwords_small): New function.
|
||||||
|
|
111
bignum.c
111
bignum.c
|
@ -982,6 +982,59 @@ rb_integer_pack(VALUE val, int *signp, void *words, size_t numwords, size_t word
|
||||||
#undef TAKE_LOWBITS
|
#undef TAKE_LOWBITS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
integer_unpack_num_bdigits_small(size_t numwords, size_t wordsize, size_t nails)
|
||||||
|
{
|
||||||
|
size_t num_bits;
|
||||||
|
num_bits = (wordsize * CHAR_BIT - nails) * numwords;
|
||||||
|
return (num_bits + SIZEOF_BDIGITS*CHAR_BIT - 1) / (SIZEOF_BDIGITS*CHAR_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
integer_unpack_num_bdigits_bytes(size_t numwords, size_t wordsize)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* num_bits = wordsize * CHAR_BIT * numwords
|
||||||
|
*
|
||||||
|
* num_bdigits = (num_bits + SIZEOF_BDIGITS*CHAR_BIT - 1) / (SIZEOF_BDIGITS*CHAR_BIT)
|
||||||
|
* = (wordsize * CHAR_BIT * numwords + SIZEOF_BDIGITS*CHAR_BIT - 1) / (SIZEOF_BDIGITS*CHAR_BIT)
|
||||||
|
* = ((wordsize * numwords + SIZEOF_BDIGITS)*CHAR_BIT - 1) / (SIZEOF_BDIGITS*CHAR_BIT)
|
||||||
|
*
|
||||||
|
* q, r = (wordsize * numwords).divmod(SIZEOF_BDIGITS)
|
||||||
|
* q * SIZEOF_BDIGITS + r = wordsize * numwords
|
||||||
|
*
|
||||||
|
* num_bdigits = ((q * SIZEOF_BDIGITS + r + SIZEOF_BDIGITS)*CHAR_BIT - 1) / (SIZEOF_BDIGITS*CHAR_BIT)
|
||||||
|
* = (q * SIZEOF_BDIGITS * CHAR_BIT + r * CHAR_BIT + SIZEOF_BDIGITS * CHAR_BIT - 1) / (SIZEOF_BDIGITS*CHAR_BIT)
|
||||||
|
* = q + (r * CHAR_BIT + SIZEOF_BDIGITS * CHAR_BIT - 1) / (SIZEOF_BDIGITS*CHAR_BIT)
|
||||||
|
*/
|
||||||
|
size_t t, q, r;
|
||||||
|
t = wordsize * numwords;
|
||||||
|
q = t / SIZEOF_BDIGITS;
|
||||||
|
r = t % SIZEOF_BDIGITS;
|
||||||
|
return q + (r * CHAR_BIT + SIZEOF_BDIGITS * CHAR_BIT - 1) / (SIZEOF_BDIGITS*CHAR_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
integer_unpack_num_bdigits_generic(size_t numwords, size_t wordsize, size_t nails)
|
||||||
|
{
|
||||||
|
VALUE num_bits_v, num_bdigits_v;
|
||||||
|
|
||||||
|
/* num_bits = (wordsize * CHAR_BIT - nails) * numwords */
|
||||||
|
num_bits_v = SIZET2NUM(wordsize);
|
||||||
|
num_bits_v = rb_funcall(num_bits_v, '*', 1, LONG2FIX(CHAR_BIT));
|
||||||
|
num_bits_v = rb_funcall(num_bits_v, '-', 1, SIZET2NUM(nails));
|
||||||
|
num_bits_v = rb_funcall(num_bits_v, '*', 1, SIZET2NUM(numwords));
|
||||||
|
|
||||||
|
if (num_bits_v == LONG2FIX(0))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* num_bdigits = (num_bits + SIZEOF_BDIGITS*CHAR_BIT - 1) / (SIZEOF_BDIGITS*CHAR_BIT) */
|
||||||
|
num_bdigits_v = rb_funcall(num_bits_v, '+', 1, LONG2FIX(SIZEOF_BDIGITS*CHAR_BIT-1));
|
||||||
|
num_bdigits_v = rb_funcall(num_bdigits_v, '/', 1, LONG2FIX(SIZEOF_BDIGITS*CHAR_BIT));
|
||||||
|
|
||||||
|
return NUM2SIZET(num_bdigits_v);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
integer_unpack_push_bits(int data, int numbits, BDIGIT_DBL *ddp, int *numbits_in_dd_p, BDIGIT **dpp)
|
integer_unpack_push_bits(int data, int numbits, BDIGIT_DBL *ddp, int *numbits_in_dd_p, BDIGIT **dpp)
|
||||||
{
|
{
|
||||||
|
@ -1012,6 +1065,7 @@ rb_integer_unpack(int sign, const void *words, size_t numwords, size_t wordsize,
|
||||||
{
|
{
|
||||||
VALUE result;
|
VALUE result;
|
||||||
const unsigned char *buf = words;
|
const unsigned char *buf = words;
|
||||||
|
size_t num_bdigits;
|
||||||
|
|
||||||
BDIGIT *dp;
|
BDIGIT *dp;
|
||||||
BDIGIT *de;
|
BDIGIT *de;
|
||||||
|
@ -1035,33 +1089,44 @@ rb_integer_unpack(int sign, const void *words, size_t numwords, size_t wordsize,
|
||||||
rb_raise(rb_eArgError, "unexpected sign: %d", sign);
|
rb_raise(rb_eArgError, "unexpected sign: %d", sign);
|
||||||
|
|
||||||
if (numwords <= (SIZE_MAX - (SIZEOF_BDIGITS*CHAR_BIT-1)) / CHAR_BIT / wordsize) {
|
if (numwords <= (SIZE_MAX - (SIZEOF_BDIGITS*CHAR_BIT-1)) / CHAR_BIT / wordsize) {
|
||||||
size_t num_bits, num_bdigits;
|
num_bdigits = integer_unpack_num_bdigits_small(numwords, wordsize, nails);
|
||||||
num_bits = (wordsize * CHAR_BIT - nails) * numwords;
|
#if 0
|
||||||
if (num_bits == 0)
|
{
|
||||||
|
static int first = 1;
|
||||||
|
if (first)
|
||||||
|
first = 0;
|
||||||
|
else {
|
||||||
|
size_t num_bdigits1 = integer_unpack_num_bdigits_generic(numwords, wordsize, nails);
|
||||||
|
assert(num_bdigits == num_bdigits1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if (nails == 0) {
|
||||||
|
num_bdigits = integer_unpack_num_bdigits_bytes(numwords, wordsize);
|
||||||
|
#if 0
|
||||||
|
{
|
||||||
|
static int first = 1;
|
||||||
|
if (first)
|
||||||
|
first = 0;
|
||||||
|
else {
|
||||||
|
size_t num_bdigits1 = integer_unpack_num_bdigits_generic(numwords, wordsize, nails);
|
||||||
|
assert(num_bdigits == num_bdigits1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
num_bdigits = integer_unpack_num_bdigits_generic(numwords, wordsize, nails);
|
||||||
|
}
|
||||||
|
if (num_bdigits == 0) {
|
||||||
|
if (flags & INTEGER_PACK_FORCE_BIGNUM)
|
||||||
|
return rb_int2big(0);
|
||||||
return LONG2FIX(0);
|
return LONG2FIX(0);
|
||||||
num_bdigits = (num_bits + SIZEOF_BDIGITS*CHAR_BIT - 1) / (SIZEOF_BDIGITS*CHAR_BIT);
|
}
|
||||||
if (LONG_MAX < num_bdigits)
|
if (LONG_MAX < num_bdigits)
|
||||||
rb_raise(rb_eArgError, "too big to unpack as an integer");
|
rb_raise(rb_eArgError, "too big to unpack as an integer");
|
||||||
result = bignew((long)num_bdigits, 0 <= sign);
|
result = bignew((long)num_bdigits, 0 <= sign);
|
||||||
}
|
|
||||||
else {
|
|
||||||
VALUE num_bits, num_bdigits;
|
|
||||||
|
|
||||||
/* num_bits = (wordsize * CHAR_BIT - nails) * numwords */
|
|
||||||
num_bits = SIZET2NUM(wordsize);
|
|
||||||
num_bits = rb_funcall(num_bits, '*', 1, LONG2FIX(CHAR_BIT));
|
|
||||||
num_bits = rb_funcall(num_bits, '-', 1, SIZET2NUM(nails));
|
|
||||||
num_bits = rb_funcall(num_bits, '*', 1, SIZET2NUM(numwords));
|
|
||||||
|
|
||||||
if (num_bits == LONG2FIX(0))
|
|
||||||
return LONG2FIX(0);
|
|
||||||
|
|
||||||
/* num_bdigits = (num_bits + SIZEOF_BDIGITS*CHAR_BIT - 1) / (SIZEOF_BDIGITS*CHAR_BIT) */
|
|
||||||
num_bdigits = rb_funcall(num_bits, '+', 1, LONG2FIX(SIZEOF_BDIGITS*CHAR_BIT-1));
|
|
||||||
num_bdigits = rb_funcall(num_bdigits, '/', 1, LONG2FIX(SIZEOF_BDIGITS*CHAR_BIT));
|
|
||||||
|
|
||||||
result = bignew(NUM2LONG(num_bdigits), 0 <= sign);
|
|
||||||
}
|
|
||||||
|
|
||||||
dp = BDIGITS(result);
|
dp = BDIGITS(result);
|
||||||
de = dp + RBIGNUM_LEN(result);
|
de = dp + RBIGNUM_LEN(result);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue