mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
extract initial sqrt estimation [Feature #13219]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@57708 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
a0acd82f2a
commit
a67c94cf40
1 changed files with 28 additions and 18 deletions
46
bignum.c
46
bignum.c
|
@ -6768,6 +6768,32 @@ BDIGIT rb_bdigit_dbl_isqrt(BDIGIT_DBL);
|
||||||
# define rb_bdigit_dbl_isqrt(x) (BDIGIT)rb_ulong_isqrt(x)
|
# define rb_bdigit_dbl_isqrt(x) (BDIGIT)rb_ulong_isqrt(x)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static BDIGIT *
|
||||||
|
estimate_initial_sqrt(VALUE *xp, const size_t xn, const BDIGIT *nds, size_t len)
|
||||||
|
{
|
||||||
|
const int zbits = nlz(nds[len-1]);
|
||||||
|
const int shift_bits = (len&1 ? BITSPERDIG/2 : BITSPERDIG) - (zbits+1)/2 + 1;
|
||||||
|
VALUE x = bignew_1(0, xn, 1); /* division may release the GVL */
|
||||||
|
BDIGIT *xds = BDIGITS(x);
|
||||||
|
|
||||||
|
*xp = x;
|
||||||
|
/* x = (n >> (b/2+1)) */
|
||||||
|
if (shift_bits == BITSPERDIG) {
|
||||||
|
MEMCPY(xds, nds+len-xn, BDIGIT, xn);
|
||||||
|
}
|
||||||
|
else if (shift_bits > BITSPERDIG) {
|
||||||
|
bary_small_rshift(xds, nds+len-xn, xn, shift_bits-BITSPERDIG, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bary_small_rshift(xds, nds+len-xn-1, xn, shift_bits, nds[len-1]);
|
||||||
|
}
|
||||||
|
/* x |= (1 << (b-1)/2) */
|
||||||
|
xds[xn-1] |= (BDIGIT)1u <<
|
||||||
|
((len&1 ? 0 : BITSPERDIG/2) + (BITSPERDIG-zbits-1)/2);
|
||||||
|
|
||||||
|
return xds;
|
||||||
|
}
|
||||||
|
|
||||||
VALUE
|
VALUE
|
||||||
rb_big_isqrt(VALUE n)
|
rb_big_isqrt(VALUE n)
|
||||||
{
|
{
|
||||||
|
@ -6783,25 +6809,9 @@ rb_big_isqrt(VALUE n)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int zbits = nlz(nds[len-1]);
|
|
||||||
int shift_bits = (len&1 ? BITSPERDIG/2 : BITSPERDIG) - (zbits+1)/2 + 1;
|
|
||||||
size_t tn = (len+1) / 2, xn = tn;
|
size_t tn = (len+1) / 2, xn = tn;
|
||||||
VALUE t, x = bignew_1(0, xn, 1); /* division may release the GVL */
|
VALUE t, x;
|
||||||
BDIGIT *tds, *xds = BDIGITS(x);
|
BDIGIT *tds, *xds = estimate_initial_sqrt(&x, xn, nds, len);
|
||||||
|
|
||||||
/* x = (n >> (b/2+1)) */
|
|
||||||
if (shift_bits == BITSPERDIG) {
|
|
||||||
MEMCPY(xds, nds+tn, BDIGIT, xn);
|
|
||||||
}
|
|
||||||
else if (shift_bits > BITSPERDIG) {
|
|
||||||
bary_small_rshift(xds, nds+len-xn, xn, shift_bits-BITSPERDIG, 0);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
bary_small_rshift(xds, nds+len-xn-1, xn, shift_bits, nds[len-1]);
|
|
||||||
}
|
|
||||||
/* x |= (1 << (b-1)/2) */
|
|
||||||
xds[xn-1] |= (BDIGIT)1u <<
|
|
||||||
((len&1 ? 0 : BITSPERDIG/2) + (BITSPERDIG-zbits-1)/2);
|
|
||||||
|
|
||||||
/* t = n/x */
|
/* t = n/x */
|
||||||
tn += BIGDIVREM_EXTRA_WORDS;
|
tn += BIGDIVREM_EXTRA_WORDS;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue