diff options
Diffstat (limited to 'otherlibs/num/bignum/c')
-rw-r--r-- | otherlibs/num/bignum/c/KerN.c | 932 | ||||
-rw-r--r-- | otherlibs/num/bignum/c/bn/bnCmp.c | 77 | ||||
-rw-r--r-- | otherlibs/num/bignum/c/bn/bnDivide.c | 156 | ||||
-rw-r--r-- | otherlibs/num/bignum/c/bn/bnInit.c | 74 | ||||
-rw-r--r-- | otherlibs/num/bignum/c/bn/bnMult.c | 84 | ||||
-rw-r--r-- | otherlibs/num/bignum/c/bz.c | 833 | ||||
-rw-r--r-- | otherlibs/num/bignum/c/bzf.c | 50 | ||||
-rw-r--r-- | otherlibs/num/bignum/c/bztest.c | 167 | ||||
-rw-r--r-- | otherlibs/num/bignum/c/testKerN.c | 1085 |
9 files changed, 3458 insertions, 0 deletions
diff --git a/otherlibs/num/bignum/c/KerN.c b/otherlibs/num/bignum/c/KerN.c new file mode 100644 index 000000000..7b9ef1ce1 --- /dev/null +++ b/otherlibs/num/bignum/c/KerN.c @@ -0,0 +1,932 @@ +/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */ +/* Last modified_on Thu Feb 20 18:18:12 GMT+1:00 1992 by shand */ +/* modified_on Tue Jan 15 19:32:53 GMT+1:00 1991 by herve */ + + +/* KerN.c: the kernel written in C */ + +/* + * Description of types and constants. + * + * Several conventions are used in the commentary: + * A "BigNum" is the name for an infinite-precision number. + * Capital letters (e.g., "N") are used to refer to the value of BigNums. + * The word "digit" refers to a single BigNum digit. + * The notation "Size(N)" refers to the number of digits in N, + * which is typically passed to the subroutine as "nl". + * The notation "Length(N)" refers to the number of digits in N, + * not including any leading zeros. + * The word "Base" is used for the number 2 ** BN_DIGIT_SIZE, where + * BN_DIGIT_SIZE is the number of bits in a single BigNum digit. + * The expression "BBase(N)" is used for Base ** NumDigits(N). + * The term "leading zeros" refers to any zeros before the most + * significant digit of a number. + * + * + * In the code, we have: + * + * "nn" is a pointer to a big number, + * "nl" is the number of digits from nn, + * "d" is a digit. + * + */ + + +/**/ + +#define BNNMACROS_OFF +#include "BigNum.h" +#define NOMEM + + /*** copyright ***/ + +static char copyright[]="@(#)KerN.c: copyright Digital Equipment Corporation & INRIA 1988, 1989\n"; + + + /******* non arithmetic access to digits ********/ + + +#ifndef _NO_PROTO +void BnnSetToZero (BigNum nn, BigNumLength nl) +#else +void BnnSetToZero (nn, nl) +BigNum nn; BigNumLength nl; +#endif + +/* + * Sets all the specified digits of the BigNum to 0 + */ + +{ + BigNum nnlim; + if (nl <= 0) + return; + nnlim = nn+nl-1; + do *nn = 0; while(nn++ < nnlim); +} + + /***************************************/ + + +#ifndef _NO_PROTO +void BnnAssign (BigNum mm, BigNum nn, BigNumLength nl) +#else /* _NO_PROTO */ +void BnnAssign ( mm, nn, nl) +BigNum mm; BigNum nn; BigNumLength nl; +#endif /* _NO_PROTO */ + +/* + * Copies N => M + */ + +{ + BigNum nnlim; + if (nl <= 0) + return; + nnlim = nn+nl; +#ifdef MSDOS + if (realaddr(mm) < realaddr(nn) || realaddr(mm) > realaddr(nnlim)) +#else + if ((mm < nn) || ( mm > nnlim)) +#endif + do *mm++ = *nn++; while(nn < nnlim); + else +#ifdef MSDOS + if (realaddr(mm) > realaddr(nn)) +#else + if (mm > nn) +#endif + { + mm += nl; + do *--mm = *--nnlim; while(nn < nnlim); + } +} + + /***************************************/ +/**/ + + +#ifndef _NO_PROTO +void BnnSetDigit (BigNum nn, BigNumDigit d) +#else /* _NO_PROTO */ +void BnnSetDigit ( nn, d) +BigNum nn; BigNumDigit d; +#endif /* _NO_PROTO */ + +/* + * Sets a single digit of N to the passed value + */ + +{ + *nn = d; +} + + /***************************************/ + + +#ifndef _NO_PROTO +BigNumDigit BnnGetDigit (BigNum nn) +#else /* _NO_PROTO */ +BigNumDigit BnnGetDigit ( nn) +BigNum nn; +#endif /* _NO_PROTO */ + +/* + * Returns the single digit pointed by N + */ + +{ + return (*nn); +} + + /***************************************/ +/**/ + + +#ifndef _NO_PROTO +BigNumLength BnnNumDigits (BigNum nn, BigNumLength nl) +#else /* _NO_PROTO */ +BigNumLength BnnNumDigits ( nn, nl) +BigNum nn; BigNumLength nl; +#endif /* _NO_PROTO */ + +/* + * Returns the number of digits of N, not counting leading zeros + */ + +{ + nn += nl; + + while (nl != 0 && *--nn == 0) + nl--; + + return (nl == 0 ? 1 : nl); +} + + /***************************************/ + + +#ifndef _NO_PROTO +BigNumDigit BnnNumLeadingZeroBitsInDigit (BigNumDigit d) +#else /* _NO_PROTO */ +BigNumDigit BnnNumLeadingZeroBitsInDigit ( d) +BigNumDigit d; +#endif /* _NO_PROTO */ + +/* + * Returns the number of leading zero bits in a digit + */ + +{ + register int p = 0; + if (BN_DIGIT_SIZE == 16 || BN_DIGIT_SIZE == 32 || BN_DIGIT_SIZE == 64) + { + register BigNumDigit mask = (~(BigNumDigit)0) << (BN_DIGIT_SIZE/2); + register BigNumLength maskl = BN_DIGIT_SIZE/2; + + if (d == 0) + return (BN_DIGIT_SIZE); + while (maskl) + { + if ((d & mask) == 0) + { + p += maskl; + d <<= maskl; + } + maskl >>= 1; + mask <<= maskl; + } + } + else + { + register BigNumDigit mask = ((BigNumDigit)1) << (BN_DIGIT_SIZE-1); + + while ((d & mask) == 0) + { + p++; + mask >>= 1; + } + } + + return (p); +} + + /***************************************/ +/**/ + + /************** Predicates on one digit ***************/ + + +#ifndef _NO_PROTO +Boolean BnnDoesDigitFitInWord (BigNumDigit d) +#else /* _NO_PROTO */ +Boolean BnnDoesDigitFitInWord ( d) +BigNumDigit d; +#endif /* _NO_PROTO */ + +/* + * Returns TRUE iff the digit can be represented in just BN_WORD_SIZE bits + */ +{ + /* The C compiler must evaluate the predicate at compile time */ + if (BN_DIGIT_SIZE > BN_WORD_SIZE) + return (d >= ((BigNumDigit)1) << BN_WORD_SIZE ? FALSE : TRUE); + else + return (TRUE); +} + + /***************************************/ + + +#ifndef _NO_PROTO +Boolean BnnIsDigitZero (BigNumDigit d) +#else /* _NO_PROTO */ +Boolean BnnIsDigitZero ( d) +BigNumDigit d; +#endif /* _NO_PROTO */ + +/* Returns TRUE iff digit = 0 */ + +{ + return (d == 0); +} + + /***************************************/ + + +#ifndef _NO_PROTO +Boolean BnnIsDigitNormalized (BigNumDigit d) +#else /* _NO_PROTO */ +Boolean BnnIsDigitNormalized ( d) +BigNumDigit d; +#endif /* _NO_PROTO */ + +/* + * Returns TRUE iff Base/2 <= digit < Base + * i.e., if digit's leading bit is 1 + */ + +{ + return (d & (((BigNumDigit)1) << (BN_DIGIT_SIZE - 1)) ? TRUE : FALSE); +} + + /***************************************/ + + +#ifndef _NO_PROTO +Boolean BnnIsDigitOdd (BigNumDigit d) +#else /* _NO_PROTO */ +Boolean BnnIsDigitOdd ( d) +BigNumDigit d; +#endif /* _NO_PROTO */ + +/* + * Returns TRUE iff digit is odd + */ + +{ + return (d & 1 ? TRUE : FALSE); +} + + /***************************************/ + + +#ifndef _NO_PROTO +BigNumCmp BnnCompareDigits (BigNumDigit d1, BigNumDigit d2) +#else /* _NO_PROTO */ +BigNumCmp BnnCompareDigits ( d1, d2) +BigNumDigit d1; BigNumDigit d2; +#endif /* _NO_PROTO */ + +/* + * Returns BN_GREATER if digit1 > digit2 + * BN_EQUAL if digit1 = digit2 + * BN_LESS if digit1 < digit2 + */ + +{ + return (d1 > d2 ? BN_GT : (d1 == d2 ? BN_EQ : BN_LT)); +} + + /***************** Logical operations ********************/ + + +#ifndef _NO_PROTO +void BnnComplement (BigNum nn, BigNumLength nl) +#else /* _NO_PROTO */ +void BnnComplement ( nn, nl) +BigNum nn; BigNumLength nl; +#endif /* _NO_PROTO */ + +/* + * Performs the computation BBase(N) - N - 1 => N + */ + +{ + BigNum nnlim; + + if (nl <= 0) + return; + nnlim = nn+nl; + do + { + nn++; + nn[-1] = ~nn[-1]; + } + while (nn < nnlim); +} + + /***************************************/ +/**/ + + +#ifndef _NO_PROTO +void BnnAndDigits (BigNum n, BigNumDigit d) +#else /* _NO_PROTO */ +void BnnAndDigits ( n, d) +BigNum n; BigNumDigit d; +#endif /* _NO_PROTO */ + +/* + * Returns the logical computation n[0] AND d in n[0] + */ + +{ + *n &= d; +} + + /***************************************/ + + +#ifndef _NO_PROTO +void BnnOrDigits (BigNum n, BigNumDigit d) +#else /* _NO_PROTO */ +void BnnOrDigits ( n, d) +BigNum n; BigNumDigit d; +#endif /* _NO_PROTO */ + +/* + * Returns the logical computation n[0] OR d2 in n[0]. + */ + +{ + *n |= d; +} + + /***************************************/ + + +#ifndef _NO_PROTO +void BnnXorDigits (BigNum n, BigNumDigit d) +#else /* _NO_PROTO */ +void BnnXorDigits ( n, d) +BigNum n; BigNumDigit d; +#endif /* _NO_PROTO */ + +/* + * Returns the logical computation n[0] XOR d in n[0]. + */ + +{ + *n ^= d; +} + + /***************************************/ +/**/ + + /****************** Shift operations *******************/ + + +#ifndef _NO_PROTO +BigNumDigit BnnShiftLeft (BigNum mm, BigNumLength ml, int nbits) +#else /* _NO_PROTO */ +BigNumDigit BnnShiftLeft ( mm, ml, nbits) +BigNum mm; BigNumLength ml; int nbits; +#endif /* _NO_PROTO */ + +/* + * Shifts M left by "nbits", filling with 0s. + * Returns the leftmost "nbits" of M in a digit. + * Assumes 0 <= nbits < BN_DIGIT_SIZE. + */ + +{ + register BigNumDigit res = 0, save; + int rnbits; + + + if (nbits != 0) + { + rnbits = BN_DIGIT_SIZE - nbits; + + while (ml-- > 0) + { + save = *mm; + *mm++ = (save << nbits) | res; + res = save >> rnbits; + } + } + + return (res); +} + + /***************************************/ +/**/ + + +#ifndef _NO_PROTO +BigNumDigit BnnShiftRight (BigNum mm, BigNumLength ml, int nbits) +#else /* _NO_PROTO */ +BigNumDigit BnnShiftRight ( mm, ml, nbits) +BigNum mm; BigNumLength ml; int nbits; +#endif /* _NO_PROTO */ + +/* + * Shifts M right by "nbits", filling with 0s. + * Returns the rightmost "nbits" of M in a digit. + * Assumes 0 <= nbits < BN_DIGIT_SIZE. + */ + +{ + register BigNumDigit res = 0, save; + int lnbits; + + + if (nbits != 0) + { + mm += ml; + lnbits = BN_DIGIT_SIZE - nbits; + + while (ml-- > 0) + { + save = *(--mm); + *mm = (save >> nbits) | res; + res = save << lnbits; + } + } + + return (res); +} + + /***************************************/ +/**/ + + + /******************* Additions **************************/ + + +#ifndef _NO_PROTO +BigNumCarry BnnAddCarry (BigNum nn, BigNumLength nl, BigNumCarry carryin) +#else /* _NO_PROTO */ +BigNumCarry BnnAddCarry ( nn, nl, carryin) +BigNum nn; BigNumLength nl; BigNumCarry carryin; +#endif /* _NO_PROTO */ + +/* + * Performs the sum N + CarryIn => N. + * Returns the CarryOut. + */ + +{ + if (carryin == 0) + return (0); + + if (nl == 0) + return (1); + + while (nl > 0 && !(++(*nn++))) + nl--; + + return (nl > 0 ? 0 : 1); +} + + /***************************************/ +/**/ + + +#ifndef _NO_PROTO +BigNumCarry BnnAdd (BigNum mm, BigNumLength ml, BigNum nn, BigNumLength nl, BigNumCarry carryin) +#else /* _NO_PROTO */ +BigNumCarry BnnAdd ( mm, ml, nn, nl, carryin) +BigNum mm; BigNumLength ml; BigNum nn; BigNumLength nl; BigNumCarry carryin; +#endif /* _NO_PROTO */ + +/* + * Performs the sum M + N + CarryIn => M. + * Returns the CarryOut. + * Assumes Size(M) >= Size(N). + */ + +{ + register BigNumProduct c = carryin; + + + ml -= nl; + /* test computed at compile time */ + if (sizeof (BigNumProduct) > sizeof (BigNumDigit)) + { + while (nl > 0) + { + c += ((BigNumProduct)*mm) + *(nn++); + *(mm++) = c; + c >>= BN_DIGIT_SIZE; + nl--; + } + } + else + { + register BigNumProduct save; + + while (nl > 0) + { + save = *mm; + c += save; + if (c < save) + { + *(mm++) = *(nn++); + c = 1; + } + else + { + save = *(nn++); + c += save; + *(mm++) = c; + c = (c < save) ? 1 : 0; + } + nl--; + } + } + + return (BnnAddCarry (mm, ml, (BigNumCarry) c)); +} + + /***************************************/ +/**/ + + /****************** Subtraction *************************/ + + + +#ifndef _NO_PROTO +BigNumCarry BnnSubtractBorrow (BigNum nn, BigNumLength nl, BigNumCarry carryin) +#else /* _NO_PROTO */ +BigNumCarry BnnSubtractBorrow ( nn, nl, carryin) +BigNum nn; BigNumLength nl; BigNumCarry carryin; +#endif /* _NO_PROTO */ + +/* + * Performs the difference N + CarryIn - 1 => N. + * Returns the CarryOut. + */ + +{ + if (carryin == 1) + return (1); + if (nl == 0) + return (0); + + while (nl > 0 && !((*nn++)--)) + nl--; + + return (nl > 0 ? 1 : 0); +} + + /***************************************/ +/**/ + + +#ifndef _NO_PROTO +BigNumCarry BnnSubtract (BigNum mm, BigNumLength ml, BigNum nn, BigNumLength nl, BigNumCarry carryin) +#else /* _NO_PROTO */ +BigNumCarry BnnSubtract ( mm, ml, nn, nl, carryin) +BigNum mm; BigNumLength ml; BigNum nn; BigNumLength nl; BigNumCarry carryin; +#endif /* _NO_PROTO */ + +/* + * Performs the difference M - N + CarryIn - 1 => M. + * Returns the CarryOut. + * Assumes Size(M) >= Size(N). + */ + +{ + register BigNumProduct c = carryin; + register BigNumDigit invn; + + + ml -= nl; + /* test computed at compile time */ + if (sizeof (BigNumProduct) > sizeof (BigNumDigit)) + { + while (nl > 0) + { + invn = *(nn++) ^ -1; + c += ((BigNumProduct)*mm) + invn; + *(mm++) = c; + c >>= BN_DIGIT_SIZE; + nl--; + } + } + else + { + register BigNumProduct save; + + while (nl > 0) + { + save = *mm; + invn = *(nn++) ^ -1; + c += save; + + if (c < save) + { + *(mm++) = invn; + c = 1; + } + else + { + c += invn; + *(mm++) = c; + c = (c < invn) ? 1 : 0; + } + nl--; + } + } + + return (BnnSubtractBorrow (mm, ml, (BigNumCarry) c)); } + + + /***************************************/ +/* */ + + /***************** Multiplication ************************/ + +#ifndef _NO_PROTO +BigNumCarry BnnMultiplyDigit (BigNum pp, BigNumLength pl, BigNum mm, BigNumLength ml, BigNumDigit d) +#else /* _NO_PROTO */ +BigNumCarry BnnMultiplyDigit ( pp, pl, mm, ml, d) +BigNum pp; BigNumLength pl; BigNum mm; BigNumLength ml; BigNumDigit d; +#endif /* _NO_PROTO */ + +/* + * Performs the product: + * Q = P + M * d + * BB = BBase(P) + * Q mod BB => P + * Q div BB => CarryOut + * Returns the CarryOut. + * Assumes Size(P) >= Size(M) + 1. + */ + +{ + register BigNumProduct c = 0; + + + if (d == 0) + return (0); + + if (d == 1) + return (BnnAdd (pp, pl, mm, ml, (BigNumCarry) 0)); + + pl -= ml; + /* test computed at compile time */ + if (sizeof (BigNumProduct) > sizeof (BigNumDigit)) + { + while (ml != 0) + { + ml--; + c += *pp + (((BigNumProduct)d) * (*(mm++))); + *(pp++) = c; + c >>= BN_DIGIT_SIZE; + } + + while (pl != 0) + { + pl--; + c += *pp; + *(pp++) = c; + c >>= BN_DIGIT_SIZE; + } + + return (c); + } + else + { +/* help for stupid compilers--may actually be counter + productive on pipelined machines with decent register allocation!! */ +#define m_digit X0 +#define X3 Lm +#define X1 Hm + register BigNumDigit Lm, Hm, Ld, Hd, X0, X2 /*, X1, X3 */; + + Ld = d & ((((BigNumDigit)1) << (BN_DIGIT_SIZE / 2)) -1); + Hd = d >> (BN_DIGIT_SIZE / 2); + while (ml != 0) + { + ml--; + m_digit = *mm++; + Lm = m_digit & ((((BigNumDigit)1) << (BN_DIGIT_SIZE / 2)) -1); + Hm = m_digit >> (BN_DIGIT_SIZE / 2); + X0 = Ld * Lm; + X2 = Hd * Lm; + X3 = Hd * Hm; + X1 = Ld * Hm; + + if ((c += X0) < X0) X3++; + if ((X1 += X2) < X2) X3 += (((BigNumDigit)1)<<(BN_DIGIT_SIZE / 2)); + X3 += (X1 >> (BN_DIGIT_SIZE / 2)); + X1 <<= (BN_DIGIT_SIZE / 2); + if ((c += X1) < X1) X3++; + if ((*pp += c) < c) X3++; + pp++; + + c = X3; +#undef m_digit +#undef X1 +#undef X3 + } + + X0 = *pp; + c += X0; + *(pp++) = c; + + if (c >= X0) + return (0); + + pl--; + while (pl != 0 && !(++(*pp++))) + pl--; + + return (pl != 0 ? 0 : 1); + } +} + +#ifdef mips +#ifndef _NO_PROTO +BigNumCarry BnnMultiply2Digit (BigNum pp, BigNumLength pl, BigNum mm, BigNumLength ml, BigNumDigit d0, BigNumDigit d1) +#else /* _NO_PROTO */ +BigNumCarry BnnMultiply2Digit ( pp, pl, mm, ml, d0, d1) +BigNum pp; BigNumLength pl; BigNum mm; BigNumLength ml; BigNumDigit d0; BigNumDigit d1; +#endif /* _NO_PROTO */ + +/* + * Provided for compatibility with mips assembler implementation. + * Performs the product: + * Q = P + M * d0_d1 + * BB = BBase(P) + * Q mod BB => P + * Q div BB => CarryOut + * Returns the CarryOut. + * Assumes Size(P) >= Size(M) + 1. + */ + +{ + return + BnnMultiplyDigit (pp, pl, mm, ml, d0) + + BnnMultiplyDigit (pp+1, pl-1, mm, ml, d1); +} +#endif /* mips */ + + + /***************************************/ +/**/ + + /********************** Division *************************/ + + + /* xh:xl -= yh:yl */ +#define SUB(xh,xl,yh,yl) if (yl > xl) {xl -= yl; xh -= yh + 1;}\ + else {xl -= yl; xh -= yh;} + +#define LOW(x) (x & ((((BigNumDigit)1) << (BN_DIGIT_SIZE / 2)) -1)) +#define HIGH(x) (x >> (BN_DIGIT_SIZE / 2)) +#define L2H(x) (x << (BN_DIGIT_SIZE / 2)) + + +#ifndef _NO_PROTO +BigNumDigit BnnDivideDigit (BigNum qq, BigNum nn, BigNumLength nl, BigNumDigit d) +#else /* _NO_PROTO */ +BigNumDigit BnnDivideDigit ( qq, nn, nl, d) +BigNum qq; BigNum nn; BigNumLength nl; BigNumDigit d; +#endif /* _NO_PROTO */ + +/* Performs the quotient: N div d => Q + * Returns R = N mod d + * Assumes leading digit of N < d, and d > 0. + */ + +{ + /* test computed at compile time */ + if (sizeof (BigNumProduct) > sizeof (BigNumDigit)) + { + register BigNumProduct quad; + + + nn += nl; + nl--; + qq += nl; + quad = *(--nn); + + while (nl != 0) + { + nl--; + quad = (quad << BN_DIGIT_SIZE) | *(--nn); + *(--qq) = quad / d; + quad = quad % d; + } + + return (quad); + } + else + { + int k; + BigNumLength orig_nl; + BigNumDigit rh; /* Two halves of current remainder */ + BigNumDigit rl; /* Correspond to quad above */ + register BigNumDigit qa; /* Current appr. to quotient */ + register BigNumDigit ph, pl; /* product of c and qa */ + BigNumDigit ch, cl, prev_qq; + + + /* Normalize divisor */ + k = BnnNumLeadingZeroBitsInDigit (d); + if (k != 0) + { + prev_qq = qq[-1]; + orig_nl = nl; + d <<= k; + BnnShiftLeft (nn, nl, k); + } + + nn += nl; + nl--; + qq += nl; + + ch = HIGH (d); + cl = LOW (d); + + rl = *(--nn); + + while (nl != 0) + { + nl--; + rh = rl; + rl = *(--nn); + qa = rh / ch; /* appr. quotient */ + + /* Compute ph, pl */ + pl = cl * qa; + ph = ch * qa; + ph += HIGH (pl); + pl = L2H (pl); + + /* While ph:pl > rh:rl, decrement qa, adjust qh:ql */ + while (ph > rh || ph == rh && pl > rl) + { + qa--; + SUB (ph, pl, ch, L2H (cl)); + } + + SUB (rh, rl, ph, pl); + + /* Top half of quotient is correct; save it */ + *(--qq) = L2H (qa); + qa = (L2H (rh) | HIGH (rl)) / ch; + + /* Approx low half of q */ + /* Compute ph, pl, again */ + pl = cl * qa; + ph = ch * qa; + ph += HIGH (pl); + pl = LOW (pl) | L2H (LOW (ph)); + ph = HIGH (ph); + + /* While ph:pl > rh:rl, decrement qa, adjust qh:ql */ + while (ph > rh || ph == rh && pl > rl) + { + qa--; + SUB (ph, pl, 0, d); + } + + /* Subtract ph:pl from rh:rl; we know rh will be 0 */ + rl -= pl; + *qq |= qa; + } + + /* Denormalize dividend */ + if (k != 0) { + if((qq > nn) && (qq < &nn[orig_nl])) { + /* Overlap between qq and nn. Care of *qq! */ + orig_nl = (qq - nn); + BnnShiftRight (nn, orig_nl, k); + nn[orig_nl - 1] = prev_qq; + } else if(qq == nn) { + BnnShiftRight(&nn[orig_nl - 1], 1, k); + } else { + BnnShiftRight (nn, orig_nl, k); + } } + return (rl >> k); + } +} + + /***************************************/ + + diff --git a/otherlibs/num/bignum/c/bn/bnCmp.c b/otherlibs/num/bignum/c/bn/bnCmp.c new file mode 100644 index 000000000..b678124d1 --- /dev/null +++ b/otherlibs/num/bignum/c/bn/bnCmp.c @@ -0,0 +1,77 @@ +/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */ +/* Last modified_on Fri Oct 5 16:13:31 GMT+1:00 1990 by herve */ +/* modified_on Fri Aug 10 17:21:47 GMT+2:00 1990 by shand */ + + +/* bnCmp.c: a piece of the bignum kernel written in C */ + + + /***************************************/ + +#define BNNMACROS_OFF +#include "BigNum.h" + + /*** copyright ***/ + +static char copyright[]="@(#)bnCmp.c: copyright Digital Equipment Corporation & INRIA 1988, 1989, 1990\n"; + + +#ifndef _NO_PROTO +Boolean BnnIsZero (BigNum nn, BigNumLength nl) +#else /* _NO_PROTO */ +Boolean BnnIsZero (nn, nl) +BigNum nn; BigNumLength nl; +#endif /* _NO_PROTO */ + +/* + * Returns TRUE iff N = 0 + */ + +{ + return (BnnNumDigits (nn, nl) == 1 && (nl == 0 || BnnIsDigitZero (*nn))); +} + + /***************************************/ +/**/ + + +#ifndef _NO_PROTO +BigNumCmp BnnCompare (BigNum mm, BigNumLength ml, BigNum nn, BigNumLength nl) +#else /* _NO_PROTO */ +BigNumCmp BnnCompare (mm, ml, nn, nl) +BigNum mm; BigNumLength ml; BigNum nn; BigNumLength nl; +#endif /* _NO_PROTO */ + +/* + * return + * BN_GT iff M > N + * BN_EQ iff N = N + * BN_LT iff N < N +*/ + +{ + register BigNumCmp result = BN_EQ; + + + ml = BnnNumDigits (mm, ml); + nl = BnnNumDigits (nn, nl); + + if (ml != nl) + return (ml > nl ? BN_GT : BN_LT); + + while (result == BN_EQ && ml-- > 0) + result = BnnCompareDigits (*(mm+ml), *(nn+ml)); + + return (result); + +/**** USE memcmp() instead: extern int memcmp (); + + if (ml == nl) + { + lex = memcmp (mm, nn, nl*BN_DIGIT_SIZE/BN_BYTE_SIZE); + return (lex > 0 ? BN_GT: (lex == 0 ? BN_EQ: BN_LT)); + } + else + return (ml > nl ? BN_GT : BN_LT); +******/ +} diff --git a/otherlibs/num/bignum/c/bn/bnDivide.c b/otherlibs/num/bignum/c/bn/bnDivide.c new file mode 100644 index 000000000..e25938bb8 --- /dev/null +++ b/otherlibs/num/bignum/c/bn/bnDivide.c @@ -0,0 +1,156 @@ +/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */ +/* Last modified_on Mon Apr 15 18:51:35 GMT+2:00 1991 by herve */ +/* modified_on Fri Mar 30 3:29:17 GMT+2:00 1990 by shand */ + + +/* bnDivide.c: a piece of the bignum kernel written in C */ + + + /***************************************/ + +#define BNNMACROS_OFF +#include "BigNum.h" + + /*** copyright ***/ + +static char copyright[]="@(#)bnDivide.c: copyright Digital Equipment Corporation & INRIA 1988, 1989, 1990\n"; + + +static divide (nn, nl, dd, dl) + + BigNum nn, dd; +register BigNumLength nl, dl; + +/* + * In-place division. + * + * Input (N has been EXTENDED by 1 PLACE; D is normalized): + * +-----------------------------------------------+----+ + * | N EXT| + * +-----------------------------------------------+----+ + * + * +-------------------------------+ + * | D 1| + * +-------------------------------+ + * + * Output (in place of N): + * +-------------------------------+---------------+----+ + * | R | Q | + * +-------------------------------+---------------+----+ + * + * Assumes: + * N > D + * Size(N) > Size(D) + * last digit of N < last digit of D + * D is normalized (Base/2 <= last digit of D < Base) + */ + +{ + register int ni; + BigNumDigit DDigit, BaseMinus1, QApp, RApp; + + + /* Initialize constants */ + BnnSetDigit (&BaseMinus1, 0); + BnnComplement(&BaseMinus1, 1); + + /* Save the most significant digit of D */ + BnnAssign (&DDigit, dd+dl-1, 1); + + /* Replace D by Base - D */ + BnnComplement (dd, dl); + BnnAddCarry (dd, dl, 1); + + /* For each digit of the divisor, from most significant to least: */ + nl += 1; + ni = nl-dl; + while (--ni >= 0) + { + /* Compute the approximate quotient */ + nl--; + + /* If first digits of numerator and denominator are the same, */ + if (BnnCompareDigits (*(nn+nl), DDigit) == BN_EQ) + /* Use "Base - 1" for the approximate quotient */ + BnnAssign (&QApp, &BaseMinus1, 1); + else + /* Divide the first 2 digits of N by the first digit of D */ + RApp = BnnDivideDigit (&QApp, nn+nl-1, 2, DDigit); + + /* Compute the remainder */ + BnnMultiplyDigit (nn+ni, dl+1, dd, dl, QApp); + + /* Correct the approximate quotient, in case it was too large */ + while (BnnCompareDigits (*(nn+nl), QApp) != BN_EQ) + { + BnnSubtract (nn+ni, dl+1, dd, dl, 1); /* Subtract D from N */ + BnnSubtractBorrow (&QApp, 1, 0); /* Q -= 1 */ + } + } + + /* Restore original D */ + BnnComplement (dd, dl); + BnnAddCarry (dd, dl, 1); +} + + + /***************************************/ +/**/ + + +void BnnDivide (nn, nl, dd, dl) + + BigNum nn, dd; +register BigNumLength nl, dl; + +/* + * Performs the quotient: + * N div D => high-order bits of N, starting at N[dl] + * N mod D => low-order dl bits of N + * + * Assumes + * Size(N) > Size(D), + * last digit of N < last digit of D (if N > D). + */ + +{ + BigNumDigit nshift; + + + /* Take care of easy cases first */ + switch (BnnCompare (nn, nl, dd, dl)) + { + case BN_LT: /* n < d */ + ; /* N => R */ + BnnSetToZero (nn+dl, nl-dl); /* 0 => Q */ + return; + case BN_EQ: /* n == d */ + BnnSetToZero (nn, nl); /* 0 => R */ + BnnSetDigit (nn+dl, 1); /* 1 => Q */ + /* bug fixed Mon Apr 15 18:36:50 GMT+2:00 1991 by jch, + was BnnSetDigit (nn+nl-1, 1); */ + return; + } + + /* here: n > d */ + + /* If divisor is just 1 digit, use a special divide */ + if (dl == 1) + *nn = BnnDivideDigit (nn+1, nn, nl, *dd); /* note: nn+1 = nn+dl */ + /* Otherwise, divide one digit at a time */ + else + { + /* Normalize */ + nshift = BnnNumLeadingZeroBitsInDigit (*(dd+dl-1)); + BnnShiftLeft (dd, dl, nshift); + BnnShiftLeft (nn, nl, nshift); + + /* Divide */ + divide (nn, nl-1, dd, dl); + + /* Unnormalize */ + BnnShiftRight (dd, dl, nshift); + BnnShiftRight (nn, dl, nshift); + /* note: unnormalize N <=> unnormalize R (with R < D) */ + } +} diff --git a/otherlibs/num/bignum/c/bn/bnInit.c b/otherlibs/num/bignum/c/bn/bnInit.c new file mode 100644 index 000000000..d02301508 --- /dev/null +++ b/otherlibs/num/bignum/c/bn/bnInit.c @@ -0,0 +1,74 @@ +/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */ +/* Last modified_on Fri Oct 5 16:28:39 GMT+1:00 1990 by herve */ +/* modified_on Fri Mar 30 3:28:56 GMT+2:00 1990 by shand */ + + +/* bnInit.c: a piece of the bignum kernel written in C */ + + + /***************************************/ + +#define BNNMACROS_OFF +#include "BigNum.h" + +static int Initialized = FALSE; + + /*** copyright ***/ + +static char copyright[]="@(#)bnInit.c: copyright Digital Equipment Corporation & INRIA 1988, 1989, 1990\n"; + + + /***************************************/ + +void BnnInit () +{ + if (!Initialized) + { + + + Initialized = TRUE; + } +} + + /***************************************/ + +void BnnClose () +{ + if (Initialized) + { + + + Initialized = FALSE; + } +} + + /***************************************/ + + /* some U*ix standard functions do not exist on VMS */ + /* neither on MSDOS */ + +#ifdef NOMEM + +/* Copies LENGTH bytes from string SRC to string DST */ +void bcopy(src, dst, length) +char *src, *dst; +register int length; +{ + for (; length > 0; length--) + *dst++ = *src++; +} + +/* Places LENGTH 0 bytes in the string B */ +void bzero(buffer, length) +char *buffer; +register int length; +{ + for (; length>0; length--) + *buffer++ = 0; +} + +#endif + + + + /***************************************/ diff --git a/otherlibs/num/bignum/c/bn/bnMult.c b/otherlibs/num/bignum/c/bn/bnMult.c new file mode 100644 index 000000000..f4ecf8337 --- /dev/null +++ b/otherlibs/num/bignum/c/bn/bnMult.c @@ -0,0 +1,84 @@ +/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */ +/* Last modified_on Tue Oct 9 10:43:48 GMT+1:00 1990 by herve */ +/* modified_on Fri Mar 30 4:13:47 GMT+2:00 1990 by shand */ + + +/* bnMult.c: a piece of the bignum kernel written in C */ + + + /***************************************/ + +#define BNNMACROS_OFF +#include "BigNum.h" + + /*** copyright ***/ + +static char copyright[]="@(#)bnMult.c: copyright Digital Equipment Corporation & INRIA 1988, 1989, 1990\n"; + + +BigNumCarry BnnMultiply (pp, pl, mm, ml, nn, nl) + +register BigNum pp, nn; + BigNum mm; +register BigNumLength pl, nl; + BigNumLength ml; + +/* + * Performs the product: + * Q = P + M * N + * BB = BBase(P) + * Q mod BB => P + * Q div BB => CarryOut + * + * Returns the CarryOut. + * + * Assumes: + * Size(P) >= Size(M) + Size(N), + * Size(M) >= Size(N). + */ + +{ + BigNumCarry c; + + /* Multiply one digit at a time */ + + /* the following code give higher performance squaring. + ** Unfortunately for small nl, procedure call overheads kills it + */ +#ifndef mips_v131 +#ifndef MSDOS + /* Squaring code provoke a mips optimizer bug in V1.31 */ + /* It also doesn't work using MSDOS */ + if (mm == nn && ml == nl && nl > 6) + { + register BigNumDigit n_prev = 0; + /* special case of squaring */ + for (c = 0; nl > 0; ) + { + register BigNumDigit n = *nn; + c += BnnMultiplyDigit(pp, pl, nn, 1, n); + if (n_prev) + c += BnnAdd(pp, pl, nn, 1, (BigNumCarry) 0); + nl--, nn++; + pp += 2, pl -= 2; + c += BnnMultiplyDigit(pp-1, pl+1, nn, nl, n+n+n_prev); + /* note following if statements are resolved at compile time */ + if (sizeof(BigNumDigit) == sizeof(short)) + n_prev = ((short) n) < 0; + else if (sizeof(BigNumDigit) == sizeof(int)) + n_prev = ((int) n) < 0; + else if (sizeof(BigNumDigit) == sizeof(long)) + n_prev = ((long) n) < 0; + else + n_prev = ((n<<1)>>1) == n; + } + } + else +#endif +#endif + for (c = 0; nl-- > 0; pp++, nn++, pl--) + c += BnnMultiplyDigit (pp, pl, mm, ml, *nn); + + return c; +} + diff --git a/otherlibs/num/bignum/c/bz.c b/otherlibs/num/bignum/c/bz.c new file mode 100644 index 000000000..10d0c224f --- /dev/null +++ b/otherlibs/num/bignum/c/bz.c @@ -0,0 +1,833 @@ +/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */ +/* Last modified_on Thu Apr 4 20:01:18 GMT+2:00 1991 by herve */ +/* modified_on Thu Mar 22 20:45:38 GMT+1:00 1990 by shand */ + + +/* bz.c: provides an implementation of "unlimited-precision" + * arithmetic for signed integers. + * + * Several conventions are used in the commentary: + * A "BigZ" is the name for an arbitrary-precision signed integer. + * Capital letters (e.g., "Z") are used to refer to the value of BigZs. + */ + + +#include "BigZ.h" + + + /***************************************/ +/* +#include <stdio.h> +#include <macros.h> +#include <math.h> +#include <malloc.h> +#include <values.h> +*/ + +#define NULL 0 +#define max(a,b) (a<b ? b : a) +#define abs(x) (x>=0 ? x : -(x)) +#define M_LN2 0.69314718055994530942 +#define M_LN10 2.30258509299404568402 +#define BITSPERBYTE 8 +#define BITS(type) (BITSPERBYTE * (int)sizeof(type)) +#define HIBITI (1 << BITS(int) - 1) +#define MAXINT (~HIBITI) + + /***************************************/ + +#define BzToBn(z) ((z)->Digits) +#define CTOI(c) (c >= '0' && c <= '9' ? c - '0' :\ + c >= 'a' && c <= 'f' ? c - 'a' + 10:\ + c >= 'A' && c <= 'F' ? c - 'A' + 10:\ + 0) + +extern char *malloc(); + + /*** copyright ***/ + +static char copyright[]="@(#)bz.c: copyright Digital Equipment Corporation & INRIA 1988, 1989\n"; + + + /***************************************/ + +static int Initialized = FALSE; + +/* constants used by BzToString() and BzFromString() */ +static double BzLog [] = +{ + 0, + 0, /* log (1) */ + M_LN2, /* log (2) */ + 1.098612, /* log (3) */ + 1.386294, /* log (4) */ + 1.609438, /* log (5) */ + 1.791759, /* log (6) */ + 1.945910, /* log (7) */ + 2.079442, /* log (8) */ + 2.197225, /* log (9) */ + M_LN10, /* log (10) */ + 2.397895, /* log (11) */ + 2.484907, /* log (12) */ + 2.564949, /* log (13) */ + 2.639057, /* log (14) */ + 2.708050, /* log (15) */ + 2.772588, /* log (16) */ +}; + +/**/ + + +#ifndef _NO_PROTO +void BzInit (void) +#else /* _NO_PROTO */ +void BzInit () +#endif /* _NO_PROTO */ +{ + if (!Initialized) + { + BnnInit (); + Initialized = TRUE; + } +} + + /***************************************/ + + +#ifndef _NO_PROTO +BigZ BzCreate (BigNumLength Size) +#else /* _NO_PROTO */ +BigZ BzCreate (Size) +BigNumLength Size; +#endif /* _NO_PROTO */ + +/* + * Allocates a BigZ of the desired size. + * Sets it to 0. + */ + +{ + BigZ z; + + + if ((z = (BigZ) (malloc (sizeof (struct BigZHeader) + Size * sizeof (BigNumDigit)))) != NULL) + { + /* reset digits */ + BnnSetToZero (BzToBn (z), Size); + + /* init header */ + BzSetSize (z, Size); + BzSetSign (z, BZ_ZERO); + } + + return (z); +} + + + +#ifndef _NO_PROTO +void BzFree (BigZ z) +#else /* _NO_PROTO */ +void BzFree (z) +BigZ z; +#endif /* _NO_PROTO */ + +/* + * Frees an existing BigZ. + */ + +{ + free (z); +} + + /***************************************/ + /***************************************/ + + +#ifndef _NO_PROTO +void BzFreeString (char *s) +#else /* _NO_PROTO */ +void BzFreeString (s) +char *s; +#endif /* _NO_PROTO */ + +/* + * Frees an existing BigZ allocated string. + */ + +{ + free (s); +} + + /***************************************/ +/**/ + +#ifndef _NO_PROTO +BigNumLength BzNumDigits (BigZ z) +#else /* _NO_PROTO */ +BigNumLength BzNumDigits (z) +BigZ z; +#endif /* _NO_PROTO */ + +/* + * Returns the number of digits used by z. + */ + +{ + return (BnnNumDigits (BzToBn (z), BzGetSize (z))); +} + + + /***************************************/ + + +#ifndef _NO_PROTO +BigZ BzCopy (BigZ z) +#else /* _NO_PROTO */ +BigZ BzCopy (z) +BigZ z; +#endif /* _NO_PROTO */ + +/* + * Creates a copy of the passed BigZ. + */ + +{ + BigZ y; + int zl; + + + zl = BzNumDigits (z); + if ((y = BzCreate (zl)) != NULL) + { + /* copy the digits */ + BnnAssign (BzToBn (y), BzToBn (z), zl); + + /* copy the header WITHOUT the size !! */ + BzSetSign (y, BzGetSign (z)); + } + + return (y); +} + + /***************************************/ +/**/ + + +#ifndef _NO_PROTO +BigZ BzNegate (BigZ z) +#else /* _NO_PROTO */ +BigZ BzNegate (z) +BigZ z; +#endif /* _NO_PROTO */ + +/* + * Negates the passed BigZ. + */ + +{ + BigZ y; + + y = BzCopy (z); + BzSetSign (y, BzGetOppositeSign (z)); + + return (y); +} + + /***************************************/ + + +#ifndef _NO_PROTO +BigZ BzAbs (BigZ z) +#else /* _NO_PROTO */ +BigZ BzAbs (z) +BigZ z; +#endif /* _NO_PROTO */ + +/* + * Takes the absolute value of the passed BigZ. + */ + +{ + BigZ y; + + y = BzCopy (z); + BzSetSign (y, abs (BzGetSign (z))); + + return (y); +} + + /***************************************/ + + +#ifndef _NO_PROTO +BzCmp BzCompare (BigZ y, BigZ z) +#else /* _NO_PROTO */ +BzCmp BzCompare (y, z) +BigZ y; BigZ z; +#endif /* _NO_PROTO */ + +/* + * Returns BZ_GT if Y > Z, + * BZ_LT if Y < Z, + * BZ_EQ otherwise. + */ + +{ + return (BzGetSign (y) > BzGetSign (z) ? BZ_GT : + BzGetSign (y) < BzGetSign (z) ? BZ_LT : + BzGetSign (y) > 0 ? BnnCompare (BzToBn (y), BzGetSize (y), + BzToBn (z), BzGetSize (z)) : + BzGetSign (y) < 0 ? BnnCompare (BzToBn (z), BzGetSize (z), + BzToBn (y), BzGetSize (y)) : + BZ_EQ); +} + + /***************************************/ +/**/ + + +#ifndef _NO_PROTO +BigZ BzAdd (BigZ y, BigZ z) +#else /* _NO_PROTO */ +BigZ BzAdd (y, z) +BigZ y; BigZ z; +#endif /* _NO_PROTO */ + +/* + * Returns Y + Z. + */ + +{ + BigZ n; + int yl; + int zl; + + + yl = BzNumDigits (y); + zl = BzNumDigits (z); + + if (BzGetSign (y) == BzGetSign (z)) + { + /* Add magnitudes if signs are the same */ + switch (BnnCompare (BzToBn (y), yl, BzToBn (z), zl)) + { + case BZ_EQ: + case BZ_GT: /* |Y| >= |Z| */ + + if ((n = BzCreate (yl+1)) != NULL) + { + BnnAssign (BzToBn (n), BzToBn (y), yl); + BnnAdd (BzToBn (n), yl+1, BzToBn (z), zl, (BigNumCarry) 0); + BzSetSign (n, BzGetSign (y)); + } + break; + + default: /* BZ_LT: |Y| < |Z| */ + + if ((n = BzCreate (zl+1)) != NULL) + { + BnnAssign (BzToBn (n), BzToBn (z), zl); + BnnAdd (BzToBn (n), zl+1, BzToBn (y), yl, (BigNumCarry) 0); + BzSetSign (n, BzGetSign (z)); + } + break; + } + } +/**/ + + + else + { + /* Subtract magnitudes if signs are different */ + switch (BnnCompare (BzToBn (y), yl, BzToBn (z), zl)) + { + case BZ_EQ: /* Y = -Z */ + + n = BzCreate (1); + break; + + case BZ_GT: /* |Y| > |Z| */ + + if ((n = BzCreate (yl)) != NULL) + { + BnnAssign (BzToBn (n), BzToBn (y), yl); + BnnSubtract (BzToBn (n), yl, BzToBn (z), zl, (BigNumCarry) 1); + BzSetSign (n, BzGetSign (y)); + } + break; + + default: /* BZ_LT: |Y| < |Z| */ + + if ((n = BzCreate (zl)) != NULL) + { + BnnAssign (BzToBn (n), BzToBn (z), zl); + BnnSubtract (BzToBn (n), zl, BzToBn (y), yl, (BigNumCarry) 1); + BzSetSign (n, BzGetSign (z)); + } + break; + } + } + + return (n); +} + + /***************************************/ +/**/ + + +#ifndef _NO_PROTO +BigZ BzSubtract (BigZ y, BigZ z) +#else /* _NO_PROTO */ +BigZ BzSubtract (y, z) +BigZ y; BigZ z; +#endif /* _NO_PROTO */ + +/* + * Returns Y - Z. + */ + +{ + if (y == z) + return (BzCreate (1)); + else + { + BigZ diff; + + BzSetSign (z, BzGetOppositeSign (z)); + diff = BzAdd (y, z); + BzSetSign (z, BzGetOppositeSign (z)); + + return diff; + } +} + + /***************************************/ +/**/ + + +#ifndef _NO_PROTO +BigZ BzMultiply (BigZ y, BigZ z) +#else /* _NO_PROTO */ +BigZ BzMultiply (y, z) +BigZ y; BigZ z; +#endif /* _NO_PROTO */ + +/* + * Returns Y * Z. + */ + +{ + BigZ n; + int yl, zl; + + + yl = BzNumDigits (y); + zl = BzNumDigits (z); + + if ((n = BzCreate (yl+zl)) != NULL) + { + BnnMultiply (BzToBn (n), yl+zl, BzToBn (y), yl, BzToBn (z), zl); + BzSetSign (n, BzGetSign (y) * BzGetSign (z)); + } + + return (n); +} + + /***************************************/ +/**/ + + +#ifndef _NO_PROTO +BigZ BzDivide (BigZ y, BigZ z, BigZ *r) +#else /* _NO_PROTO */ +BigZ BzDivide (y, z, r) +BigZ y; BigZ z; BigZ *r; +#endif /* _NO_PROTO */ + +/* + * Sets Y mod Z => R, + * Returns Y div Z => Q + * + * such that Y = ZQ + R + * and 0 <= R < |Z|. + * + * Return NULL if Z = 0 + * + * Return floor(Y/Z) if Z > 0 + * otherwise return ceil(Y/Z) + * where / is the real numbers division. + */ + +{ + BigZ q; + int yl, zl, ql, rl; + Boolean rnotnul; + + + if (BzGetSign (z) == BZ_ZERO) + return (NULL); + + yl = BzNumDigits (y); + zl = BzNumDigits (z); + + /* max +1 since BnnAddCarry can overflow */ + ql = max (yl-zl+1, 1) +1; + rl = max (zl,yl) + 1; + + /* Set up quotient, remainder */ + q = BzCreate (ql); + *r = BzCreate (rl); + + if (!*r || !q) + return (NULL); + + BnnAssign (BzToBn (*r), BzToBn (y), yl); + + /* Do the division */ + BnnDivide (BzToBn (*r), rl, BzToBn (z), zl); + BnnAssign (BzToBn (q), BzToBn (*r) + zl, rl-zl); + BnnSetToZero (BzToBn (*r) + zl, rl-zl); + rl = zl; + + /* Correct the signs, adjusting the quotient and remainder */ + rnotnul = !BnnIsZero (BzToBn (*r), rl); + if (BzGetSign (y) == BZ_MINUS && rnotnul) + { + /* Y < 0, R > 0: (Q+1)=>Q, Z-R=>R */ + BnnAddCarry (BzToBn (q), ql, (BigNumCarry) 1); + + BzSetSign (q, BzGetOppositeSign (z)); + BnnComplement (BzToBn (*r), rl); + BnnAdd (BzToBn (*r), rl, BzToBn (z), zl, (BigNumCarry) 1); + } + else + BzSetSign (q, BzGetSign (y) * BzGetSign (z)); + + if (BnnIsZero (BzToBn(q),ql)) + BzSetSign (q,BZ_ZERO); + + /* Correct the sign of the remainder */ + if (rnotnul) + BzSetSign (*r, BZ_PLUS); + + return (q); +} + + /***************************************/ +/**/ + + +#ifndef _NO_PROTO +BigZ BzDiv (BigZ y, BigZ z) +#else /* _NO_PROTO */ +BigZ BzDiv (y, z) +BigZ y; BigZ z; +#endif /* _NO_PROTO */ + +/* + * Returns Y div Z. + * + * Return NULL if Z = 0 + * + * Return floor(Y/Z) if Z > 0 + * otherwise return ceil(Y/Z) + * where / is the real numbers division + */ + +{ + BigZ q, r; + + + q = BzDivide (y, z, &r); + BzFree (r); + + return (q); +} + + /***************************************/ + + +#ifndef _NO_PROTO +BigZ BzMod (BigZ y, BigZ z) +#else /* _NO_PROTO */ +BigZ BzMod (y, z) +BigZ y; BigZ z; +#endif /* _NO_PROTO */ + +/* + * Returns Y mod Z. + */ + +{ + BigZ r; + + + BzFree (BzDivide (y, z, &r)); + + return (r); +} + + /***************************************/ +/**/ + + +#ifndef _NO_PROTO +char * BzToString (BigZ z, BigNumDigit base) +#else /* _NO_PROTO */ +char * BzToString (z, base) +BigZ z; BigNumDigit base; +#endif /* _NO_PROTO */ + +/* + * Returns a pointer to a string that represents Z in the specified base. + * Assumes 2 <= base <= 16. + */ + +{ + char * string; + BigZ y, q, t; + BigNumDigit r; + + static char Digit[] = "0123456789ABCDEF"; + char * s; + int sd; + int zl, sl; + + + if (base < 2 || base > 16) + return (NULL); + + /* Allocate BigNums and set up string */ + zl = BzNumDigits (z) + 1; + sl = BzLog[2] * BN_DIGIT_SIZE * zl / BzLog[base] + 3; + + y = BzCreate (zl); + q = BzCreate (zl); + + string = malloc (sl * sizeof (char)); + + if (!y || !q || !string) + return (NULL); + + BnnAssign (BzToBn (y), BzToBn (z), zl-1); + s = string + sl; + + /* Divide Z by base repeatedly; successive digits given by remainders */ + *--s = '\0'; + if (BzGetSign (z) == BZ_ZERO) + *--s = '0'; + else + do + { + r = BnnDivideDigit (BzToBn (q), BzToBn (y), zl, base); + *--s = Digit[r]; + + /* exchange y and q (to avoid BzMove (y, q) */ + t = q, q = y, y = t; + } while (!BnnIsZero (BzToBn (y), zl)); + + /* Set sign if negative */ + if (BzGetSign (z) < 0) + *--s = '-'; + + /* and move string into position */ + if ((sd = s-string) > 0) + while (s < string + sl) + { + *(s-sd) = *s; + s++; + } + + /* Free temporary BigNums and return the string */ + BzFree(y); + BzFree(q); + + return string; +} + + /***************************************/ +/**/ + + +#ifndef _NO_PROTO +BigZ BzFromString (char *s, BigNumDigit base) +#else /* _NO_PROTO */ +BigZ BzFromString (s, base) +char *s; BigNumDigit base; +#endif /* _NO_PROTO */ + +/* + * Creates a BigZ whose value is represented by "string" in the + * specified base. The "string" may contain leading spaces, + * followed by an optional sign, followed by a series of digits. + * Assumes 2 <= base <= 16. + * When called from C, only the first 2 arguments are passed. + */ + +{ + BigZ z, p, t; + BzSign sign; + int zl; + + + /* Throw away any initial space */ + while (*s == ' ') + s++; + + /* Allocate BigNums */ + zl = strlen (s) * BzLog[base] / (BzLog[2] * BN_DIGIT_SIZE) + 1; + + z = BzCreate (zl); + p = BzCreate (zl); + + if (!z || !p) + return (NULL); + + /* Set up sign, base, initialize result */ + sign = (*s == '-' ? (s++, BZ_MINUS) : *s == '+' ? (s++, BZ_PLUS) : BZ_PLUS); + + /* Multiply in the digits of the string, one at a time */ + for (; *s != '\0'; s++) + { + BnnSetToZero (BzToBn (p), zl); + BnnSetDigit (BzToBn (p), CTOI (*s)); + BnnMultiplyDigit (BzToBn (p), zl, BzToBn (z), zl, base); + + /* exchange z and p (to avoid BzMove (z, p) */ + t = p, p = z, z = t; + } + + /* Set sign of result */ + BzSetSign (z, BnnIsZero (BzToBn (z), zl) ? BZ_ZERO : sign); + + /* Free temporary BigNums */ + BzFree (p); + + return (z); +} + + /***************************************/ + +#ifndef _NO_PROTO +BigZ BzFromInteger (int i) +#else /* _NO_PROTO */ +BigZ BzFromInteger (i) +int i; +#endif /* _NO_PROTO */ + +{ + BigZ z; + + + z = BzCreate (1); + + z->Digits[0] = abs (i); + + if (i > 0) + BzSetSign (z, BZ_PLUS); + else + if (i < 0) + BzSetSign (z, BZ_MINUS); + else + BzSetSign (z, BZ_ZERO); + + return z; +} + + /***************************************/ + + +#ifndef _NO_PROTO +int BzToInteger (BigZ z) +#else /* _NO_PROTO */ +int BzToInteger (z) +BigZ z; +#endif /* _NO_PROTO */ + +{ + if (BzNumDigits (z) > 1) + return (MAXINT); + + if (BzGetSign (z) == BZ_MINUS) + return (- z->Digits[0]); + else + return (z->Digits[0]); +} + + /***************************************/ + + +#ifndef _NO_PROTO +BigZ BzFromBigNum (BigNum n, BigNumLength nl) +#else /* _NO_PROTO */ +BigZ BzFromBigNum (n, nl) +BigNum n; BigNumLength nl; +#endif /* _NO_PROTO */ + +{ + BigZ z; + int i; + + + z = BzCreate (nl); + + /* set the sign of z such that the pointer n is unchanged yet */ + if (BnnIsZero (n, nl)) + BzSetSign (z, BZ_ZERO); + else + BzSetSign (z, BZ_PLUS); + + for (i = 0; i < nl; i++, n++) + z->Digits[i] = *n; + + return z; +} + + /***************************************/ + +#ifndef _NO_PROTO +BigNum BzToBigNum (BigZ z, BigNumLength *nl) +#else /* _NO_PROTO */ +BigNum BzToBigNum (z, nl) +BigZ z; BigNumLength *nl; +#endif /* _NO_PROTO */ + +{ + BigNum n, m; + int i; + + + if (BzGetSign (z) == BZ_MINUS) + return NULL; + + *nl = BzNumDigits (z); + + if ((n = (BigNum) (malloc (((*nl+1) * sizeof (BigNumDigit))))) != NULL) + { + *n = *nl; /* set size */ + + for (i = 0, m = ++n; i < *nl; i++, m++) + *m = z->Digits[i]; + } + + return n; +} + + /***************************************/ + + +#ifndef _NO_PROTO +void BzClose (void) +#else /* _NO_PROTO */ +void BzClose () +#endif /* _NO_PROTO */ +{ + if (Initialized) + { + BnnClose (); + Initialized = FALSE; + } +} + + /***************************************/ diff --git a/otherlibs/num/bignum/c/bzf.c b/otherlibs/num/bignum/c/bzf.c new file mode 100644 index 000000000..7186452aa --- /dev/null +++ b/otherlibs/num/bignum/c/bzf.c @@ -0,0 +1,50 @@ +/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */ +/* Last modified_on Mon Jan 23 16:05:27 GMT+1:00 1989 by herve */ + +/* + * bzf.c: Miscellaneous functions built on top of BigZ. + * + */ + + +#include "BigZ.h" + + /***************************************/ + +#define BzToBn(z) ((z)->Digits) + + /***************************************/ + + +#ifndef _NO_PROTO +BigZ BzFactorial (BigZ z) +#else /* _NO_PROTO */ +BigZ BzFactorial (z) +BigZ z; +#endif /* _NO_PROTO */ + +/* + * Returns Z! + * Assumes Z < Base. + */ + +{ + BigZ f; + BigNumDigit zval; + int fl = 1; + + + zval = BnnGetDigit (BzToBn (z)); + f = BzCreate (zval+1); + BnnSetDigit (BzToBn (f), 1); + BzSetSign (f, BzGetSign (z)); + + while (zval-- > 1) + { + BnnMultiplyDigit (BzToBn (f), fl+1, BzToBn (f), fl, zval); + fl = BnnNumDigits (BzToBn (f), fl+1); + } + + return (f); +} + diff --git a/otherlibs/num/bignum/c/bztest.c b/otherlibs/num/bignum/c/bztest.c new file mode 100644 index 000000000..2d06b184e --- /dev/null +++ b/otherlibs/num/bignum/c/bztest.c @@ -0,0 +1,167 @@ +/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */ +/* Last modified_on Tue Feb 25 1:27:57 GMT+1:00 1992 by shand */ +/* modified_on Mon Apr 15 18:44:14 GMT+2:00 1991 by herve */ + +#include <stdio.h> +#include "BigZ.h" + +#ifndef MSDOS +#define S(A,B) strcmp(A,B) +#define P(A) fprintf(stderr,"%d...",A) +#define E(A,B,C) fprintf(stderr,"\nError in test #%d:\nComputed: %s\nCorrect: %s\n",A,C,B) +#define T(A,B,C) S(B,C)?E(A,B,C):P(A) +#else +void T(A,B,C) +int A; +char *B, *C; +{ + if (strcmp (B, C)) + fprintf (stderr, "\nError in test #%d:\nComputed: %s\nCorrect: %s\n",A,C,B); + else + fprintf (stderr,"%2d...",A); +} +#endif +#define NEWLINE fprintf(stderr,"\n") +#define To(A) BzToString(A,10) +#define From(A) BzFromString(A,10) +#define Abs(A) BzAbs(A) +#define Neg(A) BzNegate(A) +#define Add(A,B) BzAdd(A,B) +#define Sub(A,B) BzSubtract(A,B) +#define Mul(A,B) BzMultiply(A,B) +#define Div(A,B) BzDiv(A,B) +#define Mod(A,B) BzMod(A,B) +#define Fac(A) BzFactorial(A) +#define FromI(I) BzFromInteger(I) +#define Cmp(A,B) BzCompare(A,B) +#define Sqa(A) Mul(A,A) + +#define zero FromI(0) +#define one FromI(1) +#define two FromI(2) +#define minusone FromI(-1) + +#ifdef DIGITonUSHORT +#define two31m1 Sub(Mul(From("65536"),From("32768")),one) +#else +#define two31m1 FromI(0x7FFFFFFF) +#endif + +main() +{ + BigZ a,b; + + T(1,"12", To(From("12"))) ; + T(2,"12345678910", To(From("12345678910"))) ; + T(3,"123", To(From("00000123"))) ; + T(4,"-123", To(From("-123"))) ; + T(5,"-32768", To(From("-32768"))) ; + T(6,"-32768", To(Neg(From("32768")))) ; + T(7,"-32768", To(Add(From("-16384"),From("-16384")))) ; + T(8,"-32768", To(Add(From("-16383"),From("-16385")))) ; + T(9,"-32768", To(Mul(From("2"),From("-16384")))) ; + T(10,"-16384", To(Div(From("-32768"),From("2")))) ; + NEWLINE; + T(11,"100000", To(Add(From("1"),From("99999")))) ; + T(12,"12343994",To(Add(From("-1684"),From("12345678")))); + T(13,"-12329294",To(Sub(From("16384"),From("12345678")))); + T(14,"135801",To(Add(From("12345"),From("123456")))); + T(15,"123456135801",To(Add(From("12345"),From("123456123456")))); + T(16,"135801",To(Add(From("123456"),From("12345")))); + T(17,"123456135801",To(Add(From("123456123456"),From("12345")))); + T(18,"135801",To(Sub(From("12345"),From("-123456")))); + T(19,"123456135801",To(Sub(From("12345"),From("-123456123456")))); + T(20,"135801",To(Sub(From("123456"),From("-12345")))); + NEWLINE; + T(21,"123456135801",To(Sub(From("123456123456"),From("-12345")))); + T(22,"-111111",To(Sub(From("12345"),From("123456")))); + T(23,"111111",To(Sub(From("123456"),From("12345")))); + T(24,"-123456111111",To(Sub(From("12345"),From("123456123456")))); + T(25,"123456111111",To(Sub(From("123456123456"),From("12345")))); + T(26,"-111111",To(Add(From("12345"),From("-123456")))); + T(27,"111111",To(Add(From("123456"),From("-12345")))); + T(28,"-123456111111",To(Add(From("12345"),From("-123456123456")))); + T(29,"123456111111",To(Add(From("123456123456"),From("-12345")))); + T(30,"2", To(Div(From("264195"),From("97200")))) ; + NEWLINE; + T(31,"27405", To(Mod(From("97200"),From("69795")))) ; + T(32,"4294967295", To(Div(From("22685491128062564230891640495451214097"),From("5281877500950955845296219748")))) ; + T(33,"99997",To(Add(From("-3"),From("100000")))); + T(34,"-100003",To(Add(From("-3"),From("-100000")))); + T(35,"999999",To(Sub(From("1000000"),From("1")))); + T(36,"999999999",To(Mul(From("12345679"),From("81")))); + a = From("1234567"); + b = From("123456"); + T(37,"1234567",To(Add(Mul(Div(a,b),b),Mod(a,b)))); + T(38,"-1234567",To(Add(Mul(Div(Neg(a),Neg(b)),Neg(b)),Mod(Neg(a),Neg(b))))); + T(39,"1234567",To(Add(Mul(Div(a,Neg(b)),Neg(b)),Mod(a,Neg(b))))); + T(40,"10000000000000000000000",To(Mul(From("-100000000000"),From("-100000000000")))); + NEWLINE; + T(41,"-10000000000000000000000",To(Mul(From("-100000000000"),From("100000000000")))); + T(42,"-10000000000000000000000",To(Mul(From("100000000000"),From("-100000000000")))); + T(43,"10000000000000000000000",To(Mul(From("100000000000"),From("100000000000")))); + a = Sub(From("10000000000000"),From("10000000000000")); + T(44,"0",To(Mod(a,From("1000000000000")))); + T(45,"0",To(Div(a,From("1000000000000")))); + T(46,"0",To(Mod(Neg(a),From("10000000000000")))); + T(47,"0",To(Div(Neg(a),From("10000000000000")))); + T(48,"2",To(Div(From("3000"),Sub(From("1234567891234"),From("1234567890000"))))); + T(49,"532",To(Mod(From("3000"),Sub(From("1234567891234"),From("1234567890000"))))); + T(50,"9",To(Mod(From("-1234567890"),From("1234567899")))); + NEWLINE; + T(51,"2",To(Mod(Sub(From("12345678900000"),From("12345678926887")),From("3")))); + T(52,"40830949904677684825316369628906250000000000000",To(Mul(From("48270948888581289062500000000"),From("845870049062500000")))); + T(53,"22666179639240748063923391983020279316955515",To(Mul(From("6956883693"),From("3258093801689886619170103176686855")))); + T(54,"1405006117752879898543142606244511569936384000000000",To(Fac(From("42")))); + T(55,"0",To(Mod(Fac(From("13")),Fac(From("9"))))); + T(56,"0",To(Mod(Fac(From("34")),Fac(From("13"))))); + T(57,"0",To(Mod(Fac(From("57")),Fac(From("21"))))); + T(58,"0",To(Mod(Fac(From("40")),Fac(From("39"))))); + T(59,"59",To(Div(Fac(From("59")),Fac(From("58"))))); + T(60,"2",To(Div(From("5"),From("2")))); + NEWLINE; + T(61,"1",To(Mod(From("5"),From("2")))); + T(62,"-3",To(Div(From("-5"),From("2")))); + T(63,"1",To(Mod(From("-5"),From("2")))); + T(64,"3",To(Div(From("-5"),From("-2")))); + T(65,"1",To(Mod(From("-5"),From("-2")))); + T(66,"-2",To(Div(From("5"),From("-2")))); + T(67,"1",To(Mod(From("5"),From("-2")))); + T(68,"3",To(Div(From("6"),From("2")))); + T(69,"0",To(Mod(From("6"),From("2")))); + T(70,"-3",To(Div(From("-6"),From("2")))); + NEWLINE; + T(71,"0",To(Mod(From("-6"),From("2")))); + T(72,"3",To(Div(From("-6"),From("-2")))); + T(73,"0",To(Mod(From("-6"),From("-2")))); + T(74,"-3",To(Div(From("6"),From("-2")))); + T(75,"0",To(Mod(From("6"),From("-2")))); + T(76,"0",To(Abs(From("0")))); + T(77,"1234567890",To(Abs(From("1234567890")))); + T(78,"1234567890",To(Abs(From("-1234567890")))); + T(79,"1",BzCompare(From("-1234567890"),From("12345"))<0?"1":"0"); + T(80,"1",BzGetSign(From("-1234567890"))<0?"1":"0"); + NEWLINE; + T(81,"0", To(Add(From("-1"),Mul(From("-1"),From("-1"))))); + T(82,"-1",To(Add(From("-1"),Mul(From("0"), From("-1"))))); + T(83,"-3",To(Add(From("-1"),Mul(From("-2"),From("1" ))))); + T(84,"1", To(Add(From("-1"),Mul(From("-2"),From("-1"))))); + T(85,"-1",To(Add(From("1"), Mul(From("-2"),From("1" ))))); + T(86,"18446744065119617025",To(Mul(From("4294967295"),From("4294967295")))); + /* (-2^64 + 2^32 - 1) / 2^32 */ + T(87,"-4294967296",To(Div( + Sub(Mul(Mul(Add(Mul(two31m1,two),one),Mul(Add(two31m1,one), two)),minusone),one), + Mul(Add (two31m1,one),two)))); + T(88,"Equal",(Cmp(Mod(FromI(10),FromI(5)),zero) == BZ_EQ)?"Equal":"Not equal"); + T(89,"Equal",(Cmp(Div(FromI(4),FromI(5)),zero) == BZ_EQ)?"Equal":"Not equal"); + a = From ("100000000000000000000000000000000000000"); + T(90,To (a),To(Div (Sqa (a),a))); + /* 90: tests the MIPS & turbo C optimizer bugs. If the special */ + /* purpose squaring code is enabled and the optimizer */ + /* messes up, this test will fail */ + NEWLINE; + b = Sqa (a); + T(91,To (b),To(Div (Sqa (b),b))); + T(92,"-1",To(Div(From("13"),From("-13")))); + NEWLINE; +} diff --git a/otherlibs/num/bignum/c/testKerN.c b/otherlibs/num/bignum/c/testKerN.c new file mode 100644 index 000000000..22faa3224 --- /dev/null +++ b/otherlibs/num/bignum/c/testKerN.c @@ -0,0 +1,1085 @@ +/* Copyright Digital Equipment Corporation & INRIA 1988, 1989 */ +/* testKerN.c: tests des primitives de KerN */ +/* Last modified_on Thu Feb 20 17:26:13 GMT+1:00 1992 by shand */ +/* modified_on Wed Feb 14 16:14:04 GMT+1:00 1990 by herve */ +/* modified_on 17-OCT-1989 20:35:55.91 by Jim Lawton */ + +/* You can comment the line below if you want to test the C macro Package + instead of C or Assembly functions. */ + +#define BNNMACROS_OFF 1 + + +#include "BigNum.h" + /* old types of Bn */ + +typedef BigNumDigit BigNumType; /* A BigNum's type */ + +struct BigNumHeader /* The header of a BigNum */ +{ + BigNumType type; + BigNumLength length; +}; + + /* old functions of Bn */ + +/* + * Creation and access to type and length fields. + */ +extern char *malloc(); +/* Allocates a BigNum structure and returns a pointer to it */ +BigNum BnAlloc(size) int size; { + register BigNum n; + + n = (BigNum) (malloc(sizeof(struct BigNumHeader) + + size * sizeof(BigNumDigit)) + + sizeof(struct BigNumHeader)); + (((struct BigNumHeader *) n) - 1)->length = size; + return(n); +} + +/* Allocates a BigNum, inserts its Type, and returns a pointer to it */ +BigNum BnCreate(type, size) BigNumType type; int size; { + register BigNum n; + + n = BnAlloc(size); + (((struct BigNumHeader *) n) - 1)->type = type; + BnnSetToZero ((n+ 0), size); + return(n); +} + +/* Frees a BigNum structure */ +BnFree(n) BigNum n; { + free(((struct BigNumHeader *) n) - 1); + return 1; +} + +/* Returns the BigNum's Type */ +BigNumType BnGetType(n) BigNum n; { + return((((struct BigNumHeader *) n) - 1)->type); +} + +/* Sets the BigNum's Type */ +BnSetType(n, type) BigNum n; BigNumType type; { + (((struct BigNumHeader *) n) - 1)->type = type; +} + +/* Returns the number of digits allocated for the BigNum */ +BnGetSize(n) BigNum n; { + return((((struct BigNumHeader *) n) - 1)->length); +} + + + + /* structure d'un test */ + +struct testenv { + char *name; /* Le nom de la fonction teste'e. */ + int flag; /* Pour savoir si l'on continue le Test. */ + char hist[2048]; /* L'expression qui provoque l'erreur. */ + char *depend; /* De quoi depend le Test. */ +}; + + + /* Les nombres pre'de'finies. */ + +static BigNum NumbVect[5][2]; +static BigNum NumbProto, Ntmp2, NtmpBig; + +#define RN(n) NumbVect[n][0] +#define SN(n) NumbVect[n][1] + + /* Taille des nombres utilise's. */ + /* de la forme 4(n + 1) */ +#define TESTLENGTH 16 +#define DTL TESTLENGTH/2 +#define QTL TESTLENGTH/4 + +/* Nombre de test. */ +int TestCount, CallDummy = 0; + +int dummy() +{ + /* a simple way to get control after <n> steps in the debugger */ + printf("TestCount = %d\n", TestCount); +} + +int TestCountInc() +{ + TestCount++; + if (TestCount == CallDummy) + dummy(); +} + +ResetTest(n) int n; { + /* Remet le nieme nombre a` la valeur prototype. */ + BnnAssign ((RN(n)+ 0), ( NumbProto+ 0), TESTLENGTH); + BnnAssign ((SN(n)+ 0), ( NumbProto+ 0), TESTLENGTH); +} + +Check(n) int n; { + int i; + /* Verifie que les n nombres calcules correspondent aux simule's. */ + for(i = 0; i < n; i++) + if(CheckSubRange(i, 0, TESTLENGTH)) return(1); + return(FALSE); +} + +CheckSubRange(x, nd, nl) int x, nd, nl; { + /* Verifie l'e'galite' des sous-nombres + (RN(x), nd, nl) et (SN(x), nd, nl) */ + while(nl) { + nl--; + if(BnnCompareDigits (*(RN(x)+ nd), *( SN(x)+ nd))) return(nd + 1); + nd++; + } + return(FALSE); +} + +ShowDiff0(e, r1, r2) struct testenv *e; int r1,r2; { + ErrorPrint(e); + if(r1 != r2) + printf("---- Result is %d and should be %d----\n", r1, r2); + return(e->flag); +} + +ShowDiff1(e, r1, r2, n, nd, nl) + struct testenv *e; char *n; int r1, r2, nd, nl; { + ErrorPrint(e); + if(r1 != r2) + printf("---- Result is %d and should be %d----\n", r1, r2); + ShowOutRange(0, n, nd, nl); + ShowSubNumber(0, n, nd, nl); + return(e->flag); +} + +ShowDiff2(e, r1, r2, n, nd, nl, m, md, ml) + struct testenv *e; char *n, *m; int r1, r2, nd, nl, md, ml; { + ErrorPrint(e); + if(r1 != r2) + printf("---- Result is %d and should be %d----\n", r1, r2); + ShowOutRange(0, n, nd, nl); + ShowOutRange(1, m, md, ml); + ShowSubNumber(0, n, nd, nl); + ShowSubNumber(1, m, md, ml); + return(e->flag); +} + +ShowDiff3(e, r1, r2, n, nd, nl, m, md, ml, o, od, ol) + struct testenv *e; char *n, *m, *o; + int r1, r2, nd, nl, md, ml, od, ol; { + ErrorPrint(e); + if(r1 != r2) + printf("---- Result is %d and should be %d----\n", r1, r2); + ShowOutRange(0, n, nd, nl); + ShowOutRange(1, m, md, ml); + ShowOutRange(2, o, od, ol); + ShowSubNumber(0, n, nd, nl); + ShowSubNumber(1, m, md, ml); + ShowSubNumber(2, o, od, ol); + return(e->flag); +} + +ShowDiff4(e, r1, r2, n, nd, nl, m, md, ml, o, od, ol, p, pd, pl) + struct testenv *e; char *n, *m, *o, *p; + int r1, r2, nd, nl, md, ml, od, ol, pd, pl; { + ErrorPrint(e); + if(r1 != r2) + printf("---- Result is %d and should be %d----\n", r1, r2); + ShowOutRange(0, n, nd, nl); + ShowOutRange(1, m, md, ml); + ShowOutRange(2, o, od, ol); + ShowOutRange(3, p, pd, pl); + ShowSubNumber(0, n, nd, nl); + ShowSubNumber(1, m, md, ml); + ShowSubNumber(2, o, od, ol); + ShowSubNumber(3, p, pd, pl); + return(e->flag); +} + +ShowSubNumber(x, n, nd, nl) char *n; int x, nd, nl; { + printf("[%s, %d, %d] = ", n, nd, nl); + RangeNumberPrint("", RN(x), nd, nl); + if(CheckSubRange(x, nd, nl)) { + RangeNumberPrint(" Before: ", NumbProto, nd, nl); + RangeNumberPrint(" Simulated: ", SN(x), nd, nl); +} } + +RangeNumberPrint(s, n, nd, nl) char *s; BigNum n; int nd, nl; { + int first = 1; + + /* Ne marche que si BnGetDigit est garanti!!! */ + printf("%s {", s); + while(nl) { + nl--; + if(!first) printf(", "); else first = 0; + if(BN_DIGIT_SIZE <= 16) + printf("%.4X", BnnGetDigit ((n+ nd + nl))); + else if(BN_DIGIT_SIZE <= 32) + printf("%.8X", BnnGetDigit ((n+ nd + nl))); + else printf("%.16lX", BnnGetDigit ((n+ nd + nl))); + } + printf("}\n"); +} + +char *msg = "---- Modification Out of Range of number "; +ShowOutRange(x, n, nd, nl) char *n; int x, nd, nl; { + int i = 0, bol = 0; + + while(i = CheckSubRange(x, i, TESTLENGTH - i)) { + if((i <= nd) || (i > nd + nl)) { + if(!bol) { + bol = 1; + printf("%s %s at index: (%d", msg, n, i - 1); + } else { + printf(" %d", i - 1); + } } } + if(bol) printf(").\n"); +} + +ErrorPrint(e) struct testenv *e; { + printf("*** Error in compute : %s\n", e->hist); + printf(" Depends on %s\n", e->depend); +} + +/* + * Tests des fonctions non redefinisables + */ + +int genlengthvec[] = {9, 8, 1, 0, 2000, 32000,}; +BigNumType gentypevec[] = {0, 1, 2, 3, 4, 5,}; + +Generique(e) struct testenv *e; { + int i; + int length, length2; + BigNumType type, type2; + int fix; + BigNum n; + + + for(i=0; i < 6; i++) { + type = gentypevec[i]; + length = genlengthvec[i]; + n = BnCreate(type, length); + if((type2 = BnGetType(n)) != type) { + sprintf(e->hist,"BnGetType(BnCreate(%d, %d));", type, length); + if(ShowDiff0(e, type, type2)) return(TRUE); + } + if((length2 = BnGetSize(n)) != length) { + sprintf(e->hist,"BnGetSize(BnCreate(%d, %d));", type, length); + if(ShowDiff0(e, length, length2)) return(TRUE); + } + if(BnFree(n) == 0) { + sprintf(e->hist, "BnFree(BnCreate(%d, %d));", type, length); + if(ShowDiff0(e, 1, 0)) return(TRUE); + } + BnSetType((n = BnAlloc(length)), type); + if((type2 = BnGetType(n)) != type) { + sprintf(e->hist,"BnGetType(BnAlloc(%d, %d));", type, length); + if(ShowDiff0(e, type, type2)) return(TRUE); + } + if((length2 = BnGetSize(n)) != length) { + sprintf(e->hist,"BnGetSize(BnAlloc(%d, %d));", type, length); + if(ShowDiff0(e, length, length2)) return(TRUE); + } + if(BnFree(n) == 0) { + sprintf(e->hist, "BnFree(BnAlloc(%d, %d));", type, length); + if(ShowDiff0(e, 1, 0)) return(TRUE); + } + } + return(FALSE); +} + +/* + * BnSetToZero + */ +___BnSetToZero___(n, nd, nl) register BigNum n; register int nd, nl; { + register int i; + for(i=0; i<nl; i++) + BnnSetDigit ((n+ nd + i), 0); +} + +TestBnSetToZero(e) struct testenv *e; { + int nd, nl; + + e->depend = "(BnSetDigit)"; + for(nd = 0; nd <= TESTLENGTH; nd++) + for(nl = 0; nl <= TESTLENGTH - nd; nl++) { + TestCountInc(); + ResetTest(0); + BnnSetToZero ((RN(0)+ nd), nl); + ___BnSetToZero___(SN(0), nd, nl); + if(Check(1)) { + sprintf(e->hist, "%s(n, %d, %d)", e->name, nd, nl); + if(ShowDiff1(e, 0, 0, "n", nd, nl)) return(1); + } } + return(FALSE); +} + +/* + * BnAssign + */ +___BnAssign___(m, md, n, nd, nl) BigNum m, n; int md, nd, nl; { + register int i; + for(i=0; i<nl; i++) + BnnSetDigit ((NtmpBig+ i), BnnGetDigit ((n+ nd + i))); + for(i=0; i<nl; i++) + BnnSetDigit ((m+ md + i), BnnGetDigit ((NtmpBig+ i))); +} + +TestBnAssign(e) struct testenv *e; { + int md, nd, nl; + + e->depend = "(BnGetDigit, BnSetDigit)"; + for(md = 0; md <= TESTLENGTH; md++) + for(nd = 0; nd <= TESTLENGTH; nd++) + for(nl=0; ((nl<=TESTLENGTH-nd) && (nl<=TESTLENGTH-md)); nl++) { + TestCountInc(); + ResetTest(0); + BnnAssign ((RN(0)+ md), ( RN(0)+ nd), nl); + ___BnAssign___(SN(0), md, SN(0), nd, nl); + if(Check(1)) { + sprintf(e->hist, "%s(m, %d, n, %d, %d)", e->name, + md, nd, nl); + if(ShowDiff1(e, 0, 0, "n", md, nl)) return(1); + } } + return(FALSE); +} + + +/* + * BnNumDigits + */ +___BnNumDigits___(n, nd, nl) register BigNum n; register int nd, nl; { + + while(nl != 0) { + nl--; + if(!BnnIsDigitZero (*(n+ nd + nl))) break; + } + return(nl + 1); +} + +TestBnNumDigits(e) struct testenv *e; { + int nd0, nl0, nd, nl, l1, l2; + + e->depend = "(BnIsDigitZero)"; + for(nd0 = 0; nd0 <= TESTLENGTH; nd0++) + for(nl0 = 0; nl0 <= TESTLENGTH - nd0; nl0++) + for(nd = 0; nd <= TESTLENGTH; nd++) + for(nl = 0; nl <= TESTLENGTH - nd; nl++) { + TestCountInc(); + ResetTest(0); + BnnSetToZero ((RN(0)+ nd0), nl0); + BnnSetToZero ((SN(0)+ nd0), nl0); + l1 = BnnNumDigits ((RN(0)+ nd), nl); + l2 = ___BnNumDigits___(SN(0), nd, nl); + if(Check(1) || l1 != l2) { + sprintf(e->hist, "%s(n, %d, %d)", e->name, nd, nl); + if(ShowDiff1(e, l1, l2, "n", nd, nl)) return(1); + } } + return(FALSE); +} + +/* + * BnNumLeadingZeroBitsInDigit + */ +__BnNumLeadingZeroBitsInDigit__(n, nd) BigNum n; int nd; { + int p = 0; + + if(BnnIsDigitZero (*(n+ nd))) return(BN_DIGIT_SIZE); + BnnAssign ((Ntmp2+ 0), ( n+ nd), 1); + *( Ntmp2+ 1) = BnnShiftLeft ((Ntmp2+ 0), 1, 1); + while(BnnIsDigitZero (*(Ntmp2+ 1))) { + *( Ntmp2+ 1) = BnnShiftLeft ((Ntmp2+ 0), 1, 1); + p++; + } + return(p); +} + +TestBnNumLeadingZeroBitsInDigit(e) struct testenv *e; { + int nd; int l1, l2; + + + e->depend = "(BnShiftLeft, BnIsDigitZero)"; + ResetTest(0); + for(nd = 0; nd < TESTLENGTH; nd++) { + TestCountInc(); + l1 = BnnNumLeadingZeroBitsInDigit (*(RN(0)+ nd)); + l2 = __BnNumLeadingZeroBitsInDigit__(SN(0), nd); + if(Check(1) || l1 != l2) { + sprintf(e->hist, "%s(n, %d)", e->name, nd); + if(ShowDiff1(e, l1, l2, "n", nd, 1)) return(1); + } } + return(FALSE); +} + +/* + * BnIsDigitZero + */ +___BnIsDigitZero___(n, nd) BigNum n; int nd; { + if(BnnGetDigit ((n+ nd)) == 0) return(1); + return(0); +} + +TestBnIsDigitZero(e) struct testenv *e; { + int nd; int l1, l2; + + e->depend = "()"; + ResetTest(0); + for(nd = 0; nd < TESTLENGTH; nd++) { + TestCountInc(); + l1 = BnnIsDigitZero (*(RN(0)+ nd)); + l2 = ___BnIsDigitZero___(SN(0), nd); + if(Check(1) || ((l1 == 0) && (l2 != 0)) || + ((l1 != 0) && (l2 == 0))) { + sprintf(e->hist, "%s(n, %d)", e->name, nd); + if(ShowDiff1(e, l1, l2, "n", nd, 1)) return(1); + } } + return(FALSE); +} + +/* + * BnIsDigitNormalized + */ +___BnIsDigitNormalized___(n, nd) BigNum n; int nd; { + BnnAssign ((Ntmp2+ 0), ( n+ nd), 1); + *( Ntmp2+ 1) = BnnShiftLeft ((Ntmp2+ 0), 1, 1); + if(BnnIsDigitZero (*(Ntmp2+ 1))) return(0); + return(1); +} + +TestBnIsDigitNormalized(e) struct testenv *e; { + int nd; int l1, l2; + + e->depend = "(BnShiftLeft, BnIsDigitZero)"; + ResetTest(0); + for(nd = 0; nd < TESTLENGTH; nd++) { + TestCountInc(); + l1 = BnnIsDigitNormalized (*(RN(0)+ nd)); + l2 = ___BnIsDigitNormalized___(SN(0), nd); + if(Check(1) || ((l1 == 0) && (l2 != 0)) || + ((l1 != 0) && (l2 == 0))) { + sprintf(e->hist, "%s(n, %d)", e->name, nd); + if(ShowDiff1(e, l1, l2, "n", nd, 1)) return(1); + } } + return(FALSE); +} + +/* + * BnIsDigitOdd + */ +___BnIsDigitOdd___(n, nd) BigNum n; int nd; { + BnnAssign ((Ntmp2+ 0), ( n+ nd), 1); + *( Ntmp2+ 1) = BnnShiftRight ((Ntmp2+ 0), 1, 1); + if(BnnIsDigitZero (*(Ntmp2+ 1))) return(0); + return(1); +} + +TestBnIsDigitOdd(e) struct testenv *e; { + int nd; int l1, l2; + + e->depend = "(BnShiftRight, BnIsDigitZero)"; + ResetTest(0); + for(nd = 0; nd < TESTLENGTH; nd++) { + TestCountInc(); + l1 = BnnIsDigitOdd (*(RN(0)+ nd)); + l2 = ___BnIsDigitOdd___(SN(0), nd); + if(Check(1) || ((l1 == 0) && (l2 != 0)) || + ((l1 != 0) && (l2 == 0))) { + sprintf(e->hist, "%s(n, %d)", e->name, nd); + if(ShowDiff1(e, l1, l2, "n", nd, 1)) return(1); + } } + return(FALSE); +} + +/* + * BnCompareDigits + */ +___BnCompareDigits___(n, nd, m, md) BigNum n, m; int nd, md; { + BnnAssign ((Ntmp2+ 0), ( n+ nd), 1); + BnnComplement ((Ntmp2+ 0), 1); + if(BnnAdd ((Ntmp2+ 0), 1, ( m+ md), 1, (BigNumCarry) 0)) return(-1); + BnnComplement ((Ntmp2+ 0), 1); + if(BnnIsDigitZero (*(Ntmp2+ 0))) return(0); + return(1); +} + +TestBnCompareDigits(e) struct testenv *e; { + int nd, md; int l1, l2; + + e->depend = "(BnComplement, BnAdd, BnIsDigitZero)"; + ResetTest(0); + ResetTest(1); + for(nd = 0; nd < TESTLENGTH; nd++) + for(md = 0; md < TESTLENGTH; md++) { + TestCountInc(); + l1 = BnnCompareDigits (*(RN(0)+ nd), *( RN(1)+ md)); + l2 = ___BnCompareDigits___(SN(0), nd, SN(1), md); + if(Check(2) || l1 != l2) { + sprintf(e->hist, "%s(n, %d, m, %d)", e->name, nd, md); + if(ShowDiff2(e, l1, l2, "n", nd, 1, "m", md, 1)) + return(1); + } } + return(FALSE); +} + +/* + * BnComplement + */ +___BnComplement___(n, nd, nl) BigNum n; int nd, nl; { + int i; + + BnnSetDigit ((Ntmp2+ 0), 0); + BnnSubtractBorrow ((Ntmp2+ 0), 1, 0); + for(i = 0; i < nl; i++) + BnnXorDigits ((n+ nd + i), *( Ntmp2+ 0)); +} + +TestBnComplement(e) struct testenv *e; { + int nd, nl; + + e->depend = "(BnSubtractBorrow, BnXorDigits)"; + for(nd = 0; nd <= TESTLENGTH; nd++) + for(nl = 0; nl <= TESTLENGTH - nd; nl++) { + TestCountInc(); + ResetTest(0); + BnnComplement ((RN(0)+ nd), nl); + ___BnComplement___(SN(0), nd, nl); + if(Check(1)) { + sprintf(e->hist, "%s(n, %d, %d)", e->name, nd, nl); + if(ShowDiff1(e, 0, 0, "n", nd, nl)) return(1); + } } + return(FALSE); +} + +/* + * BnAndDigits + */ +___BnAndDigits___(n, nd, m, md) BigNum n, m; int nd, md; { + BnnAssign ((Ntmp2+ 0), ( n+ nd), 1); + BnnOrDigits ((Ntmp2+ 0), *( m+ md)); + BnnXorDigits ((Ntmp2+ 0), *( m+ md)); + BnnXorDigits ((n+ nd), *( Ntmp2+ 0)); +} + +TestBnAndDigits(e) struct testenv *e; { + int nd, md; + + e->depend = "(BnOrDigits, BnXorDigits)"; + ResetTest(1); + for(nd = 0; nd < TESTLENGTH; nd++) + for(md = 0; md < TESTLENGTH; md++) { + TestCountInc(); + ResetTest(0); + BnnAndDigits ((RN(0)+ nd), *( RN(1)+ md)); + ___BnAndDigits___(SN(0), nd, SN(1), md); + if(Check(2)) { + sprintf(e->hist, "%s(n, %d, m, %d)", e->name, nd, md); + if(ShowDiff2(e, 0, 0, "n", nd, 1, "m", md, 1)) + return(1); + } } + return(FALSE); +} + +/* + * BnOrDigits + */ +___BnOrDigits___(n, nd, m, md) BigNum n, m; int nd, md; { + BnnAssign ((Ntmp2+ 0), ( n+ nd), 1); + BnnAndDigits ((Ntmp2+ 0), *( m+ md)); + BnnXorDigits ((Ntmp2+ 0), *( m+ md)); + BnnXorDigits ((n+ nd), *( Ntmp2+ 0)); +} + +TestBnOrDigits(e) struct testenv *e; { + int nd, md; + + e->depend = "(BnAndDigits, BnXorDigits)"; + ResetTest(1); + for(nd = 0; nd < TESTLENGTH; nd++) + for(md = 0; md < TESTLENGTH; md++) { + TestCountInc(); + ResetTest(0); + BnnOrDigits ((RN(0)+ nd), *( RN(1)+ md)); + ___BnOrDigits___(SN(0), nd, SN(1), md); + if(Check(2)) { + sprintf(e->hist, "%s(n, %d, m, %d)", e->name, nd, md); + if(ShowDiff2(e, 0, 0, "n", nd, 1, "m", md, 1)) + return(1); + } } + return(FALSE); +} + +/* + * BnXorDigits + */ +___BnXorDigits___(n, nd, m, md) BigNum n, m; int nd, md; { + BnnAssign ((Ntmp2+ 0), ( n+ nd), 1); + BnnAndDigits ((Ntmp2+ 0), *( m+ md)); + BnnComplement ((Ntmp2+ 0), 1); + BnnOrDigits ((n+ nd), *( m+ md)); + BnnAndDigits ((n+ nd), *( Ntmp2+ 0)); +} + +TestBnXorDigits(e) struct testenv *e; { + int nd, md; + + e->depend = "(BnAndDigits, BnComplement, BnOrDigits)"; + ResetTest(1); + for(nd = 0; nd < TESTLENGTH; nd++) + for(md = 0; md < TESTLENGTH; md++) { + TestCountInc(); + ResetTest(0); + BnnXorDigits ((RN(0)+ nd), *( RN(1)+ md)); + ___BnXorDigits___(SN(0), nd, SN(1), md); + if(Check(2)) { + sprintf(e->hist, "%s(n, %d, m, %d)", e->name, nd, md); + if(ShowDiff2(e, 0, 0, "n", nd, 1, "m", md, 1)) + return(1); + } } + return(FALSE); +} + +/* + * BnShiftLeft + */ +___BnShiftLeft___(n, nd, nl, m, md, s) BigNum n, m; int nd, nl, md; int s; { + BnnSetDigit ((m+ md), 2); + BnnSetDigit ((Ntmp2+ 0), 1); + while(s--) { + BnnSetToZero ((NtmpBig+ 0), 2); + BnnMultiplyDigit ((NtmpBig+ 0), 2, ( Ntmp2+ 0), 1, *( m+ md)); + BnnAssign ((Ntmp2+ 0), ( NtmpBig+ 0), 1); + } + BnnSetToZero ((NtmpBig+ 0), nl + 1); + BnnMultiplyDigit ((NtmpBig+ 0), nl + 1, ( n+ nd), nl, *( Ntmp2+ 0)); + BnnAssign ((n+ nd), ( NtmpBig+ 0), nl); + BnnAssign ((m+ md), ( NtmpBig+ nl), 1); +} + +TestBnShiftLeft(e) struct testenv *e; { + int nd, nl, md; int s; + + e->depend = "(BnSetToZero, BnMultiplyDigit)"; + ResetTest(1); + for(nd = 0; nd <= TESTLENGTH; nd++) + for(nl = 0; nl <= TESTLENGTH - nd; nl++) + for(md = 0; md < 2; md++) + for(s = 0; s < BN_DIGIT_SIZE; s++) { + TestCountInc(); + ResetTest(0); + *( RN(1)+ md) = BnnShiftLeft ((RN(0)+ nd), nl, s); + ___BnShiftLeft___(SN(0), nd, nl, SN(1), md, s); + if(Check(2)) { + sprintf(e->hist, "%s(n, %d, %d, m, %d, %d)", + e->name, nd, nl, md, s); + if(ShowDiff2(e, 0, 0, "n", nd, nl, "m", md, 1)) + return(1); + } } + return(FALSE); +} + +/* + * BnShiftRight + */ +___BnShiftRight___(n, nd, nl, m, md, s) BigNum n, m; int nd, nl, md; int s; { + if((nl == 0) || (s == 0)) { + BnnSetDigit ((m+ md), 0); + return; + } + BnnAssign ((NtmpBig+ 0), ( n+ nd), nl); + *( NtmpBig+ nl) = BnnShiftLeft ((NtmpBig+ 0), nl, BN_DIGIT_SIZE - s); + BnnAssign ((n+ nd), ( NtmpBig+ 1), nl); + BnnAssign ((m+ md), ( NtmpBig+ 0), 1); +} + +TestBnShiftRight(e) struct testenv *e; { + int nd, nl, md; int s; + + e->depend = "(BnShiftLeft)"; + ResetTest(1); + for(nd = 0; nd <= TESTLENGTH; nd++) + for(nl = 0; nl <= TESTLENGTH - nd; nl++) + for(md = 0; md < 2; md++) + for(s = 0; s < BN_DIGIT_SIZE; s++) { + TestCountInc(); + ResetTest(0); + *( RN(1)+ md) = BnnShiftRight ((RN(0)+ nd), nl, s); + ___BnShiftRight___(SN(0), nd, nl, SN(1), md, s); + if(Check(2)) { + sprintf(e->hist, "%s(n, %d, %d, m, %d, %d)", + e->name, nd, nl, md, s); + if(ShowDiff2(e, 0, 0, "n", nd, nl, "m", md, 1)) + return(1); + } } + return(FALSE); +} + +/* + * BnAddCarry + */ +BigNumCarry +___BnAddCarry___(n, nd, nl, r) BigNum n; int nd, nl; int r;{ + if(r == 0) return(0); + BnnComplement ((n+ nd), nl); + r = BnnSubtractBorrow ((n+ nd), nl, 0); + BnnComplement ((n+ nd), nl); + if(r == 0) return(1); + return(0); +} + +TestBnAddCarry(e) struct testenv *e; { + int nd, nl; int r, l1, l2; + + e->depend = "(BnComplement, BnSubtractBorrow)"; + for(nd = 0; nd <= TESTLENGTH; nd++) + for(nl = 0; nl <= TESTLENGTH - nd; nl++) + for(r = 0; r < 2; r++) { + TestCountInc(); + ResetTest(0); + l1 = BnnAddCarry ((RN(0)+ nd), nl, r); + l2 = ___BnAddCarry___(SN(0), nd, nl, r); + if(Check(1) || l1 != l2) { + sprintf(e->hist, "%s(n, %d, %d, %d)", + e->name, nd, nl, r); + if(ShowDiff1(e, l1, l2, "n", nd, nl)) return(1); + } } + return(FALSE); +} + +/* + * BnAdd + */ +BigNumCarry +___BnAdd___(n, nd, nl, m, md, ml, r) BigNum n, m; int nd, nl, md, ml; BigNumCarry r;{ + BnnComplement ((m+ md), ml); + r = BnnSubtract ((n+ nd), ml, ( m+ md), ml, r); + BnnComplement ((m+ md), ml); + return(BnnAddCarry ((n+ nd + ml), nl - ml, r)); +} + +TestBnAdd(e) struct testenv *e; { + int nd, nl, md, ml; int l1, l2; BigNumCarry r; + + e->depend = "(BnComplement, BnSubtract, BnAddCarry)"; + ResetTest(1); + for(nd = 0; nd <= TESTLENGTH; nd++) + for(nl = 0; nl <= TESTLENGTH - nd; nl++) + for(md = 0; md <= TESTLENGTH - nl; md++) + for(ml = 0; ml <= nl ; ml++) + for(r = 0; r < 2; r++) { + TestCountInc(); + ResetTest(0); + l1 = BnnAdd ((RN(0)+ nd), nl, ( RN(1)+ md), ml, r); + l2 = ___BnAdd___(SN(0), nd, nl, SN(1), md, ml, r); + if(Check(2) || l1 != l2) { + sprintf(e->hist, "%s(n, %d, %d, m, %d, %d, %d)", + e->name, nd, nl, md, ml, r); + if(ShowDiff2(e, l1, l2, "n", nd, nl, "m", md, ml)) + return(1); + } } + return(FALSE); +} + +/* + * BnSubtractBorrow + */ +BigNumCarry +___BnSubtractBorrow___(n, nd, nl, r) BigNum n; int nd, nl; BigNumCarry r;{ + if(r == 1) return(1); + BnnComplement ((n+ nd), nl); + r = BnnAddCarry ((n+ nd), nl, (BigNumCarry) 1); + BnnComplement ((n+ nd), nl); + if(r == 0) return(1); + return(0); +} + +TestBnSubtractBorrow(e) struct testenv *e; { + int nd, nl; int l1, l2; BigNumCarry r; + + e->depend = "(BnComplement, BnAddCarry)"; + for(nd = 0; nd <= TESTLENGTH; nd++) + for(nl = 0; nl <= TESTLENGTH - nd; nl++) + for(r = 0; r < 2; r++) { + TestCountInc(); + ResetTest(0); + l1 = BnnSubtractBorrow ((RN(0)+ nd), nl, r); + l2 = ___BnSubtractBorrow___(SN(0), nd, nl, r); + if(Check(1) || l1 != l2) { + sprintf(e->hist, "%s(n, %d, %d, %d)", + e->name, nd, nl, r); + if(ShowDiff1(e, l1, l2, "n", nd, nl)) return(1); + } } + return(FALSE); +} + +/* + * BnSubtract + */ +BigNumCarry +___BnSubtract___(n, nd, nl, m, md, ml, r) BigNum n, m; int nd, nl, md, ml; BigNumCarry r;{ + BnnComplement ((m+ md), ml); + r = BnnAdd ((n+ nd), ml, ( m+ md), ml, r); + BnnComplement ((m+ md), ml); + return(BnnSubtractBorrow ((n+ nd + ml), nl - ml, r)); +} + +TestBnSubtract(e) struct testenv *e; { + int nd, nl, md, ml; int l1, l2; BigNumCarry r; + + e->depend = "(BnComplement, BnAdd, BnSubtractBorrow)"; + ResetTest(1); + for(nd = 0; nd <= TESTLENGTH; nd++) + for(nl = 0; nl <= TESTLENGTH - nd; nl++) + for(md = 0; md <= TESTLENGTH - nl; md++) + for(ml = 0; ml <= nl ; ml++) + for(r = 0; r < 2; r++) { + TestCountInc(); + ResetTest(0); + l1 = BnnSubtract ((RN(0)+ nd), nl, ( RN(1)+ md), ml, r); + l2 = ___BnSubtract___(SN(0), nd, nl, SN(1), md, ml, r); + if(Check(2) || l1 != l2) { + sprintf(e->hist, "%s(n, %d, %d, m, %d, %d, %d)", + e->name, nd, nl, md, ml, r); + if(ShowDiff2(e, l1, l2, "n", nd, nl, "m", md, ml)) + return(1); + } } + return(FALSE); +} + +/* + * BnMultiplyDigit + */ +BigNumCarry +___BnMultiplyDigit___(p, pd, pl, n, nd, nl, m, md) BigNum p, n, m; int pd, pl, nd, nl, md; { + BigNumCarry r = 0, ret = 0; + + BnnAssign ((Ntmp2+ 0), ( m+ md), 1); + BnnAssign ((NtmpBig+ 0), ( n+ nd), nl); + BnnSetToZero ((NtmpBig+ nl), 1); + while(!BnnIsDigitZero (*(Ntmp2+ 0))) { + if(BnnIsDigitOdd (*(Ntmp2+ 0))) { + r = BnnAdd ((p+ pd), pl, ( NtmpBig+ 0), nl + 1, (BigNumCarry) 0); + if((ret == 0) && (r == 1)) ret = 1; + else if((ret == 1) && (r == 1)) ret = 2; + } + *( Ntmp2+ 1) = BnnShiftRight ((Ntmp2+ 0), 1, 1); + *( Ntmp2+ 1) = BnnShiftLeft ((NtmpBig+ 0), nl + 1, 1); + if(!BnnIsDigitZero (*(Ntmp2+ 1))) ret = 3; + } + return(ret); +} + +TestBnMultiplyDigit(e) struct testenv *e; { + int pd, pl, nd, nl, md; int l1, l2; + + e->depend = "(BnSetToZero, BnIsDigitZero, BnIsDigitOdd, BnAdd, BnShiftRight, BnShiftLeft)"; + ResetTest(1); + ResetTest(2); + for(pd = 0; pd <= TESTLENGTH; pd++) + for(pl = 0; pl <= TESTLENGTH - pd; pl++) + for(nd = 0; nd <= TESTLENGTH - pl; nd++) + for(nl = 0; nl < pl ; nl++) + for(md = 0; md < TESTLENGTH; md++) { + TestCountInc(); + ResetTest(0); + l1 = BnnMultiplyDigit ((RN(0)+pd), pl, (RN(1)+nd), nl, *(RN(2)+md)); + l2 = ___BnMultiplyDigit___(SN(0),pd,pl,SN(1),nd,nl,SN(2),md); + if(Check(3) || l1 != l2) { + sprintf(e->hist, + "BnMultiplyDigit(p, %d, %d, n, %d, %d, m, %d)", + pd, pl, nd, nl, md); + if(ShowDiff3(e,l1,l2,"p",pd,pl,"n",nd,nl,"m",md,1)) + return(1); + } } + return(FALSE); +} + +/* + * BnDivideDigit + */ +TestBnDivideDigit(e) struct testenv *e; { + int nd, nl, md, qd, rd, l2; + + e->depend = "(BnSetToZero, BnMultiplyDigit, BnCompareDigits)"; + ResetTest(2); + ResetTest(3); + for(nd = 0; nd <= TESTLENGTH - 2; nd++) + for(nl = 2; nl <= TESTLENGTH - nd; nl++) + for(md = 0; md < TESTLENGTH; md++) + for(qd = 0; qd < TESTLENGTH - nl + 1 ; qd++) + for(rd = 0; rd < 2; rd++) + if((!BnnIsDigitZero (*(RN(3)+ md))) && + (BnnCompareDigits (*(RN(2)+ nd+nl-1), *( RN(3)+ md)) == -1)) { + TestCountInc(); + ResetTest(0); + ResetTest(1); + *( RN(1)+ rd) = BnnDivideDigit ((RN(0)+ qd), ( RN(2)+ nd), nl, *( RN(3)+ md)); + BnnAssign ((SN(0)+ qd), ( RN(0)+ qd), nl - 1); + BnnAssign ((SN(1)+ rd), ( RN(1)+ rd), 1); + BnnSetToZero ((SN(2)+ nd), nl); + BnnAssign ((SN(2)+ nd), ( SN(1)+ rd), 1); + l2 = BnnMultiplyDigit ((SN(2)+nd), nl, ( SN(0)+qd), nl - 1, *( SN(3)+ md)); + if(Check(4) || l2 != 0) { + sprintf(e->hist, + "BnDivideDigit(q, %d, r, %d, n, %d, %d, m, %d)", + qd, rd, nd, nl, md); + if(ShowDiff4(e, 0, l2, "q", qd, nl - 1, "r", rd, 1, + "n", nd, nl, "m", md, 1)) + return(TRUE); + } } + return(FALSE); +} + +/* + * BnMultiply + */ +___BnMultiply___(p, pd, pl, m, md, ml, n, nd, nl) BigNum p, m, n; int pd, pl, md, ml, nd, nl; { + int ret; + + for (ret = 0; nl-- > 0; pd++, nd++, pl--) + ret += BnnMultiplyDigit ((p+ pd), pl, ( m+ md), ml, *( n+ nd)); + return(ret); +} + +TestBnMultiply(e) struct testenv *e; { + BigNumLength pd, pl, nd, nl, md, ml; int l1, l2; + + e->depend = "(BnSetToZero, BnMultiplyDigit)"; + ResetTest(1); + ResetTest(2); + for(pd = 0; pd <= TESTLENGTH; pd++) + for(pl = 0; pl <= TESTLENGTH - pd && pl <= TESTLENGTH/2; pl++) + for(nd = 0; nd <= TESTLENGTH - pl; nd++) + for(nl = 0; nl < pl && nl <= TESTLENGTH/3; nl++) + { + if (nl <= pl-nl) + { + /* Test squaring */ + TestCountInc(); + ResetTest(0); + l1 = BnnMultiply ((RN(0)+pd), pl, (RN(1)+nd), nl, (RN(1)+nd), nl); + l2 = ___BnMultiply___(SN(0),pd,pl,SN(1),nd,nl,SN(1),nd,nl); + if(Check(3) || l1 != l2) { + sprintf(e->hist, + "BnMultiply(p, %d, %d, n, %d, %d, n, %d, %d)", + pd, pl, nd, nl, nd, nl); + if(ShowDiff3(e,l1,l2,"p",pd,pl,"n",nd,nl,"n",nd,nl)) + return(1); + } + + } + for(md = 0; md <= TESTLENGTH; md++) + for (ml = 0; ml <= pl-nl && ml <= TESTLENGTH/3 && md+ml <= TESTLENGTH; ml++) { + TestCountInc(); + ResetTest(0); + l1 = BnnMultiply ((RN(0)+pd), pl, (RN(1)+nd), nl, (RN(2)+md), ml); + l2 = ___BnMultiply___(SN(0),pd,pl,SN(1),nd,nl,SN(2),md,ml); + if(Check(3) || l1 != l2) { + sprintf(e->hist, + "BnMultiply(p, %d, %d, n, %d, %d, m, %d, %d)", + pd, pl, nd, nl, md, ml); + if(ShowDiff3(e,l1,l2,"p",pd,pl,"n",nd,nl,"m",md,ml)) + return(1); + } } } + return(FALSE); +} + +/* + * Main + */ +typedef struct { + int (*TestFnt)(); + char *NameFnt; +} TESTONE; +TESTONE AllTest[] = { + Generique, "Generic Functions", + TestBnSetToZero, "BnSetToZero", + TestBnAssign, "BnAssign", + TestBnNumDigits, "BnNumDigits", + TestBnNumLeadingZeroBitsInDigit, "BnNumLeadingZeroBitsInDigit", + TestBnIsDigitZero, "BnIsDigitZero", + TestBnIsDigitNormalized, "BnIsDigitNormalized", + TestBnIsDigitOdd, "BnIsDigitOdd", + TestBnCompareDigits, "BnCompareDigits", + TestBnComplement, "BnComplement", + TestBnAndDigits, "BnAndDigits", + TestBnOrDigits, "BnOrDigits", + TestBnXorDigits, "BnXorDigits", + TestBnShiftLeft, "BnShiftLeft", + TestBnShiftRight, "BnShiftRight", + TestBnAddCarry, "BnAddCarry", + TestBnAdd, "BnAdd", + TestBnSubtractBorrow, "BnSubtractBorrow", + TestBnSubtract, "BnSubtract", + TestBnMultiplyDigit, "BnMultiplyDigit", + TestBnDivideDigit, "BnDivideDigit", + TestBnMultiply, "BnMultiply", +}; + +main(n, s) int n; char **s; { + struct testenv realenv, *e = &realenv; + int i, j, nbtest, SizeAllTest; + + /* Initialisations de l'environnement de test. */ + e->flag = 1; + e->depend = "()"; + /* Allocation des 2 nombres globaux. */ + Ntmp2 = BnAlloc(2); + NtmpBig = BnAlloc(2 * TESTLENGTH); + NumbProto = BnAlloc(TESTLENGTH); + /* Creation du nombre prototype. */ + BnnSetDigit ((NumbProto+ 0), 0); /* Les 2 premiers a` ze'ro. */ + BnnSetDigit ((NumbProto+ 1), 0); + for(i=0; i < TESTLENGTH/4 - 1; i++) /* Le premier quart est la */ + BnnSetDigit ((NumbProto+ i + 2), i + 1); /* suite 1, 2, 3, ... */ + /* Le 2nd quart est le 1er shifte de BN_DIGIT_SIZE - 2. 0x4000 0x8000 ...*/ + BnnAssign ((NumbProto+ QTL + 1), ( NumbProto+ 2), QTL - 1); + *( NumbProto+ 0) = BnnShiftLeft ((NumbProto+ QTL + 1), QTL - 1, BN_DIGIT_SIZE - 2); + /* La 2nd moitie est l'inverse logique de la 1ere */ + BnnAssign ((NumbProto+ DTL), ( NumbProto+ 0), DTL); + BnnComplement ((NumbProto+ DTL), DTL); + /* Allocation des nombres utilise's */ + for(i=0; i < 5; i++) { + RN(i) = BnAlloc(TESTLENGTH); + SN(i) = BnAlloc(TESTLENGTH); + } + if(n > 1 && s[1][0] == '-') { + CallDummy = atoi(s[1]+1); + n--; + s++; + } + if(n == 1) { + printf("%s [-CallDummy#] v|a|TestNum\n", s[0]); + } + /* On y va */ + SizeAllTest = (sizeof(AllTest)/sizeof(AllTest[0])); + for(i = 1; i < n; i++) { + if(s[i][0] == 'm') { + /* 0 = No skip; 1 = skip to next; else STOP */ + e->flag = atoi(&s[i][1]); + } else if(s[i][0] == 'a') { + for(i = 0; i < SizeAllTest; i++) + dotest(e, i); + } else if(s[i][0] == 'v') { + for(j = 0; j < SizeAllTest; j++) + seetest(j); + } else { + nbtest = atoi(s[i]); + if((nbtest < 0) || (nbtest >= SizeAllTest)) + printf("Test %d is invalid\n", nbtest); + else dotest(e, nbtest); +} } } + +dotest(e, n) struct testenv *e; int n; { + seetest(n); + TestCount = 0; + e->name = AllTest[n].NameFnt; + if(((*(AllTest[n].TestFnt)) (e)) && e->flag > 1) exit(0); + printf("%d tests were performed\n", TestCount); +} + +seetest(n) int n; { + printf("%d. Testing %s\n", n, AllTest[n].NameFnt); +} + |