?? zz.cpp
字號:
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 *) NTL_MALLOC(NTL_PRIME_BND, 1, 0);
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 *) NTL_MALLOC(NTL_PRIME_BND, 1, 0);
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 must have nn >= 5
if (trunc_long(nn, 2) == 3) { // special case, n = 3 (mod 4)
ZZ n, a, e, z;
n = nn;
a = aa;
add(e, n, 1);
RightShift(e, e, 2);
PowerMod(z, a, e, n);
x = z;
return;
}
ZZ n, m;
int h, nlen;
n = nn;
nlen = NumBits(n);
sub(m, n, 1);
h = MakeOdd(m); // h >= 2
if (nlen > 50 && h < SqrRoot(nlen)) {
long i, j;
ZZ a, b, a_inv, c, r, m1, d;
a = aa;
InvMod(a_inv, a, n);
if (h == 2)
b = 2;
else {
do {
RandomBnd(b, n);
} while (Jacobi(b, n) != -1);
}
PowerMod(c, b, m, n);
add(m1, m, 1);
RightShift(m1, m1, 1);
PowerMod(r, a, m1, n);
for (i = h-2; i >= 0; i--) {
SqrMod(d, r, n);
MulMod(d, d, a_inv, n);
for (j = 0; j < i; j++)
SqrMod(d, d, n);
if (!IsOne(d))
MulMod(r, r, c, n);
SqrMod(c, c, n);
}
x = r;
return;
}
long i, k;
ZZ ma, t, u, v, e;
ZZ t1, t2, t3, t4;
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--) {
add(t2, u, v);
sqr(t3, t2); // t3 = (u+v)^2
sqr(t1, u);
sqr(t2, v);
sub(t3, t3, t1);
sub(t3, t3, t2); // t1 = u^2, t2 = v^2, t3 = 2*u*v
rem(t1, t1, n);
mul(t4, t1, t);
add(t4, t4, t3);
rem(u, t4, n);
mul(t4, t1, ma);
add(t4, t4, t2);
rem(v, t4, 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 cval;
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 (IsWhiteSpace(c)) {
i++;
c = s[i];
}
if (c == '-') {
sign = -1;
i++;
c = s[i];
}
else
sign = 1;
cval = CharToIntVal(c);
if (cval < 0 || cval > 9) Error("bad ZZ input");
ndigits = 0;
acc = 0;
while (cval >= 0 && cval <= 9) {
acc = acc*10 + cval;
ndigits++;
if (ndigits == iodigits) {
mul(a, a, ioradix);
add(a, a, acc);
ndigits = 0;
acc = 0;
}
i++;
c = s[i];
cval = CharToIntVal(c);
}
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;
}
// no overflow check --- result is computed correctly
// modulo word size
unsigned long res = 1;
unsigned long aa = a;
long i;
for (i = 0; i < e; i++)
res *= aa;
return to_long(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)); \
}
static
void 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.
*/
static
void 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 */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -