DWORD WINAPI j_ran(HWND hWnd) { char bdr[HSIZE]={0}; BIGD r; r = bdNew(); bdRandomSeeded(r, OSIZE*4, (unsigned char*)"", 0x00, pseudo_rand); bdConvToHex(r, bdr, HSIZE); SetDlgItemText(hWnd, IDC_UID, bdr); bdFree(&r); return(0); }
int main(void) { BIGD u, v, w, q, r, p, b, a; BIGD n, e, m, c, z, mz, cz, t; bdigit_t overflow; int cmp, res; unsigned char ff[64], bytes[16]; int i, mc, jac; size_t nbytes; char s[128]; /* MSVC memory leak checking stuff */ #if _MSC_VER >= 1100 _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE ); _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT ); _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE ); _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT ); #endif printf("Tests for BIGD functions\n"); /* Initialise */ u = bdNew(); v = bdNew(); w = bdNew(); p = bdNew(); q = bdNew(); r = bdNew(); printf("SIMPLE ARITHMETIC OPERATIONS...\n"); pr_msg("At start w=", w); assert(bdIsZero(w)); /* Addition */ /* 1 + 1 = 2 */ bdSetShort(u, 1); bdSetShort(v, 1); bdAdd(w, u, v); pr_msg("1+1=", w); assert(bdShortCmp(w, 2) == 0); /* Add with digit overflow */ bdSetShort(u, 0xffffffff); bdSetShort(v, 0xffffffff); bdAdd(w, u, v); pr_msg("ffffffff+ffffffff=", w); /* ffffffff+ffffffff=00000001 fffffffe */ assert(bdSizeof(w) == 2); /* Bigger random digits */ bdSetRandTest(u, 10); bdSetRandTest(v, 10); bdAdd(w, u, v); pr_msg("u=\n", u); pr_msg("v=\n", v); pr_msg("w=u+v=\n", w); /* Subtract */ bdSubtract(r, w, v); pr_msg("w-v=\n", r); assert(bdCompare(r, u) == 0); /* Multiplication */ /* 2 * 3 = 6 */ bdSetShort(u, 2); bdSetShort(v, 3); bdMultiply(w, u, v); pr_msg("2 * 3=", w); assert(bdShortCmp(w, 6) == 0); bdSetShort(u, 0xffffffff); bdSetShort(v, 0xffffffff); bdMultiply(w, u, v); pr_msg("ffffffff*ffffffff=", w); /* ffffffff*ffffffff=fffffffe 00000001 */ assert(bdGetBit(w, 0) == 1); /* Use ShortMult */ bdShortMult(p, u, 0xffffffff); pr_msg("(Short)ffffffff*ffffffff=", p); assert(bdCompare(p, w) == 0); /* Use larger random u, v */ bdSetRandTest(u, 10); bdSetRandTest(v, 20); pr_msg("u=\n", u); pr_msg("v=\n", v); /* Use ShortMult by one: w = v * 1 */ bdShortMult(w, v, 1); pr_msg("(Short)v*1=\n", w); assert(bdCompare(w, v) == 0); /* Use ShortMult by two */ bdShortMult(w, u, 2); pr_msg("(Short)u*2=\n", w); assert(bdIsEven(w)); /* Big multiplication */ bdMultiply(w, u, v); pr_msg("w=u*v=\n", w); /* Divide expecting q = w/v == u and r = w%v == 0 */ bdDivide(q, r, w, v); pr_msg("w/v=\n", q); pr_msg("w%v=", r); assert(bdIsEqual(q, u)); assert(bdShortCmp(r, 0) == 0); /* Modulo */ bdIncrement(w); bdModulo(r, w, v); pr_msg("w+1 mod v=", r); assert(bdShortCmp(r, 1) == 0); bdDecrement(w); bdModulo(r, w, u); pr_msg("w+1-1 mod u=", r); assert(bdShortCmp(r, 0) == 0); /* Use a short divisor q=w/2 */ bdShortDiv(q, r, w, 2); pr_msg("(ShortDiv)w/2=\n", q); pr_msg("(ShortDiv)w%2=", r); printf("w is %s\n", bdIsOdd(w) ? "ODD" : "EVEN"); bdShortMod(r, w, 2); pr_msg("w mod 2=", r); bdIncrement(w); printf("w+1 is %s\n", bdIsOdd(w) ? "ODD" : "EVEN"); bdShortMod(r, w, 2); pr_msg("++w mod 2=", r); bdDecrement(w); /* Check with short mult u = q*2 */ bdShortMult(u, q, 2); pr_msg("(ShortMult) (w/2) * 2=\n", u); printf("SQUARE AND SQUARE ROOT...\n"); /* Square a random number w = u^2 */ bdSetRandTest(u, 10); pr_msg("random u=\n", u); bdSquare(w, u); pr_msg("(Square) u^2=", w); /* check against product p = u * u */ bdMultiply(p, u, u); pr_msg("u*u=", p); assert(bdIsEqual(p, w)); /* Compute integer square root [new in v2.1] */ bdSqrt(p, w); pr_msg("sqrt(w)=", p); assert(bdIsEqual(p, u)); printf("MODULAR ARITHMETIC...\n"); /* Check that (u mod n + v mod n) mod n == (u+v) mod n */ bdSetRandTest(u, 10); bdSetRandTest(v, 10); bdSetRandTest(w, 10); pr_msg("(Modulo)\nNew random u=", u); pr_msg("v=", v); pr_msg("w=", w); /* r = u mod w */ bdModulo(r, u, w); /* q = v mod w */ bdModulo(q, v, w); /* q = u mod n + v mod n */ bdAdd(q, q, r); /* r = (u mod w + v mod w) mod w */ bdModulo(r, q, w); pr_msg("(u mod w + v mod w) mod w=\n", r); /* q = (u+v) mod w */ bdSetEqual(p, u); bdAdd(p, p, v); bdModulo(q, p, w); pr_msg("(u+v) mod w=\n", q); assert(bdIsEqual(r, q)); /* Clear and start again */ bdSetZero(u); bdSetZero(v); bdSetZero(w); printf("ARITHMETIC BOUNDARY CONDITIONS...\n"); /* This causes Divide algorithm to `Add Back' with 32-bit digits See Knuth 4.3.1 Algorithm D Step D6 */ printf("Check `Add Back' in Divide algorithm\n"); bdConvFromHex(u, "7fffffff 80000001 00000000 00000000"); bdConvFromHex(v, "00000000 80000000 80000002 00000005"); bdDivide(q, r, u, v); pr_msg("u=", u); pr_msg("v=", v); pr_msg("q=u/v=", q); pr_msg("r=u mod v=", r); /* check that qv + r = u */ bdMultiply(w, q, v); bdAdd(w, w, r); pr_msg("qv+r=", w); assert(bdIsEqual(w, u)); /* And check that r = u mod v >= (1-2/b)v See Knuth 4.3.1 Exercise 21 */ bdConvFromHex(p, "1 00000000"); bdSetEqual(w, p); bdShortSub(w, w, 2); bdMultiply(u, w, v); bdDivide(q, w, u, p); pr_msg("(1-2/b)=", q); cmp = bdCompare(r, q); printf("u mod v %s (1-2/b)v\n", (cmp >= 0 ? ">=" : "<")); /* Cope, sort of, with `negative' numbers */ printf("Go ``negative''...\n"); bdSetZero(u); overflow = bdShortSub(w, u, 2); pr_msg("w=0-2=", w); printf("overflow=%" PRIuBIGD "\n", overflow); overflow = bdIncrement(w); pr_msg("w+1=", w); printf("overflow=%" PRIuBIGD "\n", overflow); overflow = bdIncrement(w); pr_msg("(Note error!) w+1=", w); printf("overflow=%" PRIuBIGD "\n", overflow); bdSetZero(u); overflow = bdShortAdd(u, u, 1); pr_msg("u=0+1=", u); printf("overflow=%" PRIuBIGD "\n", overflow); bdSetZero(u); bdSetZero(v); bdAdd(w, u, v); pr_msg("0+0=", w); /* Set u = v = ffff...ffff */ for (i = 0; i < sizeof(ff); i++) ff[i] = 0xff; bdConvFromOctets(u, ff, sizeof(ff)); bdConvFromOctets(v, ff, sizeof(ff)); pr_msg("u=", u); pr_msg("v=", v); /* Compute u * v */ bdMultiply(w, u, v); pr_msg("w = u * v =\n", w); /* Set v = w / u */ bdDivide(v, r, w, u); pr_msg("v = w / u =\n", v); pr_msg("rem=", r); assert(bdIsEqual(u, v)); assert(bdShortCmp(r, 0) == 0); bdIncrement(u); bdDecrement(v); bdMultiply(w, u, v); pr_msg("w = ++u * --v =\n", w); bdDivide(w, r, u, v); pr_msg("q = u / v =", w); pr_msg("rem=", r); assert(bdShortCmp(w, 1) == 0); assert(bdShortCmp(r, 2) == 0); /* Clear and start again */ bdSetZero(u); bdSetZero(v); bdSetZero(w); bdSetShort(u, 0); /* Fixed [v2.3]: This used to cause an error */ bdPrintDecimal("bdSetShort(u, 0)=> u=", u, "\n"); bdSetShort(v, 3); bdModulo(w, u, v); bdPrintDecimal("0 mod 3=", w, "\n"); /* Set a new random value for v */ bdSetRandTest(v, 10); pr_msg("Random v=\n", v); bdShortAdd(u, v, 1); pr_msg("u = v + 1 =\n", u); cmp = bdCompare(u, v); printf("bdCompare(u-v) = %d\n", cmp); assert(cmp > 0); cmp = bdCompare(v, u); printf("bdCompare(v-u) = %d\n", cmp); assert(cmp < 0); cmp = bdCompare(u, u); printf("bdCompare(u-u) = %d\n", cmp); assert(cmp == 0); /* Compare with short */ bdSetShort(w, 0xfffffffe); pr_msg("w=", w); cmp = bdShortCmp(w, 1); assert(cmp > 0); printf("bdShortCmp(w-1) = %d\n", cmp); cmp = bdShortCmp(w, 0xffffffff); assert(cmp < 0); printf("bdShortCmp(w-0xffffffff) = %d\n", cmp); cmp = bdShortCmp(w, 0xfffffffd); printf("bdShortCmp(w-0xfffffffd) = %d\n", cmp); assert(cmp > 0); printf("BIT SHIFT OPERATIONS...\n"); /* Try shifting bits */ pr_msg("w = ", w); bdFree(&u); u = bdNew(); bdShiftLeft(u, w, 2); pr_msg("w << 2 = ", u); assert(bdGetBit(u, 33) == 1); bdShiftRight(v, u, 3); pr_msg("(w << 2) >> 3 = ", v); assert(bdGetBit(v, 31) == 0); /* Bigger shift */ bdShiftLeft(u, w, 128); pr_msg("w << 128 = ", u); assert(bdGetBit(u, 159) == 1); bdShiftRight(v, u, 129); pr_msg("(w << 128) >> 129 = ", v); assert(bdGetBit(v, 31) == 0); /* Use a new variable */ b = bdNew(); bdSetZero(b); /* overkill */ bdSetBit(b, 510, 1); bdSetBit(b, 477, 1); bdSetBit(b, 31, 1); bdSetBit(b, 0, 1); pr_msg("b=\n", b); bdSetBit(b, 512, 1); bdSetBit(b, 31, 0); pr_msg("b'=\n", b); printf("Bit 512 is %d\n", bdGetBit(b, 512)); assert(bdGetBit(b, 512) == 1); printf("Bit 511 is %d\n", bdGetBit(b, 511)); assert(bdGetBit(b, 511) == 0); assert(bdGetBit(b, 477) == 1); /* NB one-based bit lengths so expecting 513 */ printf("Bit Length = %u\n", bdBitLength(b)); assert(bdBitLength(b) == 513); pr_msg("b'=\n", b); /* Destroy b */ bdFree(&b); printf("RANDOM NUMBER GENERATION...\n"); /* Create a random number using `my_rand' callback function */ bdRandomSeeded(r, 508, (const unsigned char*)"", 0, my_rand); pr_msg("random=\n", r); /* NB bit length may be less than 508 */ printf("%u bits\n", bdBitLength(r)); assert(bdBitLength(r) <= 508); /* Create a random number using the internal RNG */ bdRandomBits(r, 509); pr_msg("random=\n", r); printf("%u bits\n", bdBitLength(r)); assert(bdBitLength(r) <= 509); printf("PRIME NUMBERS...\n"); /* Generate two random primes */ printf("Generating two primes...\n"); bdGeneratePrime(p, 128, 5, (const unsigned char*)"1", 1, my_rand); pr_msg("prime p=\n", p); bdGeneratePrime(q, 128, 5, (const unsigned char*)"abcdef", 6, my_rand); pr_msg("prime q=\n", q); /* Check primality with more tests (64 vs 5) */ /* NB vv small chance this could fail */ printf("Checking prime: p "); res = bdIsPrime(p, 64); printf("%s\n", (res ? "is OK" : "is NOT prime!!")); /* And again using Fermat test */ res = fermat_test(p); if (res == 0) printf("WARNING: p failed Fermat test.\n"); /* w = product pq */ bdMultiply(w, p, q); pr_msg("pq=\n", w); /* Product pq should not be prime */ res = bdIsPrime(w, 5); printf("Composite pq %s\n", (res ? "IS prime" : "is NOT prime")); assert(res == 0); /* Check GCD: gcd(pq, p) == p */ bdGcd(r, w, p); pr_msg("gcd(pq, p) =\n", r); assert(bdIsEqual(r, p)); /* --Modular inversion-- */ printf("MODULAR INVERSION...\n"); /* set v to be a small random multiplier */ bdSetRandTest(v, 1); bdIncrement(v); /* Make sure not zero */ pr_msg("multiplier, v=", v); /* set u = vp - 1 */ bdMultiply(u, v, p); bdDecrement(u); pr_msg("p=\n", p); pr_msg("u = vp - 1 =\n", u); /* compute w = u^-1 mod p */ res = bdModInv(w, u, p); pr_msg("w = u^-1 mod p=\n", w); assert(res == 0); /* check that wu mod p == 1 */ bdModMult(r, w, u, p); pr_msg("wu mod p = ", r); assert(bdShortCmp(r, 1) == 0); /* Try mod inversion that should fail */ /* Set u = pq so that gcd(u, p) != 1 */ bdMultiply(u, p, q); res = bdModInv(w, u, p); printf("w = (pq)^-1 mod p returns (expected) error %d\n", res); assert(res != 0); pr_msg("output, w=", w); /* Do some bit string operations */ printf("BIT STRING OPERATIONS...\n"); /* Use XOR to swop two variables without a temp variable, i.e. a = a XOR b; b = a XOR b; a = a XOR b; */ printf("Swop u and w:\n"); /* Generate 2 random numbers (u,w) each 144 bits long */ bdRandomBits(u, 144); bdRandomBits(w, 144); pr_msg("u= ", u); pr_msg("w= ", w); /* remember these for later (p=u, q=w) */ bdSetEqual(p, u); bdSetEqual(q, w); /* Swop using XOR */ bdXorBits(u, u, w); bdXorBits(w, u, w); bdXorBits(u, u, w); pr_msg("u'=", u); pr_msg("w'=", w); /* check they have swopped accurately */ assert(bdIsEqual(u, q)); assert(bdIsEqual(w, p)); /* Try some simple AND and OR ops */ printf("AND and OR ops:\n"); /* Set every even bit in u and every odd bit in v */ bdSetZero(u); bdSetZero(v); for (i = 0; i < 144 / 2; i++) { bdSetBit(u, (i * 2), 1); bdSetBit(v, (i * 2) + 1, 1); } pr_msg("u= ", u); pr_msg("v= ", v); bdAndBits(w, u, v); pr_msg("u AND v=", w); /* expected answer = zero */ assert(bdIsZero(w)); bdOrBits(w, u, v); pr_msg("u OR v= ", w); /* expected answer p = 2^144 - 1 */ bdSetZero(p); bdSetBit(p, 144, 1); bdDecrement(p); pr_msg("2^144-1=", p); assert(bdIsEqual(p, w)); /* Invert all bits */ bdSetZero(p); bdSetZero(q); bdSetShort(p, 0xfffe); bdShiftLeft(p, p, 32); bdShortAdd(p, p, 0xfffe); pr_msg("p= ", p); bdNotBits(q, p); pr_msg("NOT p=", q); /* check p AND (NOT p) == 0 */ bdAndBits(w, p, q); pr_msg("p AND (NOT p)=", w); assert(bdIsZero(w)); /* Compose a 400-bit string by concatenating random 160-bit sections and then truncating the result */ printf("Bit string concatenation and truncation:\n"); /* ALGORITHM: (based on a similar one in RFC 2631/ANSI X.42) Set m' = m/160 where / represents integer division with rounding upwards Set U = 0 For i = 0 to m' - 1 Set R = FUNC_160 and V = FUNC_160 where FUNC_160 generates a unique 160-bit value U = U + (R XOR V) * 2^(160 * i) Form q from U by computing U mod (2^m) and setting the most significant bit (the 2^(m-1) bit) and the least significant bit to 1. In terms of boolean operations, q = U OR 2^(m-1) OR 1. Note that 2^(m-1) < q < 2^m */ /* In this example, m=400 and m'=3, and we just generate 160-bit random values */ mc = 3; bdSetZero(u); /* Set U = 0 */ for (i = 0; i < mc; i++) { bdRandomBits(r, 160); /* R = FUNC_160 */ bdRandomBits(v, 160); /* V = FUNC_160 */ bdXorBits(p, r, v); /* p = (R XOR V) */ /* w = p * 2^160i, i.e. shift p left by 160i bits */ bdShiftLeft(w, p, (160 * i)); bdOrBits(u, u, w); /* q = q + w */ printf("w(%d)=", i); pr_msg("", w); } pr_msg("u = w(0)+w(1)+w(2) =\n", u); bdModPowerOf2(u, 400); /* U = U mod (2^m) */ pr_msg("u = u mod (2^m) = // `ModPowerOf2' \n", u); /* q = U OR 2^(m-1) OR 1 */ bdSetEqual(q, u); /* q = U */ bdSetBit(q, 400-1, 1); /* q = q OR 2^(m-1) */ bdSetBit(q, 0, 1); /* q = q OR 1 */ pr_msg("q = u OR 2^(m-1) OR 1 =\n", q); /* Check that 2^(m-1) < q < 2^m */ printf("BitLength(q)=%d\n", bdBitLength(q)); bdSetZero(p); bdSetBit(p, 400-1, 1); /* p = 2^(m-1) */ assert(bdCompare(p, q) < 1); /* p < q */ bdSetZero(r); bdSetBit(r, 400, 1); /* r = 2^m */ assert(bdCompare(q, r) < 1); /* q < r */ printf("OK, checked that 2^(m-1) < q < 2^m\n"); /* Create a new set for Modular exponentiation test */ printf("MODULAR EXPONENTIATION...\n"); n = bdNew(); e = bdNew(); m = bdNew(); c = bdNew(); z = bdNew(); mz = bdNew(); cz = bdNew(); t = bdNew(); /* n is a prime modulus */ printf("Generating a prime...\n"); bdGeneratePrime(n, 513, 5, NULL, 0, my_rand); pr_msg("prime n=\n", n); printf("bdBitLength(n)=%u bdSizeof(n)=%u\n", bdBitLength(n), bdSizeof(n)); /* Check primality using Fermat test */ res = fermat_test(n); if (res == 0) printf("WARNING: n failed Fermat test.\n"); /* exponent e is a single random digit */ bdSetShort(e, bdRandDigit()); pr_msg("e=", e); /* base m is some random number m < n */ bdSetRandTest(m, bdSizeof(n) - 1); pr_msg("random m=\n", m); /* Compute c = m^e mod n */ bdModExp(c, m, e, n); pr_msg("c = m^e mod n =\n", c); /* Now use a random z and check that c.z^e == (m.z)^e (mod n) */ bdSetRandTest(z, bdSizeof(n)); pr_msg("random z=\n", z); /* Compute cz = c.z^e mod n (Note use of temp t) */ bdModExp(t, z, e, n); bdModMult(cz, c, t, n); pr_msg("c.z^e mod n=\n", cz); /* Compute mz = (m.z)^e mod n */ bdModMult(t, m, z, n); bdModExp(mz, t, e, n); pr_msg("(m.z)^e mod n==\n", mz); if (!bdIsEqual(mz, cz)) printf("ERROR: (c.z^e == (m.z)^e (mod n) DOES NOT MATCH m'\n"); else printf("c.z^e == (m.z)^e (mod n) checks OK\n"); assert(bdIsEqual(mz, cz)); /* Do some conversions with hex and decimal strings */ bdSetZero(u); bdConvFromHex(u, "DeadBeefCafeBabeBeddedDefacedDeafBeadFacade"); pr_msg("From Hex: ", u); bdConvToHex(u, s, sizeof(s)); printf("To Hex: %s\n", s); bdConvFromDecimal(u, "1234567890123456789012345678901234567890"); pr_msg("From Decimal: ", u); bdConvToDecimal(u, s, sizeof(s)); printf("To Decimal: %s\n", s); cmp = strcmp(s, "1234567890123456789012345678901234567890"); assert(cmp == 0); /* 987654321 x 81 = 80000000001 */ bdConvFromDecimal(u, "987654321"); bdShortMult(v, u, 81); bdConvToDecimal(v, s, sizeof(s)); printf("987654321 x 81 = %s\n", s); cmp = strcmp(s, "80000000001"); assert(cmp == 0); /* 123456789 x 9 + 10 = 1111111111 */ bdConvFromDecimal(u, "123456789"); bdShortMult(v, u, 9); bdShortAdd(w, v, 10); bdConvToDecimal(w, s, sizeof(s)); printf("123456789 x 9 + 10 = %s\n", s); cmp = strcmp(s, "1111111111"); assert(cmp == 0); /* Convert an empty decimal string to a BIGD */ bdSetShort(u, 0xfdfdfdfd); bdConvFromDecimal(u, ""); pr_msg("bdConvFromDecimal(u, '')=", u); assert(bdIsZero(u)); /* ditto an empty hex string */ bdSetShort(u, 0xfdfdfdfd); bdConvFromHex(u, ""); pr_msg("bdConvFromHex(u, '')=", u); assert(bdIsZero(u)); /* Convert zero BIGD value to a decimal string */ bdSetZero(u); bdConvToDecimal(u, s, sizeof(s)); printf("Decimal zero = '%s'\n", s); cmp = strcmp(s, "0"); assert(cmp == 0); /* ditto to a hex string */ bdConvToHex(u, s, sizeof(s)); printf("Hex zero = '%s'\n", s); cmp = strcmp(s, "0"); assert(cmp == 0); /* Convert a zero BIGD to an array of octets */ memset(bytes, 0xdf, sizeof(bytes)); bdSetZero(u); nbytes = bdConvToOctets(u, bytes, sizeof(bytes)); printf("bdConvToOctets returns %d: ", nbytes); /* show that all bytes are zero */ pr_bytesmsg("", bytes, sizeof(bytes)); assert(0 == bytes[sizeof(bytes)-1] && 0 == bytes[0]); /* Convert an zero-length array of octets to a BIGD */ bdSetShort(u, 0xfdfdfdfd); bdConvFromOctets(u, bytes, 0); pr_msg("bdConvFromOctets(nbytes=0)=", u); assert(bdIsZero(u)); bdFree(&n); /* Try computing some Jacobi and Legendre symbol values */ a = bdNew(); n = bdNew(); bdSetShort(a, 158); bdSetShort(n, 235); jac = bdJacobi(a, n); printf("Jacobi(158, 235)=%d\n", jac); assert(-1 == jac); bdSetShort(a, 2183); bdSetShort(n, 9907); jac = bdJacobi(a, n); printf("Jacobi(2183, 9907)=%d\n", jac); assert(1 == jac); bdSetShort(a, 1001); jac = bdJacobi(a, n); printf("Jacobi(1001, 9907)=%d\n", jac); assert(-1 == jac); bdShortMult(a, n, 10000); jac = bdJacobi(a, n); printf("Jacobi(10000 * 9907, 9907)=%d\n", jac); assert(0 == jac); printf("SQUARE AND SQUARE ROOT...\n"); /* Square a random number w = u^2 */ bdSetRandTest(u, 10); bdPrintHex("random u=\n", u, "\n"); bdSquare(w, u); bdPrintHex("(Square) u^2=", w, "\n"); /* check against product p = u * u */ bdMultiply(p, u, u); bdPrintHex("u*u=", p, "\n"); assert(bdIsEqual(p, w)); /* and check against power function */ bdPower(p, u, 2); bdPrintHex("u power 2=", p, "\n"); assert(bdIsEqual(p, w)); /* Compute integer square root [new in v2.1] */ bdSqrt(p, w); bdPrintHex("sqrt(u^2)=", p, "\n"); assert(bdIsEqual(p, u)); /* Now test sqrt(u^2 - 1) */ bdDecrement(w); bdPrintHex("u^2-1=", w, "\n"); bdSqrt(r, w); bdPrintHex("sqrt(u^2-1)=", r, "\n"); /* Check difference is 1 */ bdSubtract(q, p, r); bdPrintHex("difference=", q, " (expected 1)\n"); assert(bdShortCmp(q, 1) == 0); printf("\nCUBE AND CUBE ROOT...\n"); /* Cube a random number w = u^2 */ bdPrintHex("u=", u, "\n"); bdSquare(v, u); bdMultiply(w, v, u); bdPrintHex("(Cube) u^3=", w, "\n"); /* Check that power function works */ bdPower(v, u, 0); bdPrintHex("u^0=", v, "\n"); bdPower(v, u, 1); bdPrintHex("u^1=", v, "\n"); bdPower(v, u, 3); bdPrintHex("(Power) u^3=", v, "\n"); assert(bdIsEqual(v, w)); /* Compute integer cube root (new in [v2.3]) */ bdCubeRoot(p, w); bdPrintHex("cuberoot(u^3)=", p, "\n"); assert(bdIsEqual(p, u)); /* Now test cuberoot(u^2 - 1) */ bdDecrement(w); bdPrintHex("u^3-1=", w, "\n"); bdCubeRoot(r, w); bdPrintHex("cuberoot(u^3-1)=", r, "\n"); /* Check difference is 1 */ bdSubtract(q, p, r); bdPrintHex("difference=", q, " (expected 1)\n"); assert(bdShortCmp(q, 1) == 0); /* Finally, show the current version number */ printf("\nVERSION=%d\n", bdVersion()); /* Clear up */ bdFree(&u); bdFree(&v); bdFree(&w); bdFree(&q); bdFree(&r); bdFree(&p); bdFree(&a); bdFree(&n); bdFree(&e); bdFree(&m); bdFree(&c); bdFree(&z); bdFree(&mz); bdFree(&cz); bdFree(&t); printf("OK, successfully completed tests.\n"); return 0; }