static long ZZ_remove(struct ZZ &dest, const struct ZZ &src, const struct ZZ &f) { // Based on the code for mpz_remove ZZ fpow[40]; // inexaustible...until year 2020 or so ZZ x, rem; long pwr; int p; if (compare(f, 1) <= 0 && compare(f, -1) >= 0) Error("Division by zero"); if (compare(src, 0) == 0) { if (src != dest) dest = src; return 0; } if (compare(f, 2) == 0) { dest = src; return MakeOdd(dest); } /* We could perhaps compute mpz_scan1(src,0)/mpz_scan1(f,0). It is an upper bound of the result we're seeking. We could also shift down the operands so that they become odd, to make intermediate values smaller. */ pwr = 0; fpow[0] = ZZ(f); dest = src; rem = ZZ(); x = ZZ(); /* Divide by f, f^2, ..., f^(2^k) until we get a remainder for f^(2^k). */ for (p = 0;;p++) { DivRem(x, rem, dest, fpow[p]); if (compare(rem, 0) != 0) break; fpow[p+1] = ZZ(); NTL::mul(fpow[p+1], fpow[p], fpow[p]); dest = x; } pwr = (1 << p) - 1; /* Divide by f^(2^(k-1)), f^(2^(k-2)), ..., f for all divisors that give a zero remainder. */ while (--p >= 0) { DivRem(x, rem, dest, fpow[p]); if (compare(rem, 0) == 0) { pwr += 1 << p; dest = x; } } return pwr; }
static void normalize1(RR& z, const ZZ& y_x, long y_e, long prec, long residual) { long len = NumBits(y_x); if (len > prec) { long correction = ZZ_RoundCorrection(y_x, len - prec, residual); RightShift(z.x, y_x, len - prec); if (correction) add(z.x, z.x, correction); z.e = y_e + len - prec; } else if (len == 0) { clear(z.x); z.e = 0; } else { z.x = y_x; z.e = y_e; } if (!IsOdd(z.x)) z.e += MakeOdd(z.x); if (z.e >= NTL_OVFBND) ResourceError("RR: overflow"); if (z.e <= -NTL_OVFBND) ResourceError("RR: underflow"); }
static void RowTransform2(vec_ZZ& A, vec_ZZ& B, const ZZ& MU1) // x = x + y*MU { NTL_ZZRegister(T); NTL_ZZRegister(MU); long k; long n = A.length(); long i; MU = MU1; if (MU == 1) { for (i = 1; i <= n; i++) add(A(i), A(i), B(i)); return; } if (MU == -1) { for (i = 1; i <= n; i++) sub(A(i), A(i), B(i)); return; } if (MU == 0) return; if (NumTwos(MU) >= NTL_ZZ_NBITS) k = MakeOdd(MU); else k = 0; if (MU.WideSinglePrecision()) { long mu1; conv(mu1, MU); for (i = 1; i <= n; i++) { mul(T, B(i), mu1); if (k > 0) LeftShift(T, T, k); add(A(i), A(i), T); } } else { for (i = 1; i <= n; i++) { mul(T, B(i), MU); if (k > 0) LeftShift(T, T, k); add(A(i), A(i), T); } } }
/* Quickly find factor of n in the case where n is a prime power (and not * a power of 2). n>2, odd. Returns q, a factor of n, or 1 in case of * failure. */ void PrimePowerTest(ZZ& q, const ZZ& n) { // n-1 == 2^k * m, m odd ZZ n1,m; sub(n1,n,1); m=n1; long k = MakeOdd(m); set(q); ZZ z; conv(z,2); PowerMod(z,z,m,n); do { if (IsOne(z) || z==n1) return; SqrMod(z,z,n); } while (--k>0); if (IsOne(z)) return; z*=2; z-=2; GCD(q,z,n); if (q==0 || q==n) set(q); }
NTL_START_IMPL static void RowTransform(vec_ZZ& A, vec_ZZ& B, const ZZ& MU1) // x = x - y*MU { static ZZ T, MU; long k; long n = A.length(); long i; MU = MU1; if (MU == 1) { for (i = 1; i <= n; i++) sub(A(i), A(i), B(i)); return; } if (MU == -1) { for (i = 1; i <= n; i++) add(A(i), A(i), B(i)); return; } if (MU == 0) return; if (NumTwos(MU) >= NTL_ZZ_NBITS) k = MakeOdd(MU); else k = 0; if (MU.WideSinglePrecision()) { long mu1; conv(mu1, MU); if (k > 0) { for (i = 1; i <= n; i++) { mul(T, B(i), mu1); LeftShift(T, T, k); sub(A(i), A(i), T); } } else { for (i = 1; i <= n; i++) { MulSubFrom(A(i), B(i), mu1); } } } else { for (i = 1; i <= n; i++) { mul(T, B(i), MU); if (k > 0) LeftShift(T, T, k); sub(A(i), A(i), T); } } }