//
//
//
//
//
///* $Id: t_bdTest.c $ */
//
///***** BEGIN LICENSE BLOCK *****
 //*
 //* This Source Code Form is subject to the terms of the Mozilla Public
 //* License, v. 2.0. If a copy of the MPL was not distributed with this
 //* file, You can obtain one at http://mozilla.org/MPL/2.0/.
 //*
 //* Copyright (c) 2001-16 David Ireland, D.I. Management Services Pty Limited
 //* <http://www.di-mgt.com.au/bigdigits.html>. All rights reserved.
 //*
 //***** END LICENSE BLOCK *****/
///*
 //* Last updated:
 //* $Date: 2016-03-31 09:51:00 $
 //* $Revision: 2.6.1 $
 //* $Author: dai $
 //*/
//
///* Various tests of "bd" functions, not exhaustive */
//
//#if _MSC_VER >= 1100
	///* Detect memory leaks in MSVC++ */ 
	//#define _CRTDBG_MAP_ALLOC
	//#include <stdlib.h>
	//#include <crtdbg.h>
//#else
	//#include <stdlib.h>
//#endif
//
//#ifdef NDEBUG
//#undef NDEBUG
//#endif
//#include <assert.h>
//#include <stdio.h>
//#include <string.h>
//#include <time.h>
//#include "bigd.h"
//#include "bigdRand.h"
//
//static void pr_bytesmsg(const char *msg, unsigned char *bytes, size_t nbytes)
///* Display a message followed by the hex values of a byte array */
//{
	//size_t i;
	//printf("%s", msg);
	//for (i = 0; i < nbytes; i++)
		//printf("%02x", bytes[i]);
	//printf("\n");
//}	
//
//int my_rand(unsigned char *bytes, size_t nbytes, const unsigned char *seed, size_t seedlen)
///* Our own (very insecure) random generator call-back function using good old rand() 
   //This demonstrates the required format for BD_RANDFUNC
   //-- replace this in practice with your own cryptographically-secure function.
//*/
//{
	//unsigned int myseed;
	//size_t i;
	//int offset;
//
	///* Use time - then blend in seed, if any */
	//myseed = (unsigned)time(NULL);
	//if (seed)
	//{
		//for (offset = 0, i = 0; i < seedlen; i++, offset = (offset + 1) % sizeof(unsigned))
			//myseed ^= ((unsigned int)seed[i] << (offset * 8));
	//}
//
	//srand(myseed);
	//while (nbytes--)
	//{
		//*bytes++ = rand() & 0xFF;
	//}
//
	//return 0;
//}
//
//int fermat_test(BIGD n)
//{
///* Carries out a quick Fermat primality test on n > 4.
   //Returns 1 if n is prime and 0 if composite or -1 if n < 5.
   //This is not foolproof but we use it as a 
   //check on our main bdIsPrime function.
   //It will return a false positive for Fermat Liars, which
   //are very rare.
//*/
	//BIGD a, e, r;
	//int isprime = 1;
//
	///* For any integer a, 1<=a<=n-1, if a^(n-1) mod n != 1
	   //then n is composite. */
//
	//if (bdShortCmp(n, 5) < 0) return -1;
//
	//a = bdNew();
	//e = bdNew();
	//r = bdNew();
	///* e = n -1 */
	//bdSetEqual(e, n);
	//bdDecrement(e);
//
	///* Set a = 2 and compute a^(n-1) mod n */
	//bdSetShort(a, 2);
	//bdModExp(r, a, e, n);
	//if (bdShortCmp(r, 1) != 0)
		//isprime = 0;
//
	///* a = 3 */
	//bdSetShort(a, 3);
	//bdModExp(r, a, e, n);
	//if (bdShortCmp(r, 1) != 0)
		//isprime = 0;
//
	///* a = 5 */
	//bdSetShort(a, 5);
	//bdModExp(r, a, e, n);
	//if (bdShortCmp(r, 1) != 0)
		//isprime = 0;
//
	//bdFree(&a);
	//bdFree(&e);
	//bdFree(&r);
//
	//return isprime;
//}
//
///** Compute w = u - v using cutoff subtraction so `w >= 0` always. 
 //*  @return 1 if subtraction underflowed or 0 for normal result
 //*/
//int cutoff_subtraction(BIGD w, BIGD u, BIGD v)
//{
	//int carry = 0;
	//if (bdCompare(u, v) < 0) {
		//bdSetZero(w);
		//carry = 1;
	//}
	//else {
		//bdSubtract(w, u, v);
	//}
	//return carry;
//}
//
//int main(void)
//{
	//BIGD u, v, w, q, r, p, b, a;
	//BIGD n, e, m, c, z, mz, cz, t;
	//BIGD x, y;
	//bdigit_t overflow, d;
	//int cmp, res;
	//unsigned char ff[64], bytes[16];
	//int i, mc, jac;
	//size_t nbytes, nbits;
	//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");
//
	///* Initialize - new way in [v2.6]*/
	//bdNewVars(&u, &v, &w, &p, &q, &r, &x, &y);
	////u = bdNew();
	////v = bdNew();
	////w = bdNew();
	////p = bdNew();
	////q = bdNew();
	////r = bdNew();
	////x = bdNew();
	////y = bdNew();
//
	//printf("\nSIMPLE ARITHMETIC OPERATIONS...\n");
	//bdPrintDecimal("At start w=", w, "\n");
	//assert(bdIsZero(w));
//
	///* Addition */
	///* 1 + 1 = 2 */
	//bdSetShort(u, 1);
	//bdSetShort(v, 1);
	//bdAdd(w, u, v);
	//bdPrintDecimal("1+1=", w, "\n");
	//assert(bdShortCmp(w, 2) == 0);
//
	///* Add with digit overflow */
	//bdSetShort(u, 0xffffffff);
	//bdSetShort(v, 0xffffffff);
	//bdAdd(w, u, v);
	//bdPrintHex("ffffffff+ffffffff=", w, "\n");
	///* ffffffff+ffffffff=00000001 fffffffe */
	//assert(bdSizeof(w) == 2);
//
	///* Bigger random digits */
	//bdSetRandTest(u, 10);
	//bdSetRandTest(v, 10);
	//bdAdd(w, u, v);
	//bdPrintHex("u=\n", u, "\n");
	//bdPrintHex("v=\n", v, "\n");
	//bdPrintHex("w=u+v=\n", w, "\n");
//
	///* Subtract */
	//bdSubtract(r, w, v);
	//bdPrintHex("w-v=\n", r, "\n");
	//assert(bdCompare(r, u) == 0);
//
	///* Multiplication */
	///* 2 * 3 = 6 */
	//bdSetShort(u, 2);
	//bdSetShort(v, 3);
	//bdMultiply(w, u, v);
	//bdPrintDecimal("2 * 3=", w, "\n");
	//assert(bdShortCmp(w, 6) == 0);
//
	//bdSetShort(u, 0xffffffff);
	//bdSetShort(v, 0xffffffff);
	//bdMultiply(w, u, v);
	//bdPrintHex("ffffffff*ffffffff=", w, "\n");
	///* ffffffff*ffffffff=fffffffe 00000001 */
	//assert(bdGetBit(w, 0) == 1);
//
	///* Use ShortMult */
	//bdShortMult(p, u, 0xffffffff);
	//bdPrintHex("(Short)ffffffff*ffffffff=", p, "\n");
	//assert(bdCompare(p, w) == 0);
//
	///* Use larger random u, v */
	//bdSetRandTest(u, 10);
	//bdSetRandTest(v, 20);
	//bdPrintHex("u=\n", u, "\n");
	//bdPrintHex("v=\n", v, "\n");
//
	///* Use ShortMult by one: w = v * 1 */
	//bdShortMult(w, v, 1);
	//bdPrintHex("(Short)v*1=\n", w, "\n");
	//assert(bdCompare(w, v) == 0);
//
	///* Use ShortMult by two */
	//bdShortMult(w, u, 2);
	//bdPrintHex("(Short)u*2=\n", w, "\n");
	//assert(bdIsEven(w));
//
	///* Big multiplication */
	//bdMultiply(w, u, v);
	//bdPrintHex("w=u*v=\n", w, "\n");
//
	///* Divide expecting q = w/v == u and r = w%v == 0 */
	//bdDivide(q, r, w, v);
	//bdPrintHex("w/v=\n", q, "\n");
	//bdPrintHex("w%v=", r, "\n");
	//assert(bdIsEqual(q, u));
	//assert(bdShortCmp(r, 0) == 0);
//
	///* Modulo */
	//bdIncrement(w);
	//bdModulo(r, w, v);
	//bdPrintHex("w+1 mod v=", r, "\n");
	//assert(bdShortCmp(r, 1) == 0);
//
	//bdDecrement(w);
	//bdModulo(r, w, u);
	//bdPrintHex("w+1-1 mod u=", r, "\n");
	//assert(bdShortCmp(r, 0) == 0);
//
	///* Use a short divisor q=w/2 */
	//bdShortDiv(q, r, w, 2);
	//bdPrintHex("(ShortDiv)w/2=\n", q, "\n");
	//bdPrintHex("(ShortDiv)w%2=", r, "\n");
//
	//printf("w is %s\n", bdIsOdd(w) ? "ODD" : "EVEN");
	//bdShortMod(r, w, 2);
	//bdPrintHex("w mod 2=", r, "\n");
	//bdIncrement(w);
	//printf("w+1 is %s\n", bdIsOdd(w) ? "ODD" : "EVEN");
	//bdShortMod(r, w, 2);
	//bdPrintHex("++w mod 2=", r, "\n");
	//bdDecrement(w);
//
	///* Check with short mult u = q*2 */
	//bdShortMult(u, q, 2);
	//bdPrintHex("(ShortMult) (w/2) * 2=\n", u, "\n");
//
	//printf("\nSQUARE 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));
	///* Compute integer square root [new in v2.1] */
	//bdSqrt(p, w);
	//bdPrintHex("sqrt(w)=", p, "\n");
	//assert(bdIsEqual(p, u));
//
	//printf("\nMODULAR 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);
	//bdPrintHex("(Modulo)\nNew random u=", u, "\n");
	//bdPrintHex("v=", v, "\n");
	//bdPrintHex("w=", w, "\n");
	///* 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);
	//bdPrintHex("(u mod w + v mod w) mod w=\n", r, "\n");
	///* q = (u+v) mod w */
	//bdSetEqual(p, u);
	//bdAdd(p, p, v);
	//bdModulo(q, p, w);
	//bdPrintHex("(u+v) mod w=\n", q, "\n");
	//assert(bdIsEqual(r, q));
//
	///* ModMult and ModSquare */
	//bdModMult(p, u, v, w);
	//bdPrintHex("u * v mod w=\n", p, "\n");
	//bdModMult(p, u, u, w);
	//bdPrintHex("u * u mod w=\n", p, "\n");
	//bdModSquare(q, u, w);
	//bdPrintHex("u^2 mod w=\n", q, "\n");
	//assert(bdIsEqual(p, q));
//
//
	///* Clear and start again */
	//bdSetZero(u);
	//bdSetZero(v);
	//bdSetZero(w);
//
	//printf("\nARITHMETIC 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);
	//bdPrintHex("u=", u, "\n");
	//bdPrintHex("v=", v, "\n");
	//bdPrintHex("q=u/v=", q, "\n");
	//bdPrintHex("r=u mod v=", r, "\n");
	///* check that qv + r = u */
	//bdMultiply(w, q, v);
	//bdAdd(w, w, r);
	//bdPrintHex("qv+r=", w, "\n");
	//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);
	//bdPrintHex("(1-2/b)=", q, "\n");
	//cmp = bdCompare(r, q);
	//printf("u mod v %s (1-2/b)v\n", (cmp >= 0 ? ">=" : "<"));
//
//
	//printf("\nCope, sort of, with `negative` numbers...\n");
	//bdSetZero(u);
	//overflow = bdShortSub(w, u, 2);
	//bdPrintHex("w=0-2=", w, "\n");
	//printf("overflow=%" PRIuBIGD "\n", overflow);
	//overflow = bdIncrement(w);
	//bdPrintHex("w+1=", w, "\n");
	//printf("overflow=%" PRIuBIGD "\n", overflow);
	//overflow = bdIncrement(w);
	//bdPrintHex("(Note error!) w+1=", w, "\n");
	//printf("overflow=%" PRIuBIGD "\n", overflow);
//
	//printf("\nUse cut-off subtraction...\n");
	//bdSetShort(u, 3);
	//bdSetShort(v, 7);
	//cutoff_subtraction(w, u, v);
	//bdPrintDecimal("3-7=", w, "\n");
	//// But OK if no underflow
	//cutoff_subtraction(w, v, u);
	//bdPrintDecimal("7-3=", w, "\n");
//
	//printf("\nCatch problems working close to zero...\n");
	//bdSetZero(u);
	//overflow = bdShortAdd(u, u, 1);
	//bdPrintHex("u=0+1=", u, "\n");
	//printf("overflow=%" PRIuBIGD " (expected 0)\n", overflow);
//
	//printf("Compute w = 0 + 0...\n");
	//bdSetZero(u);
	//bdSetZero(v);
	//bdAdd(w, u, v);
	//printf("bdPrint(w)=");
	//bdPrint(w, 0x1);
	//bdPrintDecimal("w=0+0=", w, "\n");
	//bdPrintHex("w=0+0=0x", w, "\n");
	//bdPrintBits("w=0+0='", w, "'b\n");
	//assert(bdIsZero(w));
//
	//bdAdd(u, w, v);
	//bdPrintHex("w+0=", u, "\n");
	//bdAdd(w, w, v);
	//bdPrintHex("w+=0=", w, "\n");
//
//
	///* 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));
	//bdPrintHex("u=", u,"\n");
	//bdPrintHex("v=", v,"\n");
//
	///* Compute u * v */
	//bdMultiply(w, u, v);
	//bdPrintHex("w = u * v =\n", w,"\n");
	///* Set v = w / u */
	//bdDivide(v, r, w, u);
	//bdPrintHex("v = w / u =\n", v,"\n");
	//bdPrintHex("rem=", r,"\n");
	//assert(bdIsEqual(u, v));
	//assert(bdShortCmp(r, 0) == 0);
//
	//bdIncrement(u);
	//bdDecrement(v);
	//bdMultiply(w, u, v);
	//bdPrintHex("w = ++u * --v =\n", w,"\n");
	//bdDivide(w, r, u, v);
	//bdPrintHex("q = u / v =", w,"\n");
	//bdPrintHex("rem=", r,"\n");
	//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);
	//bdPrintHex("Random v=\n", v,"\n");
	//bdShortAdd(u, v, 1);
	//bdPrintHex("u = v + 1 =\n", u,"\n");
	//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);
	//bdPrintHex("w=", w,"\n");
	//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);
	///* Convert w back to a short and compare */
	//d = bdToShort(w);	/* NB This will truncate if w is too big */
	//printf("d=bdToShort(w)=%" PRIxBIGD "\n", d);
	//cmp = bdShortIsEqual(w, d);
	//printf("bdShortIsEqual(w, d)=%d\n", cmp);
	//assert(cmp == 1);
//
	//printf("\nBIT SHIFT OPERATIONS...\n");
	///* Try shifting bits */
	//bdPrintHex("w      = ", w,"\n");
	//bdFree(&u);
	//u = bdNew();
	//bdShiftLeft(u, w, 2);
	//bdPrintHex("w << 2 = ", u,"\n");
	//assert(bdGetBit(u, 33) == 1);
	//bdShiftRight(v, u, 3);
	//bdPrintHex("(w << 2) >> 3 = ", v,"\n");
	//assert(bdGetBit(v, 31) == 0);
//
	///* Bigger shift */
	//bdShiftLeft(u, w, 128);
	//bdPrintHex("w << 128 = ", u,"\n");
	//assert(bdGetBit(u, 159) == 1);
	//bdShiftRight(v, u, 129);
	//bdPrintHex("(w << 128) >> 129 = ", v,"\n");
	//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);
	//bdPrintHex("b=\n", b,"\n");
//
	//bdSetBit(b, 512, 1);
	//bdSetBit(b, 31, 0);
	//bdPrintHex("b'=\n", b,"\n");
	//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);
	//bdPrintHex("b'=\n", b,"\n");
	///* Destroy b */
	//bdFree(&b);
	//
	//printf("\nRANDOM NUMBER GENERATION...\n");
	///* Create a random number using `my_rand' callback function */
	//bdRandomSeeded(r, 508, (const unsigned char*)"", 0, my_rand);
	//bdPrintHex("random=\n", r,"\n");
	///* 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);
	//bdPrintHex("random=\n", r,"\n");
	//printf("%u bits\n", bdBitLength(r));
	//assert(bdBitLength(r) <= 509);
//
	//printf("\nPRIME NUMBERS...\n");
	///* Generate two random primes */
	//printf("Generating two primes...\n");
	//bdGeneratePrime(p, 128, 5, (const unsigned char*)"1", 1, my_rand);
	//bdPrintHex("prime p=\n", p,"\n");
	//bdGeneratePrime(q, 128, 5, (const unsigned char*)"abcdef", 6, my_rand);
	//bdPrintHex("prime q=\n", q,"\n");
//
	///* 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);
	//bdPrintHex("pq=\n", w,"\n");
//
	///* 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);
	//bdPrintHex("gcd(pq, p) =\n", r,"\n");
	//assert(bdIsEqual(r, p));
//
	///* --Modular inversion-- */
	//printf("\nMODULAR INVERSION...\n");
	///* set v to be a small random multiplier */
	//bdSetRandTest(v, 1);
	//bdIncrement(v);	/* Make sure not zero */
	//bdPrintHex("multiplier, v=", v,"\n");
	///* set u = vp - 1 */
	//bdMultiply(u, v, p);
	//bdDecrement(u);
	//bdPrintHex("p=\n", p,"\n");
	//bdPrintHex("u = vp - 1 =\n", u,"\n");
//
	///* compute w = u^-1 mod p */
	//res = bdModInv(w, u, p);
	//bdPrintHex("w = u^-1 mod p=\n", w,"\n");
	//assert(res == 0);
//
	///* check that wu mod p == 1 */
	//bdModMult(r, w, u, p);
	//bdPrintHex("wu mod p = ", r,"\n");
	//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);
	//bdPrintHex("output, w=", w,"\n");
//
	///* Do some bit string operations */
	//printf("\nBIT 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);
	//bdPrintHex("u= ", u,"\n");
	//bdPrintHex("w= ", w,"\n");
	///* 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);
	//bdPrintHex("u'=", u,"\n");
	//bdPrintHex("w'=", w,"\n");
	///* 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);
	//}
	//bdPrintHex("u=      ", u,"\n");
	//bdPrintHex("v=      ", v,"\n");
	//bdAndBits(w, u, v);
	//bdPrintHex("u AND v=", w,"\n");
	///* expected answer = zero */
	//assert(bdIsZero(w));
	//bdOrBits(w, u, v);
	//bdPrintHex("u OR v= ", w,"\n");
	///* expected answer p = 2^144 - 1 */
	//bdSetZero(p);
	//bdSetBit(p, 144, 1);
	//bdDecrement(p);
	//bdPrintHex("2^144-1=", p,"\n");
	//assert(bdIsEqual(p, w));
//
	///* Invert all bits */
	//bdSetZero(p);
	//bdSetZero(q);
	//bdSetShort(p, 0xfffe);
	//bdShiftLeft(p, p, 32);
	//bdShortAdd(p, p, 0xfffe);
	//bdPrintHex("p=    ", p,"\n");
	//bdNotBits(q, p);
	//bdPrintHex("NOT p=", q,"\n");
	///* check p AND (NOT p) == 0 */
	//bdAndBits(w, p, q);
	//bdPrintHex("p AND (NOT p)=", w,"\n");
	//assert(bdIsZero(w));
//
	///* Compose a 400-bit string by concatenating random 160-bit sections 
	   //and then truncating the result */
	//printf("\nBit 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);
		//bdPrintHex("", w,"\n");
	//}
	//bdPrintHex("u = w(0)+w(1)+w(2) =\n", u,"\n");
	//bdModPowerOf2(u, 400);	/* U = U mod (2^m) */
	//bdPrintHex("u = u mod (2^m) = // `ModPowerOf2' \n", u,"\n");
	///* 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 */
	//bdPrintHex("q = u OR 2^(m-1) OR 1 =\n", q,"\n");
	///* 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("\nMODULAR 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);
	//bdPrintHex("prime n=\n", n,"\n");
	//printf("bdBitLength(n)=%u bdSizeof(n)=%u\n", bdBitLength(n), bdSizeof(n));
	///* Check primality using Fermat test (NB could fail!) */
	//res = fermat_test(n);
	//if (res == 0) printf("WARNING: n failed Fermat test (this can happen!).\n");
//
	///* exponent e and base m are some random numbers < n */
	//bdSetRandTest(e, bdSizeof(n) - 1);
	//bdPrintHex("e=", e,"\n");
	//bdSetRandTest(m, bdSizeof(n) - 1);
	//bdPrintHex("random m=\n", m,"\n");
//
	///* Compute c = m^e mod n */
	//bdModExp(c, m, e, n);
	//bdPrintHex("c = m^e mod n =\n", c,"\n");
//
	///* Now use a random z and check that 
	   //c.z^e == (m.z)^e (mod n) */
	//bdSetRandTest(z, bdSizeof(n));
	//bdPrintHex("random z=\n", z,"\n");
//
	///* Compute cz = c.z^e mod n (Note use of temp t) */
	//bdModExp(t, z, e, n);
	//bdModMult(cz, c, t, n);
	//bdPrintHex("c.z^e mod n=\n", cz,"\n");
	///* Compute mz = (m.z)^e mod n */
	//bdModMult(t, m, z, n);
	//bdModExp(mz, t, e, n);
	//bdPrintHex("(m.z)^e mod n==\n", mz,"\n");
	//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));
//
	///* Repeat using constant-time exponentiation */
//
	//printf("Using constant-time exponentiation...\n");
	///* Compute cz = c.z^e mod n (Note use of temp t) */
	//bdModExp_ct(t, z, e, n);
	//bdModMult(cz, c, t, n);
	//bdPrintHex("c.z^e mod n=\n", cz,"\n");
	///* Compute mz = (m.z)^e mod n */
	//bdModMult(t, m, z, n);
	//bdModExp_ct(mz, t, e, n);
	//bdPrintHex("(m.z)^e mod n==\n", mz,"\n");
	//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));
//
//
	//printf("\nCONVERSIONS WITH HEX AND DECIMAL...\n");
	///* Do some conversions with hex and decimal strings */
	//bdSetZero(u);
	//bdConvFromHex(u, "DeadBeefCafeBabeBeddedDefacedDeafBeadFacade");
	//bdPrintHex("From Hex: ", u,"\n");
	//bdConvToHex(u, s, sizeof(s));
	//printf("To Hex: %s\n", s);
	//bdConvFromDecimal(u, "1234567890123456789012345678901234567890");
	//bdPrintHex("From Decimal: ", u,"\n");
	//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, "");
	//bdPrintHex("bdConvFromDecimal(u, '')=", u,"\n");
	//assert(bdIsZero(u));
	///* ditto an empty hex string */
	//bdSetShort(u, 0xfdfdfdfd);
	//bdConvFromHex(u, "");
	//bdPrintHex("bdConvFromHex(u, '')=", u,"\n");
	//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);
	//bdPrintHex("bdConvFromOctets(nbytes=0)=", u,"\n");
	//assert(bdIsZero(u));
//
	//bdFree(&n);
	//printf("\nJACOBI AND LEGENDRE SYMBOLS...\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("\nSQUARE 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);
//
	//printf("\nQUICK-AND-DIRTY RANDOM NUMBERS (bitlen <= nbits)...\n");
	//for (i = 0; i < 5; i++)
	//{
		//int nbits = 128 + i;
		//bdQuickRandBits(a, nbits);
		//printf("q-rand(%d)=", nbits);
		//bdPrintHex("", a, "");
		//printf("\t%d bits\n", bdBitLength(a));
	//}
//
	//printf("\nPRINT BITS...\n");
	//bdSetShort(u, 0xdeadbeef);
	//bdPrintHex("u=0x", u, " => ");
	//bdPrintBits("'", u, "'b\n");
	//printf("(correct)=       %s\n", "11011110101011011011111011101111");
	//bdSetShort(u, 0);
	//bdPrintHex("u=0x", u, " => ");
	//bdPrintBits("'", u, "'b\n");
	//bdSetShort(u, 1);
	//bdPrintHex("u=0x", u, " => ");
	//bdPrintBits("'", u, "'b\n");
//
	//printf("\nMODULAR SQUARE ROOT...\n");
	//printf("Select a 192-bit prime number...\n");
	//bdConvFromHex(p, "fffffffffffffffffffffffffffffffeffffffffffffffff");
	//bdPrintHex("p=0x", p, "\n");
	//bdPrintDecimal("p=", p, "\n");
	//res = bdIsPrime(p, 50);
	//printf("bdIsPrime(p)=%d\n", res);
	//assert(r != 0);
	//nbits = bdBitLength(p);
	//printf("p is %d bits\n", nbits);
	//// Pick a number just smaller than p
	//bdQuickRandBits(u, nbits - 1);
	//bdPrintDecimal("u=               ", u, "\n");
	//// Square it
	//bdModSquare(w, u, p);
	//bdPrintDecimal("w=u^2(mod p)=    ", w, "\n");
	///* Check we have a quadratic residue */
	//jac = bdJacobi(w, p);
	//printf("Legendre symbol (w|p)=%d (expected 1)\n", jac);
	//assert(jac == 1);
	///* Compute one modular square root */
	//bdModSqrt(x, w, p);
	//bdPrintDecimal("x=sqrt(w)(mod p)=", x, "\n");
	///* and the other */
	//bdSubtract(y, p, x);
	//bdPrintDecimal("other root y=p-x=", y, "\n");
	//assert(bdIsEqual(x, u) || bdIsEqual(y, u));
	//if (bdIsEqual(x, u)) {
		//printf("u == x => OK\n");
	//}
	//else {
		//printf("u == p-x => OK\n");
	//}
//
	//printf("\nFind a number that is not a quadratic residue mod p...\n");
	//do {
		//bdQuickRandBits(v, nbits - 1);
	//} while (bdJacobi(v, p) != -1);
	//bdPrintDecimal("v=", v, "\n");
	//printf("Legendre symbol (v|p)=%d (expected -1)\n", bdJacobi(v, p));
	//res = bdModSqrt(x, v, p);
	//printf("bdModSqrt(v) returns %d (-1 => square root does not exist)\n", res);
	//assert(res != 0);
//
	//printf("\nADD AND SUBTRACT MODULO M ...\n");
	///* Add two random numbers w = u + v mod p */
	//bdQuickRandBits(u, nbits - 1);
	//bdQuickRandBits(v, nbits - 1);
	//bdPrintDecimal("u=           ", u, "\n");
	//bdPrintDecimal("v=           ", v, "\n");
	//bdModAdd(w, u, v, p);
	//bdPrintDecimal("w=u+v(mod p)=", w, "\n");
//
	///* y = w - v */
	//bdModSub(y, w, v, p);
	//bdPrintDecimal("y=w-v(mod p)=", y, "\n");
	///* Check y == u */
	//printf("y == u => %s\n", (bdIsEqual(y, u) ? "OK" : "ERROR"));
	//assert(bdIsEqual(y, u));
//
	//printf("\nDivide an integer by 2 modulo p using bdModHalve()...\n");
	//bdSetEqual(w, u);
	//bdPrintDecimal("w=           ", u, "\n");
	//bdModHalve(w, w, p);
	//bdPrintDecimal("w=w/2(mod p)=", w, "\n");
	//// Check result
	//bdModAdd(v, w, w, p);
	//bdPrintDecimal("v=w+w(mod p)=", v, "\n");
	//printf("v == u => %s\n", (bdIsEqual(v, u) ? "OK" : "ERROR"));
	//assert(bdIsEqual(v, u));
//
//
	///* Finally, show the current version number */
	//printf("\nVERSION=%d\n", bdVersion());
	//printf("Compiled on [%s]\n", bdCompileTime());
//
//
	///* Clear up */
//
	//bdFree(&a);
	//bdFree(&n);
	//bdFree(&e);
	//bdFree(&m);
	//bdFree(&c);
	//bdFree(&z);
	//bdFree(&mz);
	//bdFree(&cz);
	//bdFree(&t);
//
//
	///* Old method... */
	////bdFree(&u);
	////bdFree(&v);
	////bdFree(&w);
	////bdFree(&q);
	////bdFree(&r);
	////bdFree(&p);
	////bdFree(&x);
	////bdFree(&y);
//
	///* New way in [v2.6] */
	//bdFreeVars(&u, &v, &w, &p, &q, &r, &x, &y);
	//printf("OK, successfully completed tests.\n");
//
	//return 0;
//}
//
