
///////////////////////////////////////////////////////////////////////////////
//                                                                           //
//                           Long Integer - test                             //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////
// (c) 2021 Miroslav Nemecek, Panda38@seznam.cz, panda38.sweb.cz
// This source code may be used freely without restrictions for any purpose,
// including commercial.

#include "include.h"

// temporary text buffer
char TextBuf[TEXTBUF_SIZE];
char TextBuf2[TEXTBUF_SIZE];

// --- double integer

// uint32, sint32, fix32
#define DBLUINT uint32	// double integer class unsigned
#define BASEUINT u16	// base integer unsigned
#define HALFUINT u8		// half integer unsigned
#define BASEBITS 16		// number of bits of base integer
#define DBLSINT sint32	// double integer class signed
#define BASESINT s16	// base integer signed
#define HALFSINT s8		// half integer signed
#define DBLFIX fix32	// double fixed point class
#include "dblint_cpp.h"

// uint64, sint64, fix64
#define DBLUINT uint64	// double integer class unsigned
#define BASEUINT u32	// base integer unsigned
#define HALFUINT u16	// half integer unsigned
#define BASEBITS 32		// number of bits of base integer
#define DBLSINT sint64	// double integer class signed
#define BASESINT s32	// base integer signed
#define HALFSINT s16	// half integer signed
#define DBLFIX fix64	// double fixed point class
#include "dblint_cpp.h"

// uint128, sint128, fix128
#define DBLUINT uint128	// double integer class unsigned
#define BASEUINT u64	// base integer unsigned
#define HALFUINT u32	// half integer unsigned
#define BASEBITS 64		// number of bits of base integer
#define DBLSINT sint128	// double integer class signed
#define BASESINT s64	// base integer signed
#define HALFSINT s32	// half integer signed
#define DBLFIX fix128	// double fixed point class
#include "dblint_cpp.h"

// --- quadruple integer

// uint64B, sint64B, fix64B
#define QUADUINT uint64B // quadruple integer class
#define DBLUINT uint32	// double integer class unsigned
#define BASEUINT u16	// base integer unsigned
#define HALFUINT u8		// half integer unsigned
#define BASEBITS 16		// number of bits of base integer
#define QUADSINT sint64B // double integer class signed
#define DBLSINT sint32	// double integer class signed
#define BASESINT s16	// base integer signed
#define HALFSINT s8		// half integer signed
#define DBLFIX fix32	// double fixed point class
#define QUADFIX fix64B	// quadruple fixed point class
#include "quadint_cpp.h"

// uint128B, sint128B, fix128B
#define QUADUINT uint128B // quadruple integer class
#define DBLUINT uint64	// double integer class unsigned
#define BASEUINT u32	// base integer unsigned
#define HALFUINT u16	// half integer unsigned
#define BASEBITS 32		// number of bits of base integer
#define QUADSINT sint128B // double integer class signed
#define DBLSINT sint64	// double integer class signed
#define BASESINT s32	// base integer signed
#define HALFSINT s16	// half integer signed
#define DBLFIX fix64	// double fixed point class
#define QUADFIX fix128B	// quadruple fixed point class
#include "quadint_cpp.h"

// uint256, sint256, fix256
#define QUADUINT uint256 // quadruple integer class
#define DBLUINT uint128	// double integer class unsigned
#define BASEUINT u64	// base integer unsigned
#define HALFUINT u32	// half integer unsigned
#define BASEBITS 64		// number of bits of base integer
#define QUADSINT sint256 // double integer class signed
#define DBLSINT sint128	// double integer class signed
#define BASESINT s64	// base integer signed
#define HALFSINT s32	// half integer signed
#define DBLFIX fix128	// double fixed point class
#define QUADFIX fix256	// quadruple fixed point class
#include "quadint_cpp.h"

///////////////////////////////////////////////////////////////////////////////
// print number in hex code

void PrintTestHex(const char* name, void* num, int bits)
{
	printf("   %s=", name);

	int i;
	u16* s = (u16*)num;
	for (i = bits/16 - 1; i >= 0; i--)
	{
		printf("%04X", s[i]);
		if (i > 0) printf(":");
	}

	printf("\n");
}

///////////////////////////////////////////////////////////////////////////////
// fixed point reference number help functions

s64 RefMul64(s64 u, s64 v, int shift)
{
	sint128 z;
	z.Mul(u, v);
	z.RShift(shift);
	return z.N0();
}

s64 RefDiv64(s64 u, s64 v, int shift, u64 max)
{
	bool neg = false;

	if (u < 0)
	{
		u = -u;
		neg = true;
	}

	if (v < 0)
	{
		v = -v;
		neg = !neg;
	}

	sint128 z;
	z = u;
	z.LShift(shift);
	if (z.N1() >= v)
	{
		if (neg)
			return (s64)(1ULL << (shift*2-1));
		else
			return (s64)((1ULL << (shift*2-1)) - 1);
	}
	z.Div(v);

	if (z.N0() > max)
	{
		if (neg)
			return (s64)(1ULL << (shift*2-1));
		else
			return (s64)((1ULL << (shift*2-1)) - 1);
	}

	if (neg) z.Neg();
	return z.N0();
}

s64 RefMod64(s64 u, s64 v)
{
	s64 z = u/v;
	return u - z*v;
}

///////////////////////////////////////////////////////////////////////////////
// check double integer + u32

#define TESTINT uint32	// tested number class
#define REFINT u32		// reference number class
#define REFISCLS 0		// 1=reference number is class, 0=reference number is integer
#define BASEINT u16		// base integer
#define BASEBITS 16		// number of bits of base integer
#define HALFINT u8		// half integer
#define TESTBITS 32		// number of bits

void Check_dbluint32(int max)
{
	const char* name = "Check dbl uint32";
#include "test_func.h"
}

///////////////////////////////////////////////////////////////////////////////
// check double integer + s32

#define TESTINT sint32	// tested number class
#define REFINT s32		// reference number class
#define REFISCLS 0		// 1=reference number is class, 0=reference number is integer
#define BASEINT s16		// base integer
#define BASEBITS 16		// number of bits of base integer
#define HALFINT s8		// half integer
#define TESTBITS 32		// number of bits
#define SIGNED			// signed number

void Check_dblsint32(int max)
{
	const char* name = "Check dbl sint32";
#include "test_func.h"
}

///////////////////////////////////////////////////////////////////////////////
// check double fix + s32

#define TESTINT fix32	// tested number class
#define REFINT s32		// reference number class
#define REFISCLS 0		// 1=reference number is class, 0=reference number is integer
#define BASEINT s16		// base integer
#define BASEBITS 16		// number of bits of base integer
#define HALFINT s8		// half integer
#define TESTBITS 32		// number of bits
#define SIGNED			// flag - signed number
#define FIXED			// flag - fix point number

void Check_dblfix32(int max)
{
	const char* name = "Check dbl fix32";
#include "test_func.h"
}

///////////////////////////////////////////////////////////////////////////////
// check double integer + u64

#define TESTINT uint64	// tested number class
#define REFINT u64		// reference number class
#define REFISCLS 0		// 1=reference number is class, 0=reference number is integer
#define BASEINT u32		// base integer
#define BASEBITS 32		// number of bits of base integer
#define HALFINT u16		// half integer
#define TESTBITS 64		// number of bits

void Check_dbluint64(int max)
{
	const char* name = "Check dbl uint64";
#include "test_func.h"
}

///////////////////////////////////////////////////////////////////////////////
// check double integer + s64

#define TESTINT sint64	// tested number class
#define REFINT s64		// reference number class
#define REFISCLS 0		// 1=reference number is class, 0=reference number is integer
#define BASEINT s32		// base integer
#define BASEBITS 32		// number of bits of base integer
#define HALFINT s16		// half integer
#define TESTBITS 64		// number of bits
#define SIGNED			// signed number

void Check_dblsint64(int max)
{
	const char* name = "Check dbl sint64";
#include "test_func.h"
}

///////////////////////////////////////////////////////////////////////////////
// check double fix + s64

#define TESTINT fix64	// tested number class
#define REFINT s64		// reference number class
#define REFISCLS 0		// 1=reference number is class, 0=reference number is integer
#define BASEINT s32		// base integer
#define BASEBITS 32		// number of bits of base integer
#define HALFINT s16		// half integer
#define TESTBITS 64		// number of bits
#define SIGNED			// flag - signed number
#define FIXED			// flag - fix point number

void Check_dblfix64(int max)
{
	const char* name = "Check dbl fix64";
#include "test_func.h"
}

///////////////////////////////////////////////////////////////////////////////
// check quadruple integer + u64

#define TESTINT uint64B // tested number class
#define REFINT u64		// reference number class
#define REFISCLS 0		// 1=reference number is class, 0=reference number is integer
#define BASEINT u16		// base integer
#define BASEBITS 16		// number of bits of base integer
#define HALFINT u8		// half integer
#define TESTBITS 64		// number of bits

#define DBLINT1 uint32	// double integer class for tested number
#define DBLINT2 u32		// double integer for reference number

void Check_quaduint64B(int max)
{
	const char* name = "Check quad uint64B";
#include "test_func.h"
}

///////////////////////////////////////////////////////////////////////////////
// check quadruple integer + s64

#define TESTINT sint64B // tested number class
#define REFINT s64		// reference number class
#define REFISCLS 0		// 1=reference number is class, 0=reference number is integer
#define BASEINT s16		// base integer
#define BASEBITS 16		// number of bits of base integer
#define HALFINT s8		// half integer
#define TESTBITS 64		// number of bits
#define SIGNED			// signed number

#define DBLINT1 sint32	// double integer class for tested number
#define DBLINT2 s32		// double integer for reference number

void Check_quadsint64B(int max)
{
	const char* name = "Check quad sint64B";
#include "test_func.h"
}

///////////////////////////////////////////////////////////////////////////////
// check quadruple fix + s64

#define TESTINT fix64B	// tested number class
#define REFINT s64		// reference number class
#define REFISCLS 0		// 1=reference number is class, 0=reference number is integer
#define BASEINT s16		// base integer
#define BASEBITS 16		// number of bits of base integer
#define HALFINT s8		// half integer
#define TESTBITS 64		// number of bits
#define SIGNED			// signed number
#define FIXED			// flag - fix point number

#define DBLINT1 fix32	// double integer class for tested number
#define DBLINT2 s32		// double integer for reference number

void Check_quadfix64B(int max)
{
	const char* name = "Check quad fix64B";
#include "test_func.h"
}

///////////////////////////////////////////////////////////////////////////////
// check quadruple integer + double integer unsigned

#define TESTINT uint128B // tested number class
#define REFINT uint128	// reference number class
#define REFISCLS 1		// 1=reference number is class, 0=reference number is integer
#define BASEINT u32		// base integer
#define BASEBITS 32		// number of bits of base integer
#define HALFINT u16		// half integer
#define TESTBITS 128	// number of bits

void Check_quadudbl128(int max)
{
	const char* name = "Check quad dbl uint128";
#include "test_func.h"
}

///////////////////////////////////////////////////////////////////////////////
// check quadruple integer + double integer signed

#define TESTINT sint128B // tested number class
#define REFINT sint128	// reference number class
#define REFISCLS 1		// 1=reference number is class, 0=reference number is integer
#define BASEINT s32		// base integer
#define BASEBITS 32		// number of bits of base integer
#define HALFINT s16		// half integer
#define TESTBITS 128	// number of bits
#define SIGNED			// signed number

void Check_quadsdbl128(int max)
{
	const char* name = "Check quad dbl sint128";
#include "test_func.h"
}
