📄 zz.c
字号:
long r = DivRem(qq, a, b); if (r) return 0; q = qq; return 1;}long divide(const ZZ& a, long b){ if (!b) return IsZero(a); if (b == 1) { return 1; } long r = rem(a, b); return (r == 0);} long RandomPrime_long(long l, long NumTrials){ if (l <= 1 || l >= NTL_BITS_PER_LONG) Error("RandomPrime: length out of range"); long n; do { n = RandomLen_long(l); } while (!ProbPrime(n, NumTrials)); return n;}PrimeSeq::PrimeSeq(){ movesieve = 0; movesieve_mem = 0; pshift = -1; pindex = -1; exhausted = 0;}PrimeSeq::~PrimeSeq(){ if (movesieve_mem) free(movesieve_mem);}long PrimeSeq::next(){ if (exhausted) { return 0; } if (pshift < 0) { shift(0); return 2; } for (;;) { char *p = movesieve; long i = pindex; while ((++i) < NTL_PRIME_BND) { if (p[i]) { pindex = i; return pshift + 2 * i + 3; } } long newshift = pshift + 2*NTL_PRIME_BND; if (newshift > 2 * NTL_PRIME_BND * (2 * NTL_PRIME_BND + 1)) { /* end of the road */ exhausted = 1; return 0; } shift(newshift); }}static char *lowsieve = 0;void PrimeSeq::shift(long newshift){ long i; long j; long jstep; long jstart; long ibound; char *p; if (!lowsieve) start(); pindex = -1; exhausted = 0; if (newshift < 0) { pshift = -1; return; } if (newshift == pshift) return; pshift = newshift; if (pshift == 0) { movesieve = lowsieve; } else { if (!movesieve_mem) { movesieve_mem = (char *) malloc(NTL_PRIME_BND); if (!movesieve_mem) Error("out of memory in PrimeSeq"); } p = movesieve = movesieve_mem; for (i = 0; i < NTL_PRIME_BND; i++) p[i] = 1; jstep = 3; ibound = pshift + 2 * NTL_PRIME_BND + 1; for (i = 0; jstep * jstep <= ibound; i++) { if (lowsieve[i]) { if (!((jstart = (pshift + 2) / jstep + 1) & 1)) jstart++; if (jstart <= jstep) jstart = jstep; jstart = (jstart * jstep - pshift - 3) / 2; for (j = jstart; j < NTL_PRIME_BND; j += jstep) p[j] = 0; } jstep += 2; } }}void PrimeSeq::start(){ long i; long j; long jstep; long jstart; long ibnd; char *p; p = lowsieve = (char *) malloc(NTL_PRIME_BND); if (!p) Error("out of memory in PrimeSeq"); for (i = 0; i < NTL_PRIME_BND; i++) p[i] = 1; jstep = 1; jstart = -1; ibnd = (SqrRoot(2 * NTL_PRIME_BND + 1) - 3) / 2; for (i = 0; i <= ibnd; i++) { jstart += 2 * ((jstep += 2) - 1); if (p[i]) for (j = jstart; j < NTL_PRIME_BND; j += jstep) p[j] = 0; }}void PrimeSeq::reset(long b){ if (b > (2*NTL_PRIME_BND+1)*(2*NTL_PRIME_BND+1)) { exhausted = 1; return; } if (b <= 2) { shift(-1); return; } if ((b & 1) == 0) b++; shift(((b-3) / (2*NTL_PRIME_BND))* (2*NTL_PRIME_BND)); pindex = (b - pshift - 3)/2 - 1;} long Jacobi(const ZZ& aa, const ZZ& nn){ ZZ a, n; long t, k; long d; a = aa; n = nn; t = 1; while (a != 0) { k = MakeOdd(a); d = trunc_long(n, 3); if ((k & 1) && (d == 3 || d == 5)) t = -t; if (trunc_long(a, 2) == 3 && (d & 3) == 3) t = -t; swap(a, n); rem(a, a, n); } if (n == 1) return t; else return 0;}void SqrRootMod(ZZ& x, const ZZ& aa, const ZZ& nn){ if (aa == 0 || aa == 1) { x = aa; return; } // at this point, we msut have nn >= 5 long i, k; ZZ ma, n, t, u, v, e; ZZ t1, t2, t3; n = nn; NegateMod(ma, aa, n); // find t such that t^2 - 4*a is not a square MulMod(t1, ma, 4, n); do { RandomBnd(t, n); SqrMod(t2, t, n); AddMod(t2, t2, t1, n); } while (Jacobi(t2, n) != -1); // compute u*X + v = X^{(n+1)/2} mod f, where f = X^2 - t*X + a add(e, n, 1); RightShift(e, e, 1); u = 0; v = 1; k = NumBits(e); for (i = k - 1; i >= 0; i--) { SqrMod(t1, u, n); SqrMod(t2, v, n); MulMod(t3, u, v, n); MulMod(t3, t3, 2, n); MulMod(u, t1, t, n); AddMod(u, u, t3, n); MulMod(v, t1, ma, n); AddMod(v, v, t2, n); if (bit(e, i)) { MulMod(t1, u, t, n); AddMod(t1, t1, v, n); MulMod(v, u, ma, n); u = t1; } } x = v;}// Chinese Remaindering.//// This version in new to v3.7, and is significantly// simpler and faster than the previous version.//// This function takes as input g, a, G, p,// such that a > 0, 0 <= G < p, and gcd(a, p) = 1.// It computes a' = a*p and g' such that // * g' = g (mod a);// * g' = G (mod p);// * -a'/2 < g' <= a'/2.// It then sets g := g' and a := a', and returns 1 iff g has changed.//// Under normal use, the input value g satisfies -a/2 < g <= a/2;// however, this was not documented or enforced in earlier versions,// so to maintain backward compatability, no restrictions are placed// on g. This routine runs faster, though, if -a/2 < g <= a/2,// and the first thing the routine does is to make this condition// hold.//// Also, under normal use, both a and p are odd; however, the routine// will still work even if this is not so.//// The routine is based on the following simple fact.//// Let -a/2 < g <= a/2, and let h satisfy// * g + a h = G (mod p);// * -p/2 < h <= p/2.// Further, if p = 2*h and g > 0, set// g' := g - a h;// otherwise, set// g' := g + a h.// Then g' so defined satisfies the above requirements.//// It is trivial to see that g's satisfies the congruence conditions.// The only thing is to check that the "balancing" condition// -a'/2 < g' <= a'/2 also holds.long CRT(ZZ& gg, ZZ& a, long G, long p){ if (p >= NTL_SP_BOUND) { ZZ GG, pp; conv(GG, G); conv(pp, p); return CRT(gg, a, GG, pp); } long modified = 0; ZZ g; if (!CRTInRange(gg, a)) { modified = 1; ZZ a1; rem(g, gg, a); RightShift(a1, a, 1); if (g > a1) sub(g, g, a); } else g = gg; long p1; p1 = p >> 1; long a_inv; a_inv = rem(a, p); a_inv = InvMod(a_inv, p); long h; h = rem(g, p); h = SubMod(G, h, p); h = MulMod(h, a_inv, p); if (h > p1) h = h - p; if (h != 0) { modified = 1; ZZ ah; mul(ah, a, h); if (!(p & 1) && g > 0 && (h == p1)) sub(g, g, ah); else add(g, g, ah); } mul(a, a, p); gg = g; return modified;}long CRT(ZZ& gg, ZZ& a, const ZZ& G, const ZZ& p){ long modified = 0; ZZ g; if (!CRTInRange(gg, a)) { modified = 1; ZZ a1; rem(g, gg, a); RightShift(a1, a, 1); if (g > a1) sub(g, g, a); } else g = gg; ZZ p1; RightShift(p1, p, 1); ZZ a_inv; rem(a_inv, a, p); InvMod(a_inv, a_inv, p); ZZ h; rem(h, g, p); SubMod(h, G, h, p); MulMod(h, h, a_inv, p); if (h > p1) sub(h, h, p); if (h != 0) { modified = 1; ZZ ah; mul(ah, a, h); if (!IsOdd(p) && g > 0 && (h == p1)) sub(g, g, ah); else add(g, g, ah); } mul(a, a, p); gg = g; return modified;}void sub(ZZ& x, const ZZ& a, long b){ static ZZ B; conv(B, b); sub(x, a, B);}void sub(ZZ& x, long a, const ZZ& b){ static ZZ A; conv(A, a); sub(x, A, b);}void power2(ZZ& x, long e){ if (e < 0) Error("power2: negative exponent"); set(x); LeftShift(x, x, e);} void conv(ZZ& x, const char *s){ long c; long sign; long ndigits; long acc; long i = 0; static ZZ a; if (!s) Error("bad ZZ input"); if (!iodigits) InitZZIO(); a = 0; c = s[i]; while (c == ' ' || c == '\n' || c == '\t') { i++; c = s[i]; } if (c == '-') { sign = -1; i++; c = s[i]; } else sign = 1; if (c < '0' || c > '9') Error("bad ZZ input"); ndigits = 0; acc = 0; while (c >= '0' && c <= '9') { acc = acc*10 + c - '0'; ndigits++; if (ndigits == iodigits) { mul(a, a, ioradix); add(a, a, acc); ndigits = 0; acc = 0; } i++; c = s[i]; } if (ndigits != 0) { long mpy = 1; while (ndigits > 0) { mpy = mpy * 10; ndigits--; } mul(a, a, mpy); add(a, a, acc); } if (sign == -1) negate(a, a); x = a;}void bit_and(ZZ& x, const ZZ& a, long b){ static ZZ B; conv(B, b); bit_and(x, a, B);}void bit_or(ZZ& x, const ZZ& a, long b){ static ZZ B; conv(B, b); bit_or(x, a, B);}void bit_xor(ZZ& x, const ZZ& a, long b){ static ZZ B; conv(B, b); bit_xor(x, a, B);}long power_long(long a, long e){ if (e < 0) Error("power_long: negative exponent"); if (e == 0) return 1; if (a == 1) return 1; if (a == -1) { if (e & 1) return -1; else return 1; } long res = 1; long i; for (i = 0; i < e; i++) res *= a; return res;}// RANDOM NUMBER GENERATION// Idea for this PRNG. Iteratively hash seed using md5 // to get 256 bytes to initialize arc4.// Then use arc4 to get a pseudo-random byte stream.// I've taken care that the pseudo-random numbers generated by// the routines RandomBnd, RandomBits, and RandomLen // are completely platform independent.// I make use of the md5 compression function,// which I've modified to work on 64-bit machines/* * BEGIN RSA's md5 stuff * *//* ********************************************************************** ** md5.c ** ** RSA Data Security, Inc. MD5 Message Digest Algorithm ** ** Created: 2/17/90 RLR ** ** Revised: 1/91 SRD,AJ,BSK,JT Reference C Version ** ********************************************************************** *//* ********************************************************************** ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** ** ** ** License to copy and use this software is granted provided that ** ** it is identified as the "RSA Data Security, Inc. MD5 Message ** ** Digest Algorithm" in all material mentioning or referencing this ** ** software or this function. ** ** ** ** License is also granted to make and use derivative works ** ** provided that such works are identified as "derived from the RSA ** ** Data Security, Inc. MD5 Message Digest Algorithm" in all ** ** material mentioning or referencing the derived work. ** ** ** ** RSA Data Security, Inc. makes no representations concerning ** ** either the merchantability of this software or the suitability ** ** of this software for any particular purpose. It is provided "as ** ** is" without express or implied warranty of any kind. ** ** ** ** These notices must be retained in any copies of any part of this ** ** documentation and/or software. ** ********************************************************************** */#if (NTL_BITS_PER_LONG <= 32)#define TRUNC32(x) (x)#else#define TRUNC32(x) ((x) & ((1UL << 32)-1UL))#endif/* F, G and H are basic MD5 functions: selection, majority, parity */#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))#define H(x, y, z) ((x) ^ (y) ^ (z))#define I(x, y, z) (TRUNC32((y) ^ ((x) | (~z)))) /* ROTATE_LEFT rotates x left n bits */#define ROTATE_LEFT(x, n) (TRUNC32(((x) << (n)) | ((x) >> (32-(n)))))/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 *//* Rotation is separate from addition to prevent recomputation */#define FF(a, b, c, d, x, s, ac) \ {(a) = TRUNC32((a) + F((b), (c), (d)) + (x) + (ac)); \ (a) = ROTATE_LEFT((a), (s)); \ (a) = TRUNC32((a) + (b)); \ }#define GG(a, b, c, d, x, s, ac) \ {(a) = TRUNC32((a) + G((b), (c), (d)) + (x) + (ac)); \ (a) = ROTATE_LEFT((a), (s)); \ (a) = TRUNC32((a) + (b)); \ }#define HH(a, b, c, d, x, s, ac) \ {(a) = TRUNC32((a) + H((b), (c), (d)) + (x) + (ac)); \ (a) = ROTATE_LEFT((a), (s)); \ (a) = TRUNC32((a) + (b)); \ }#define II(a, b, c, d, x, s, ac) \ {(a) = TRUNC32((a) + I((b), (c), (d)) + (x) + (ac)); \ (a) = ROTATE_LEFT((a), (s)); \ (a) = TRUNC32((a) + (b)); \ }staticvoid MD5_default_IV(unsigned long *buf){ buf[0] = 0x67452301UL; buf[1] = 0xefcdab89UL; buf[2] = 0x98badcfeUL; buf[3] = 0x10325476UL;}/* Basic MD5 step. Transform buf based on in. */staticvoid MD5_compress(unsigned long *buf, unsigned long *in){ unsigned long a = buf[0], b = buf[1], c = buf[2], d = buf[3]; /* Round 1 */#define S11 7#define S12 12#define S13 17#define S14 22 FF ( a, b, c, d, in[ 0], S11, 3614090360UL); /* 1 */ FF ( d, a, b, c, in[ 1], S12, 3905402710UL); /* 2 */ FF ( c, d, a, b, in[ 2], S13, 606105819UL); /* 3 */ FF ( b, c, d, a, in[ 3], S14, 3250441966UL); /* 4 */ FF ( a, b, c, d, in[ 4], S11, 4118548399UL); /* 5 */ FF ( d, a, b, c, in[ 5], S12, 1200080426UL); /* 6 */ FF ( c, d, a, b, in[ 6], S13, 2821735955UL); /* 7 */ FF ( b, c, d, a, in[ 7], S14, 4249261313UL); /* 8 */ FF ( a, b, c, d, in[ 8], S11, 1770035416UL); /* 9 */ FF ( d, a, b, c, in[ 9], S12, 2336552879UL); /* 10 */ FF ( c, d, a, b, in[10], S13, 4294925233UL); /* 11 */ FF ( b, c, d, a, in[11], S14, 2304563134UL); /* 12 */ FF ( a, b, c, d, in[12], S11, 1804603682UL); /* 13 */ FF ( d, a, b, c, in[13], S12, 4254626195UL); /* 14 */ FF ( c, d, a, b, in[14], S13, 2792965006UL); /* 15 */ FF ( b, c, d, a, in[15], S14, 1236535329UL); /* 16 */ /* Round 2 */#define S21 5#define S22 9#define S23 14#define S24 20 GG ( a, b, c, d, in[ 1], S21, 4129170786UL); /* 17 */ GG ( d, a, b, c, in[ 6], S22, 3225465664UL); /* 18 */ GG ( c, d, a, b, in[11], S23, 643717713UL); /* 19 */ GG ( b, c, d, a, in[ 0], S24, 3921069994UL); /* 20 */ GG ( a, b, c, d, in[ 5], S21, 3593408605UL); /* 21 */ GG ( d, a, b, c, in[10], S22, 38016083UL); /* 22 */ GG ( c, d, a, b, in[15], S23, 3634488961UL); /* 23 */ GG ( b, c, d, a, in[ 4], S24, 3889429448UL); /* 24 */ GG ( a, b, c, d, in[ 9], S21, 568446438UL); /* 25 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -