YoushouldhavereceivedcopiesoftheGNUGeneralPublicLicenseandthe GNULesserGeneralPublicLicensealongwiththeGNUMPLibrary.Ifnot,
see https://www.gnu.org/licenses/. */
/* See "Karatsuba Square Root", reference in gmp.texi. */
/* Use Newton iterations for approximating 1/sqrt(a) instead of sqrt(a), sincewecandotheformerwithoutdivision.Aspartofthelast
iteration convert from 1/sqrt(a) to sqrt(a). */
/* same as mpn_sqrtrem, but for size=2 and {np, 2} normalized
return cc such that {np, 2} = sp[0]^2 + cc*2^GMP_NUMB_BITS + rp[0] */ #if SQRTREM2_INPLACE #define CALL_SQRTREM2_INPLACE(sp,rp) mpn_sqrtrem2 (sp, rp) static mp_limb_t
mpn_sqrtrem2 (mp_ptr sp, mp_ptr rp)
{
mp_srcptr np = rp; #else #define CALL_SQRTREM2_INPLACE(sp,rp) mpn_sqrtrem2 (sp, rp, rp) static mp_limb_t
mpn_sqrtrem2 (mp_ptr sp, mp_ptr rp, mp_srcptr np)
{ #endif
mp_limb_t q, u, np0, sp0, rp0, q2; int cc;
ASSERT (np[1] >= GMP_NUMB_HIGHBIT / 2);
np0 = np[0];
sp0 = mpn_sqrtrem1 (rp, np[1]);
rp0 = rp[0]; /* rp0 <= 2*sp0 < 2^(Prec + 1) */
rp0 = (rp0 << (Prec - 1)) + (np0 >> (Prec + 1));
q = rp0 / sp0; /* q <= 2^Prec, if q = 2^Prec, reduce the overestimate. */
q -= q >> Prec; /* now we have q < 2^Prec */
u = rp0 - q * sp0; /* now we have (rp[0]<<Prec + np0>>Prec)/2 = q * sp0 + u */
sp0 = (sp0 << Prec) | q;
cc = u >> (Prec - 1);
rp0 = ((u << (Prec + 1)) & GMP_NUMB_MASK) + (np0 & ((CNST_LIMB (1) << (Prec + 1)) - 1)); /* subtract q * q from rp */
q2 = q * q;
cc -= rp0 < q2;
rp0 -= q2; if (cc < 0)
{
rp0 += sp0;
cc += rp0 < sp0;
--sp0;
rp0 += sp0;
cc += rp0 < sp0;
}
rp[0] = rp0;
sp[0] = sp0; return cc;
}
/* writes in {sp, n} the square root (rounded towards zero) of {np, 2n}, andin{np,n}thelownlimbsoftheremainder,returnsthehigh limboftheremainder(whichis0or1). Assumes{np,2n}isnormalized,i.e.np[2n-1]>=B/4 whereB=2^GMP_NUMB_BITS.
Needs a scratch of n/2+1 limbs. */ static mp_limb_t
mpn_dc_sqrtrem (mp_ptr sp, mp_ptr np, mp_size_t n, mp_limb_t approx, mp_ptr scratch)
{
mp_limb_t q; /* carry out of {sp, n} */ int c, b; /* carry out of remainder */
mp_size_t l, h;
/* writes in {sp, n} the square root (rounded towards zero) of {np, 2n-odd}, returnszeroiftheoperandwasaperfectsquare,oneotherwise. Assumes{np,2n-odd}*4^nshisnormalized,i.e.B>np[2n-1-odd]*4^nsh>=B/4 whereB=2^GMP_NUMB_BITS. THINK:Intheoddcase,threemore(dummy)limbsaretakenintoaccount, whennshismaximal,twolimbsarediscardedfromtheresultofthe
division. Too much? Is a single dummy limb enough? */ staticint
mpn_dc_sqrt (mp_ptr sp, mp_srcptr np, mp_size_t n, unsigned nsh, unsigned odd)
{
mp_limb_t q; /* carry out of {sp, n} */ int c; /* carry out of remainder */
mp_size_t l, h;
mp_ptr qp, tp, scratch;
TMP_DECL;
TMP_MARK;
high = np[nn - 1]; if (high & (GMP_NUMB_HIGHBIT | (GMP_NUMB_HIGHBIT / 2)))
c = 0; else
{
count_leading_zeros (c, high);
c -= GMP_NAIL_BITS;
c = c / 2; /* we have to shift left by 2c bits to normalize {np, nn} */
} if (nn == 1) { if (c == 0)
{
sp[0] = mpn_sqrtrem1 (&rl, high); if (rp != NULL)
rp[0] = rl;
} else
{
cc = mpn_sqrtrem1 (&rl, high << (2*c)) >> c;
sp[0] = cc; if (rp != NULL)
rp[0] = rl = high - cc*cc;
} return rl != 0;
} if (nn == 2) {
mp_limb_t tp [2]; if (rp == NULL) rp = tp; if (c == 0)
{ #if SQRTREM2_INPLACE
rp[1] = high;
rp[0] = np[0];
cc = CALL_SQRTREM2_INPLACE (sp, rp); #else
cc = mpn_sqrtrem2 (sp, rp, np); #endif
rp[1] = cc; return ((rp[0] | cc) != 0) + cc;
} else
{
rl = np[0];
rp[1] = (high << (2*c)) | (rl >> (GMP_NUMB_BITS - 2*c));
rp[0] = rl << (2*c);
CALL_SQRTREM2_INPLACE (sp, rp);
cc = sp[0] >>= c; /* c != 0, the highest bit of the root cc is 0. */
rp[0] = rl -= cc*cc; /* Computed modulo 2^GMP_LIMB_BITS, because it's smaller. */ return rl != 0;
}
}
tn = (nn + 1) / 2; /* 2*tn is the smallest even integer >= nn */
if ((rp == NULL) && (nn > 8)) return mpn_dc_sqrt (sp, np, tn, c, nn & 1);
TMP_MARK; if (((nn & 1) | c) != 0)
{
mp_limb_t s0[1], mask;
mp_ptr tp, scratch;
TMP_ALLOC_LIMBS_2 (tp, 2 * tn, scratch, tn / 2 + 1);
tp[0] = 0; /* needed only when 2*tn > nn, but saves a test */ if (c != 0)
mpn_lshift (tp + (nn & 1), np, nn, 2 * c); else
MPN_COPY (tp + (nn & 1), np, nn);
c += (nn & 1) ? GMP_NUMB_BITS / 2 : 0; /* c now represents k */
mask = (CNST_LIMB (1) << c) - 1;
rl = mpn_dc_sqrtrem (sp, tp, tn, (rp == NULL) ? mask - 1 : 0, scratch); /* We have 2^(2k)*N = S^2 + R where k = c + (2tn-nn)*GMP_NUMB_BITS/2,
thus 2^(2k)*N = (S-s0)^2 + 2*S*s0 - s0^2 + R where s0=S mod 2^k */
s0[0] = sp[0] & mask; /* S mod 2^k */
rl += mpn_addmul_1 (tp, sp, tn, 2 * s0[0]); /* R = R + 2*s0*S */
cc = mpn_submul_1 (tp, s0, 1, s0[0]);
rl -= (tn > 1) ? mpn_sub_1 (tp + 1, tp + 1, tn - 1, cc) : cc;
mpn_rshift (sp, sp, tn, c);
tp[tn] = rl; if (rp == NULL)
rp = tp;
c = c << 1; if (c < GMP_NUMB_BITS)
tn++; else
{
tp++;
c -= GMP_NUMB_BITS;
} if (c != 0)
mpn_rshift (rp, tp, tn, c); else
MPN_COPY_INCR (rp, tp, tn);
rn = tn;
} else
{ if (rp != np)
{ if (rp == NULL) /* nn <= 8 */
rp = TMP_SALLOC_LIMBS (nn);
MPN_COPY (rp, np, nn);
}
rn = tn + (rp[tn] = mpn_dc_sqrtrem (sp, rp, tn, 0, TMP_ALLOC_LIMBS(tn / 2 + 1)));
}
MPN_NORMALIZE (rp, rn);
TMP_FREE; return rn;
}
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.37Bemerkung:
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-09-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.