634 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			SourcePawn
		
	
	
	
	
	
			
		
		
	
	
			634 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			SourcePawn
		
	
	
	
	
	
| /***
 | |
| bigint.inc - Big Integers Operation Library Functions
 | |
| 
 | |
| Version: 0.1
 | |
| Date: 28-12-2014
 | |
| Author: Statik
 | |
| 
 | |
| Provides some arithmetic and logical maths functions to operate 
 | |
| with big integers.
 | |
| 
 | |
| **UNFINISHED**
 | |
| 
 | |
| ***/
 | |
| 
 | |
| #if defined _BigInt_included
 | |
| 	#endinput
 | |
| #endif
 | |
| 
 | |
| #define _BigInt_included
 | |
| 
 | |
| stock modpowBigInt(base[], exponent[], modulus[], nBase, output[], oSize) // http://en.wikipedia.org/wiki/Modular_exponentiation
 | |
| { // Modular exponentiation, Right-to-left binary method (binary exponentiation + memory efficient method)
 | |
| 	new eSize = getBigIntSize(exponent);
 | |
| 	new mSize = getBigIntSize(modulus);
 | |
| 	new auxSize = (mSize+1)*2; // output and base (pow base) are never bigger than modulus
 | |
| 	decl aux[auxSize];
 | |
| 	decl auxBase[auxSize]; // Is used as a replacemente of the power base, not the numeric base
 | |
| 	decl auxExponent[eSize+1];
 | |
| 	new parity[2];
 | |
| 	
 | |
| 	output[0] = 1;
 | |
| 	output[1] = -1;
 | |
| 	copyBigInt(base, auxBase, auxSize);
 | |
| 	copyBigInt(exponent, auxExponent, eSize+1);
 | |
| 	modBigInt(base, modulus, nBase, auxBase, auxSize);
 | |
| 	
 | |
| 	while (isBiggerThanBigNumber(auxExponent, {0,-1})) // exponent > 0
 | |
| 	{
 | |
| 		fulldivBigInt(auxExponent, {2,-1}, nBase, auxExponent, eSize+1, parity, sizeof(parity));
 | |
| 		if (parity[0] == 1) // (exponent % 2) == 1 / Is exponent odd?
 | |
| 		{
 | |
| 			multBigInt(output, auxBase, nBase, aux, auxSize);
 | |
| 			modBigInt(aux, modulus, nBase, output, oSize);
 | |
| 		}
 | |
| 		multBigInt(auxBase, auxBase, nBase, auxBase, auxSize);
 | |
| 		modBigInt(auxBase, modulus, nBase, auxBase, auxSize);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| stock powBigInt(number[], exponent[], base, output[], oSize) // Exponentiation by squaring recursive algorithm **UNFINISHED**
 | |
| { // http://en.wikipedia.org/wiki/Exponentiation_by_squaring
 | |
| 	new nSize = getBigIntSize(number);
 | |
| 	new eSize = getBigIntSize(exponent);
 | |
| 	if (!isBiggerThanBigNumber(exponent, {0,-1})) // Exponent is 0
 | |
| 	{
 | |
| 		output[0] = 1;
 | |
| 		output[1] = -1;
 | |
| 		return;
 | |
| 	}
 | |
| 	if (!isBiggerThanBigNumber(exponent, {1,-1})) // Exponent is 1
 | |
| 	{
 | |
| 		for (new i = 0; i <= nSize; i++)
 | |
| 		{
 | |
| 			output[i] = number[i];
 | |
| 		}
 | |
| 		return;
 | |
| 	}
 | |
| 	new bool:isExponentEven = (exponent[0] % 2) == 0;
 | |
| 	multBigInt(number, number, base, output, oSize); // number^2
 | |
| 	if (!isBiggerThanBigNumber(exponent, {2,-1})) return;
 | |
| 	
 | |
| 	if (isExponentEven)
 | |
| 	{
 | |
| 		//powBigInt(output, exponent/2, base, output, oSize);
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		
 | |
| 		//powBigInt(output, exponent-1/2, base, output, oSize);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| stock multBigInt(n1[], n2[], base, output[], oSize)
 | |
| {
 | |
| 	new n1Size = getBigIntSize(n1);
 | |
| 	new n2Size = getBigIntSize(n2);
 | |
| 	if (n1Size < 40000 && n2Size < 40000)
 | |
| 	{
 | |
| 		standardMult(n1, n2, base, output, oSize);
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		karatsubaMult(n1, n2, base, output, oSize);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| stock divBigInt(n1[], n2[], base, output[], oSize)
 | |
| {
 | |
| 	new n2Size = getBigIntSize(n2);
 | |
| 	decl remainder[n2Size+1]; // Remainder is never bigger than divisor/denominator
 | |
| 	fulldivBigInt(n1, n2, base, output, oSize, remainder, n2Size+1);
 | |
| }
 | |
| 
 | |
| stock modBigInt(n1[], n2[], base, output[], oSize)
 | |
| {
 | |
| 	new n1Size = getBigIntSize(n1);
 | |
| 	decl quotient[n1Size+1]; // Quotient is never bigger than dividend/numerator
 | |
| 	fulldivBigInt(n1, n2, base, quotient, n1Size+1, output, oSize);
 | |
| }
 | |
| 
 | |
| stock fulldivBigInt(n1[], n2[], base, quotient[], qSize, remainder[], rSize)
 | |
| {
 | |
| 	new n1Size = getBigIntSize(n1);
 | |
| 	new n2Size = getBigIntSize(n2);
 | |
| 	
 | |
| 	if (qSize < (n1Size+1)) return;
 | |
| 	if (!isBiggerThanBigNumber(n2, {0,-1})) // n2 == 0
 | |
| 		return;
 | |
| 	
 | |
| 	if (n2Size > n1Size)
 | |
| 	{
 | |
| 		quotient[0] = 0;
 | |
| 		quotient[1] = -1;
 | |
| 		copyBigInt(n1, remainder, rSize);
 | |
| 		return;
 | |
| 	}
 | |
| 	decl tempRemainder[rSize+1];
 | |
| 	tempRemainder[0] = -1;
 | |
| 	quotient[n1Size] = -1;
 | |
| 	new i;
 | |
| 	for (i = n1Size-1; i >= 0; i--)
 | |
| 	{
 | |
| 		leftShiftBigInt(tempRemainder, 1);
 | |
| 		trimBigInt(tempRemainder);
 | |
| 		tempRemainder[0] = n1[i];
 | |
| 		quotient[i] = 0;
 | |
| 		while (!isBiggerThanBigNumber(n2, tempRemainder)) // (tempRemainder >= n2)
 | |
| 		{
 | |
| 			subBigInt(tempRemainder, n2, base, tempRemainder, rSize);
 | |
| 			quotient[i]++;
 | |
| 		}
 | |
| 	}
 | |
| 	copyBigInt(tempRemainder, remainder, rSize);
 | |
| 	trimBigInt(quotient);
 | |
| }
 | |
| 
 | |
| stock karatsubaMult(n1[], n2[], base, output[], oSize) // Karatsuba recursive algorithm
 | |
| {	// http://en.wikipedia.org/wiki/Karatsuba_algorithm#Pseudo_Code_Implementation
 | |
| 	if (oSize < 2) return;
 | |
| 	new n1Size = getBigIntSize(n1);
 | |
| 	new n2Size = getBigIntSize(n2);
 | |
| 	if (n1Size == 1 || n2Size == 1) // Base case 
 | |
| 	{
 | |
| 		standardMult(n1, n2, base, output, oSize);
 | |
| 		return;
 | |
| 	}
 | |
| 	new m = (n1Size > n2Size) ? n1Size : n2Size;
 | |
| 	new m2 = m/2;
 | |
| 	
 | |
| 	decl l1[oSize], h1[oSize];
 | |
| 	decl l2[oSize], h2[oSize];
 | |
| 	splitBigIntAt(n1, m2, l1, oSize, h1, oSize);
 | |
| 	splitBigIntAt(n2, m2, l2, oSize, h2, oSize);
 | |
| 	
 | |
| 	decl z0[oSize]; // <-
 | |
| 	karatsubaMult(l1, l2, base, z0, oSize);
 | |
| 	//standardMult(l1, l2, base, z0, oSize);
 | |
| 	
 | |
| 	decl z1[oSize]; // <-
 | |
| 	decl l1plush1[oSize];
 | |
| 	decl l2plush2[oSize];
 | |
| 	addBigInt(l1, h1, base, l1plush1, oSize);
 | |
| 	addBigInt(l2, h2, base, l2plush2, oSize);
 | |
| 	karatsubaMult(l1plush1, l2plush2, base, z1, oSize);
 | |
| 	//standardMult(l1plush1, l2plush2, base, z1, oSize);
 | |
| 	
 | |
| 	decl z2[oSize]; // <-
 | |
| 	karatsubaMult(h1, h2, base, z2, oSize);
 | |
| 	//standardMult(h1, h2, base, z2, oSize);
 | |
| 	
 | |
| 	decl z3[oSize]; // <-
 | |
| 	subBigInt(z1, z2, base, z3, oSize);
 | |
| 	subBigInt(z3, z0, base, z3, oSize);
 | |
| 	
 | |
| 	leftShiftBigInt(z2, 2*m2);
 | |
| 	leftShiftBigInt(z3, m2);
 | |
| 	
 | |
| 	addBigInt(z2, z3, base, output, oSize);
 | |
| 	addBigInt(output, z0, base, output, oSize);
 | |
| 	
 | |
| 	trimBigInt(output);
 | |
| }
 | |
| 
 | |
| stock standardMult(n1[], n2[], base, output[], oSize)
 | |
| {
 | |
| 	new n1Size = getBigIntSize(n1);
 | |
| 	new n2Size = getBigIntSize(n2);
 | |
| 	new bool:n1b = isBiggerThanBigNumber(n1, n2); // Is n1 bigger
 | |
| 	new sSize = (n1b) ? n2Size : n1Size; // Smallest size
 | |
| 	new bSize = (n1b) ? n1Size : n2Size; // Biggest size
 | |
| 	new carry = 0;
 | |
| 	decl value[sSize][oSize];
 | |
| 	new temp, i, u;
 | |
| 	for (i = 0; i < sSize; i++)
 | |
| 	{
 | |
| 		for (u = 0; u < bSize; u++)
 | |
| 		{
 | |
| 			temp = n1[(n1b)?u:i] * n2[(n1b)?i:u] + carry;
 | |
| 			if (temp >= base)
 | |
| 			{
 | |
| 				carry = temp / base;
 | |
| 				value[i][u] = temp % base;
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				carry = 0;
 | |
| 				value[i][u] = temp;
 | |
| 			}
 | |
| 		}
 | |
| 		if (carry != 0)
 | |
| 		{
 | |
| 			value[i][u] = carry;
 | |
| 			value[i][u+1] = -1;
 | |
| 			carry = 0;
 | |
| 		}
 | |
| 		else 
 | |
| 		{
 | |
| 			value[i][u] = -1;
 | |
| 		}
 | |
| 		leftShiftBigInt(value[i], i);
 | |
| 	}
 | |
| 	output[0] = -1; // Initializes output
 | |
| 	for (i = 0; i < sSize; i++)
 | |
| 	{
 | |
| 		addBigInt(output, value[i], base, output, oSize);
 | |
| 	}
 | |
| 	trimBigInt(output);
 | |
| }
 | |
| 
 | |
| stock addBigInt(n1[], n2[], base, output[], oSize) // Standard algorithm
 | |
| {
 | |
| 	new n1Size = getBigIntSize(n1);
 | |
| 	new n2Size = getBigIntSize(n2);
 | |
| 	new carry = 0;
 | |
| 	new temp;
 | |
| 	new i;
 | |
| 	for (i = 0; (i < n1Size || i < n2Size); i++)
 | |
| 	{
 | |
| 		if (i == oSize) return;
 | |
| 		if (i >= n1Size) temp = n2[i] + carry;
 | |
| 		else if (i >= n2Size) temp = n1[i] + carry;
 | |
| 		else temp = n1[i] + n2[i] + carry;
 | |
| 		
 | |
| 		if (temp >= base)
 | |
| 		{
 | |
| 			output[i] = temp - base;
 | |
| 			carry = 1;
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			output[i] = temp;
 | |
| 			carry = 0;
 | |
| 		}
 | |
| 	}
 | |
| 	if (carry == 1) // Adds the last carry
 | |
| 	{
 | |
| 		output[i] = carry;
 | |
| 		output[i+1] = -1;
 | |
| 	}
 | |
| 	else output[i] = -1;
 | |
| 	trimBigInt(output);
 | |
| }
 | |
| 
 | |
| stock subBigInt(n1[], n2[], base, output[], oSize) // Standard algorithm
 | |
| {
 | |
| 	new n1Size = getBigIntSize(n1);
 | |
| 	new n2Size = getBigIntSize(n2);
 | |
| 	new carry = 0;
 | |
| 	new temp;
 | |
| 	new i;
 | |
| 	for (i = 0; (i < n1Size || i < n2Size); i++)
 | |
| 	{
 | |
| 		if (i == oSize) return;
 | |
| 		if (i >= n1Size) temp = n2[i] - carry;
 | |
| 		else if (i >= n2Size) temp = n1[i] - carry;
 | |
| 		else temp = n1[i] - n2[i] - carry;
 | |
| 		
 | |
| 		if (temp < 0)
 | |
| 		{
 | |
| 			output[i] =  temp + base;
 | |
| 			carry = 1;
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			output[i] = temp;
 | |
| 			carry = 0;
 | |
| 		}
 | |
| 	}
 | |
| 	output[i] = -1;
 | |
| 	trimBigInt(output);
 | |
| }
 | |
| 
 | |
| stock bool:splitBigIntAt(number[], index, lowOut[], loSize, highOut[], hoSize)
 | |
| {
 | |
| 	new nSize = getBigIntSize(number);
 | |
| 	if (index == 0) return false;
 | |
| 	if (index >= nSize) return false;
 | |
| 	if (index >= loSize) return false;
 | |
| 	if (nSize-index >= hoSize) return false;
 | |
| 	
 | |
| 	new i;
 | |
| 	for (i = 0; i < index; i++)
 | |
| 	{
 | |
| 		lowOut[i] = number[i];
 | |
| 	}
 | |
| 	lowOut[i] = -1;
 | |
| 	trimBigInt(lowOut);
 | |
| 	
 | |
| 	for (i = index; i < nSize; i++)
 | |
| 	{
 | |
| 		highOut[i-index] = number[i];
 | |
| 	}
 | |
| 	highOut[i-index] = -1;
 | |
| 	trimBigInt(highOut);
 | |
| 	
 | |
| 	return true;
 | |
| }
 | |
| 
 | |
| stock bool:isEqualToBigNumber(n1[], n2[])
 | |
| {
 | |
| 	new n1Size = getBigIntSize(n1);
 | |
| 	new n2Size = getBigIntSize(n2);
 | |
| 	if (n1Size != n2Size) return false;
 | |
| 	
 | |
| 	for (new i = 0; i < n1Size; i++)
 | |
| 	{
 | |
| 		if (n1[i] != n2[i]) return false;
 | |
| 	}
 | |
| 	return true;
 | |
| }
 | |
| 
 | |
| stock bool:isBiggerThanBigNumber(n1[], n2[])
 | |
| {
 | |
| 	new n1Size = getBigIntSize(n1);
 | |
| 	new n2Size = getBigIntSize(n2);
 | |
| 	if (n1Size > n2Size) return true;
 | |
| 	if (n1Size < n2Size) return false;
 | |
| 	
 | |
| 	for (new i = (n1Size-1); i >= 0; i--)
 | |
| 	{
 | |
| 		if (n1[i] == n2[i]) continue;
 | |
| 		else if (n1[i] > n2[i]) return true;
 | |
| 		else return false;
 | |
| 	}
 | |
| 	return false; // In case both numbers are the same
 | |
| }
 | |
| 
 | |
| stock leftShiftBigInt(number[], digits) // Logical shift
 | |
| {
 | |
| 	if (digits == 0) return;
 | |
| 	new nSize = getBigIntSize(number);
 | |
| 	decl temp[nSize+1];
 | |
| 	for (new i = 0; i <= nSize; i++) // Creates a backup
 | |
| 	{
 | |
| 		temp[i] = number[i];
 | |
| 	}
 | |
| 	for (new a = 0; a < digits; a++) // Fills with zeros
 | |
| 	{
 | |
| 		number[a] = 0;
 | |
| 	}
 | |
| 	for (new i = 0; i <= nSize; i++) // Puts the backup back in
 | |
| 	{
 | |
| 		number[i+digits] = temp[i];
 | |
| 	}
 | |
| 	trimBigInt(number);
 | |
| }
 | |
| 
 | |
| stock trimBigInt(number[]) // Removes left padded zeros
 | |
| {
 | |
| 	new nSize = getBigIntSize(number);
 | |
| 	for (new zeros = 0; number[nSize-zeros-1] == 0; zeros++)
 | |
| 	{ 
 | |
| 		if (nSize-zeros-1 != 0) number[nSize-zeros-1] = -1;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| stock copyBigInt(number[], output[], oSize)
 | |
| {
 | |
| 	new nSize = getBigIntSize(number);
 | |
| 	if (oSize <= nSize) return;
 | |
| 	for (new i = 0; i <= nSize; i++)
 | |
| 	{
 | |
| 		output[i] = number[i];
 | |
| 	}
 | |
| }
 | |
| 
 | |
| stock getBigIntSize(number[])
 | |
| {
 | |
| 	new i;
 | |
| 	for (i = 0; number[i] != -1; i++){}
 | |
| 	return i;
 | |
| }
 | |
| 
 | |
| stock toBase256BigInt(number[], output[], oLength)
 | |
| {
 | |
| 	new nSize = getBigIntSize(number);
 | |
| 	new finalLength = nSize/2 + (nSize%2);
 | |
| 	if (oLength < finalLength) return 0;
 | |
| 	new i;
 | |
| 	new high, low;
 | |
| 	
 | |
| 	for (i = 0; i < finalLength; i++)
 | |
| 	{
 | |
| 		if ((i == finalLength-1) && nSize%2 == 1)
 | |
| 			high = 0;
 | |
| 		else
 | |
| 			high = number[i*2+1];
 | |
| 		low = number[i*2];
 | |
| 		output[finalLength-i-1] = (high << 4) + low;
 | |
| 	}
 | |
| 	return finalLength;
 | |
| }
 | |
| 
 | |
| stock bool:hexString2BigInt(const String:hexString[], output[], oSize)
 | |
| {
 | |
| 
 | |
| 	new i;
 | |
| 	new temp[oSize];
 | |
| 	for(i = 0; hexString[i] != 0; i++)
 | |
| 	{
 | |
| 		if (i >= oSize) return false;
 | |
| 		temp[i] = hexChar2Int(hexString[i]);
 | |
| 		
 | |
| 		if (temp[i] == -1) return false;
 | |
| 	}
 | |
| 	// Inverts number string
 | |
| 	for (new u = 0; u < i; u++)
 | |
| 	{
 | |
| 		output[u] = temp[i-u-1];
 | |
| 	}
 | |
| 	output[i] = -1; // Terminates the number string
 | |
| 	trimBigInt(output);
 | |
| 	return true;
 | |
| }
 | |
| 
 | |
| stock bool:bigInt2HexString(input[], String:hexString[], hsSize)
 | |
| {
 | |
| 	new nSize = getBigIntSize(input);
 | |
| 	new i;
 | |
| 	for (i = 0; i < (hsSize-1); i++)
 | |
| 	{
 | |
| 		if (i == nSize) break;
 | |
| 		if ((hexString[i] = int2HexChar(input[nSize-i-1])) == -1) return false;
 | |
| 	}
 | |
| 	hexString[i] = 0;
 | |
| 	return true;
 | |
| 	
 | |
| }
 | |
| 
 | |
| stock hexChar2Int(input)
 | |
| {
 | |
| 	if(input >= '0' && input <= '9')
 | |
| 		return input - '0';
 | |
| 	if(input >= 'A' && input <= 'F')
 | |
| 		return input - 'A' + 10;
 | |
| 	if(input >= 'a' && input <= 'f')
 | |
| 		return input - 'a' + 10;
 | |
| 	return -1;
 | |
| }
 | |
| 
 | |
| stock int2HexChar(input)
 | |
| {
 | |
| 	if (input >= 0 && input <= 9)
 | |
| 		return input + '0';
 | |
| 	if (input >= 10 && input <= 16)
 | |
| 		return input + 'A' - 10;
 | |
| 	return -1;	
 | |
| }
 | |
| 
 | |
| /*
 | |
| test()
 | |
| {
 | |
| 	// LOTS OF TESTS
 | |
| 	PrintDebug(caller, "Modulus size: %i", getBigIntSize(modulus));
 | |
| 	
 | |
| 	/// Addition test
 | |
| 	new n1[] = {0xC,9,4,9,0xF,0,-1};
 | |
| 	new n2[] = {0,0x3,5,7,-1};
 | |
| 	decl String:s1[7];
 | |
| 	decl String:s2[7];
 | |
| 	bigInt2HexString(n1, s1, sizeof(s1));
 | |
| 	bigInt2HexString(n2, s2, sizeof(s2));
 | |
| 	PrintDebug(caller, "HEX 1 : %s", s1);
 | |
| 	PrintDebug(caller, "HEX 2 : %s", s2);
 | |
| 	new a[20];
 | |
| 	addBigInt(n1, n2, 16, a, sizeof(a));
 | |
| 	new String:sa[20];
 | |
| 	bigInt2HexString(a, sa, sizeof(sa));
 | |
| 	PrintDebug(caller, "HEX 1 + HEX 2 = %s", sa);
 | |
| 	
 | |
| 	/// Split test
 | |
| 	new n3[] = {4,6,8,2,5,7,3,4,7,2,-1};
 | |
| 	new n4[15];
 | |
| 	new n5[15];
 | |
| 	splitBigIntAt(n3, 5, n4, sizeof(n4), n5, sizeof(n5));
 | |
| 	new String:s3[30];
 | |
| 	new String:s4[15];
 | |
| 	new String:s5[15];
 | |
| 	bigInt2HexString(n3, s3, sizeof(s3));
 | |
| 	bigInt2HexString(n4, s4, sizeof(s4));
 | |
| 	bigInt2HexString(n5, s5, sizeof(s5));
 | |
| 	PrintDebug(caller, "%s splitted at index %i", s3, 5);
 | |
| 	PrintDebug(caller, "Low: %s", s4);
 | |
| 	PrintDebug(caller, "High: %s", s5);
 | |
| 	
 | |
| 	/// Subtraction test
 | |
| 	new n6[] = {3,1,3,5,5,9,6,9,-1};
 | |
| 	new n7[] = {1,3,5,6,9,6,9,2,-1};
 | |
| 	decl String:s6[10];
 | |
| 	decl String:s7[10];
 | |
| 	bigInt2HexString(n6, s6, sizeof(s6));
 | |
| 	bigInt2HexString(n7, s7, sizeof(s7));
 | |
| 	new n8[10];
 | |
| 	new String:s8[10];
 | |
| 	subBigInt(n6, n7, 16, n8, sizeof(n8));
 | |
| 	bigInt2HexString(n8, s8, sizeof(s8));
 | |
| 	PrintDebug(caller, "Subtracting %s to %s...", s7, s6);
 | |
| 	PrintDebug(caller, "Result: %s", s8);
 | |
| 	
 | |
| 	/// Shift test
 | |
| 	new n9[] = {3,7,9,1,5,7,8,1,-1};
 | |
| 	decl String:s9[15];
 | |
| 	bigInt2HexString(n9, s9, sizeof(s9));
 | |
| 	PrintDebug(caller, "Shifting %s 3 numbers to left", s9);
 | |
| 	leftShiftBigInt(n9, 3);
 | |
| 	bigInt2HexString(n9, s9, sizeof(s9));
 | |
| 	PrintDebug(caller, "Result: %s", s9);
 | |
| 	
 | |
| 	/// Standard multiplication test
 | |
| 	new n10[] = {3,1,3,5,5,9,6,9,-1};
 | |
| 	new n11[] = {1,3,5,6,9,6,9,2,-1};
 | |
| 	decl String:s10[10];
 | |
| 	decl String:s11[10];
 | |
| 	bigInt2HexString(n10, s10, sizeof(s10));
 | |
| 	bigInt2HexString(n11, s11, sizeof(s11));
 | |
| 	new n12[30];
 | |
| 	new String:s12[30];
 | |
| 	standardMult(n10, n11, 16, n12, sizeof(n12));
 | |
| 	bigInt2HexString(n12, s12, sizeof(s12));
 | |
| 	PrintDebug(caller, "Multiplying (standard) %s to %s...", s10, s11);
 | |
| 	PrintDebug(caller, "Result: %s", s12);
 | |
| 	
 | |
| 	/// Karatsuba multiplication test
 | |
| 	new n13[] = {3,1,3,5,5,9,6,9,-1};
 | |
| 	new n14[] = {1,3,5,6,9,6,9,2,-1};
 | |
| 	decl String:s13[10];
 | |
| 	decl String:s14[10];
 | |
| 	bigInt2HexString(n13, s13, sizeof(s13));
 | |
| 	bigInt2HexString(n14, s14, sizeof(s14));
 | |
| 	new n15[30];
 | |
| 	new String:s15[30];
 | |
| 	karatsubaMult(n13, n14, 16, n15, sizeof(n15));
 | |
| 	bigInt2HexString(n15, s15, sizeof(s15));
 | |
| 	PrintDebug(caller, "Multiplying (karatsuba) %s to %s...", s13, s14);
 | |
| 	PrintDebug(caller, "Result: %s", s15);
 | |
| 	
 | |
| 	/// Exponentiation test
 | |
| 	new n16[] = {3,4,5,6,2,5,-1};
 | |
| 	new n17[] = {0,1,-1};
 | |
| 	decl String:s16[20];
 | |
| 	decl String:s17[20];
 | |
| 	bigInt2HexString(n16, s16, sizeof(s16));
 | |
| 	bigInt2HexString(n17, s17, sizeof(s17));
 | |
| 	new n18[30];
 | |
| 	new String:s18[30];
 | |
| 	powBigInt(n16, n17, 16, n18, sizeof(n18));
 | |
| 	bigInt2HexString(n18, s18, sizeof(s18));
 | |
| 	PrintDebug(caller, "Exponentiating %s to %s...", s16, s17);
 | |
| 	PrintDebug(caller, "Result: %s", s18);
 | |
| 	
 | |
| 	/// Division test
 | |
| 	new n19[] = {9,0xC,7,2,-1};
 | |
| 	new n20[] = {6,2,6,-1};
 | |
| 	decl String:s19[20];
 | |
| 	decl String:s20[20];
 | |
| 	bigInt2HexString(n19, s19, sizeof(s19));
 | |
| 	bigInt2HexString(n20, s20, sizeof(s20));
 | |
| 	new n21[30];
 | |
| 	new String:s21[30];
 | |
| 	new n22[30];
 | |
| 	new String:s22[30];
 | |
| 	fulldivBigInt(n19, n20, 16, n21, sizeof(n21), n22, sizeof(n22));
 | |
| 	bigInt2HexString(n21, s21, sizeof(s21));
 | |
| 	bigInt2HexString(n22, s22, sizeof(s22));
 | |
| 	PrintDebug(caller, "Dividing %s to %s...", s19, s20);
 | |
| 	PrintDebug(caller, "Quotient: %s - Remainder: %s", s21, s22);
 | |
| 	
 | |
| 	/// PKCS#1 v1.5 Padding Scheme test
 | |
| 	//decl String:aux[1024] = "BE629EA2D835880BF2572379CC751C5FA44F4A09B6F8CE5CB52C53EEDD0314E77AC827219E78DB1473BBA7BBE8BABC85C02CBC308B75375AE7C4B3AA31A491BB08D1946328F2B1BCE3E07E96D1CFF5E95A553C083A424CD5F6B7F2B55F89B958F0AE3B80A94CF5FEB3BD9417ABD09E1A42456E99128169CCEC176FDF7D2893A5";
 | |
| 	new k = strlen(hexModulus);
 | |
| 	new String:paddedMessage[k+1];
 | |
| 	pkcs1v15Pad(message, k, paddedMessage, k+1);
 | |
| 	PrintDebug(caller, "Padding message: %s with %i length modulus ", message, k);
 | |
| 	PrintDebug(caller, "Result: %i - %s", strlen(paddedMessage), paddedMessage);
 | |
| 	
 | |
| 	/// Modular exponentiation test
 | |
| 
 | |
| 	decl n23[1024];
 | |
| 	decl n24[20];
 | |
| 	decl n25[1024];
 | |
| 	hexString2BigInt(paddedMessage, n23, 1024);
 | |
| 	hexString2BigInt(hexExponent, n24, 20);
 | |
| 	hexString2BigInt(hexModulus, n25, 1024);
 | |
| 
 | |
| 	//new n23[] = {3,2,-1};
 | |
| 	//new n24[] = {5,-1};
 | |
| 	//new n25[] = {6,2,6,-1};
 | |
| 	new String:s23[1024];
 | |
| 	new String:s24[40];
 | |
| 	new String:s25[1024];
 | |
| 	new n26[1024];
 | |
| 	new String:s26[1024];
 | |
| 	modpowBigInt(n23, n24, n25, 16, n26, sizeof(n26));
 | |
| 	bigInt2HexString(n23, s23, sizeof(s23));
 | |
| 	bigInt2HexString(n24, s24, sizeof(s24));
 | |
| 	bigInt2HexString(n25, s25, sizeof(s25));
 | |
| 	bigInt2HexString(n26, s26, sizeof(s26));
 | |
| 	PrintDebug(caller, "Modular Power Test");
 | |
| 	PrintDebug(caller, "base = %s", s23);
 | |
| 	PrintDebug(caller, "exponent = %s", s24);
 | |
| 	PrintDebug(caller, "modulus = %s", s25);
 | |
| 	PrintDebug(caller, "Result size: %i, result = \n%s", getBigIntSize(n26), s26);
 | |
| }
 | |
| */ |