Blog Entry © Sunday, October 19, 2025, by James Pate Williams, Jr. LIPCalculator (Large Integer Package Calculator)

Blog Entry © Wednesday, October 15, 2025, by James Pate Williams, Jr. Miscellaneous Algorithms from Chapters 2 and 4 of the “Handbook of Applied Cryptography” by Alfred J. Menezes, Paul C. van Oorschot, and Scott A. Vanstone

#pragma once
class PrimalityTests
{

public:

	static int Jacobi(long long a, long long n);

	static void LongLongToBits(
		long long n, std::vector<int>& bits);

	static long long ModPow(
		long long a, long long k, long long n);

	static bool MillerRabin(long long n, int t);

	static bool SolovayStrassen(long long n, int t);
};

#include "pch.h"
#include "PrimalityTests.h"

int PrimalityTests::Jacobi(long long a, long long n) {
	int s;
	long long a1, b = a, e = 0, m, n1;

	if (a == 0)
		return 0;

	if (a == 1)
		return 1;

	while ((b & 1) == 0)
		b >>= 1, e++;

	a1 = b;
	m = n % 8;

	if (!(e & 1))
		s = +1;
	else if (m == 1 || m == 7)
		s = +1;
	else if (m == 3 || m == 5)
		s = -1;

	if (n % 4 == 3 && a1 % 4 == 3)
		s = -s;

	if (a1 != 1)
		n1 = n % a1;
	else
		n1 = 1;

	return s * Jacobi(n1, a1);
}

void PrimalityTests::LongLongToBits(
	long long n, std::vector<int>& bits) {
	bits.clear();

	while (n > 0) {
		int digit = (int)(n % 2);
		bits.push_back(digit);
		n /= 2;
	}
} 

long long PrimalityTests::ModPow(
	long long a, long long k, long long n) {
	std::vector<int> kBits;
	LongLongToBits(k, kBits);

	long long b = 1;

	if (k == 0) {
		return b;
	}

	long long A = a;

	if (kBits[0] == 1) {
		b = a;
	}

	for (int i = 1; i < (int)kBits.size(); i++) {
		A = (A * A) % n;

		if (kBits[i] == 1) {
			b = (A * b) % n;
		}
	}

	return b;
}

bool PrimalityTests::MillerRabin(long long n, int t) {
	if (n == 2 || n == 3) {
		return true;
	}

	long long m = n % 2;

	if (m == 0) {
		return false;
	}

	long long n2 = n - 2;
	std::random_device rd;  // Seed generator
	std::mt19937 mt(rd());  // Mersenne Twister engine
	std::uniform_int_distribution<long long> dist(2, n2);

	long long n1 = n - 1;
	long long r = n1;
	long s = 0;

	m = r % 2;

	while (m == 0) {
		r = r / 2;
		m = r % 2;
		s++;
	}

	for (int i = 1; i <= t; i++) {
		long long a = dist(mt);
		long long y = ModPow(a, r, n);

		if (y != 1 && y != n1) {
			int j = 1;

			while (j <= s && y != n1) {
				y = ModPow(y, 2, n);

				if (y == 1)
					return false;

				j++;
			}

			if (y != n1)
				return false;
		}
	}

	return true;
}

bool PrimalityTests::SolovayStrassen(long long n, int t) {
	long long n1 = n - 1, n2 = n - 2, n12 = n1 / 2;
	std::random_device rd;  // Seed generator
	std::mt19937 mt(rd());  // Mersenne Twister engine
	std::uniform_int_distribution<long long> dist(2, n2);

	for (int i = 1; i <= t; i++) {
		long long a = dist(mt);
		long long r = ModPow(a, n12, n);

		if (r != 1 && r != n1)
			return false;

		int s = Jacobi(a, n);

		if (!(r == s) && !(s == -1 && r == n1))
			return false;
	}

	return true;
}

// ProbPrimalityTests.cpp (c) Monday, October 13, 2025
// Reference: "Handbook of Applied Cryptography" by
// Alfred J. Menezes, Paul C. van Oorschot, Scott A.
// Vanstone Chapters 2, 3, and 4
// https://www.walter-fendt.de/html5/men/primenumbers_en.htm

#include "pch.h"

int main()
{
	while (true) {
		std::string str = "";
		std::cout << "== Menu ==" << std::endl;
		std::cout << "1 Test Jacobi" << std::endl;
		std::cout << "2 Test To Bits" << std::endl;
		std::cout << "3 Test ModPow" << std::endl;
		std::cout << "4 Test Miller-Rabin" << std::endl;
		std::cout << "5 Test Solovay-Strassen" << std::endl;
		std::cout << "6 Exit" << std::endl;
		std::cout << "Option (1 - 6): ";
		std::getline(std::cin, str);
		int option = std::stoi(str);
		if (option < 1 || option > 6) {
			std::cout << "Illegal option" << std::endl;
			continue;
		}
		if (option == 6) {
			break;
		}
		switch (option)	{
		case 1:	{
			std::cout << "a = ";
			std::getline(std::cin, str);
			long long a = std::stoll(str);
			std::cout << "n = ";
			std::getline(std::cin, str);
			long long n = std::stoll(str);
			int j = PrimalityTests::Jacobi(a, n);
			std::cout << "Jacobi = " << j << std::endl;
			break;
		}
		case 2:	{
			std::vector<int> bits = { };
			std::cout << "n = ";
			std::getline(std::cin, str);
			long long n = std::stoll(str);
			PrimalityTests::LongLongToBits(n, bits);
			for (int i = (int)bits.size() - 1; i >= 0; i--) {
				std::cout << bits[i];
			}
			std::cout << std::endl;
			break;
		}
		case 3:	{
			std::cout << "a = ";
			std::getline(std::cin, str);
			long long a = std::stoll(str);
			std::cout << "k = ";
			std::getline(std::cin, str);
			long long k = std::stoll(str);
			std::cout << "n = ";
			std::getline(std::cin, str);
			long long n = std::stoll(str);
			long long m = PrimalityTests::ModPow(a, k, n);
			std::cout << "ModPow(a, k, n) = " << m << std::endl;
			break;
		}
		case 4:	{
			std::cout << "n = ";
			std::getline(std::cin, str);
			long long n = std::stoll(str);
			std::cout << "t = ";
			std::getline(std::cin, str);
			int t = std::stoi(str);
			bool mr = PrimalityTests::MillerRabin(n, t);
			std::cout << "Miller-Rabin = " << mr << std::endl;
			break;
		}
		case 5:	{
			std::cout << "n = ";
			std::getline(std::cin, str);
			long long n = std::stoll(str);
			std::cout << "t = ";
			std::getline(std::cin, str);
			int t = std::stoi(str);
			bool ss = PrimalityTests::SolovayStrassen(n, t);
			std::cout << "Solavay-Strassen = " << ss << std::endl;
			break;
		}
		}
	}
	return 0;
}

// pch.h: This is a precompiled header file.
// Files listed below are compiled only once, improving build performance for future builds.
// This also affects IntelliSense performance, including code completion and many code browsing features.
// However, files listed here are ALL re-compiled if any one of them is updated between builds.
// Do not add files here that you will be updating frequently as this negates the performance advantage.

#ifndef PCH_H
#define PCH_H
#include <iostream>
#include <random>
#include <string>
#include <vector>
#include "framework.h"
#include "PrimalityTests.h"
#endif //PCH_H

Blog Entry © Sunday, October 12, 2025, by James Pate Williams, Jr. More 64-Bit Factoring Using Pollard’s Cubic Integer Factoring Algorithm

Blog Entry © Saturday, October 11, 2025, by James Pate Williams, Jr., Starling’s Virial Expansion for a Real Gas or Liquid 1972

Blog Entry © Tuesday, September 30, 2025, by James Pate Williams, Jr. Win32 Desktop C++ App to Solve Small Instances of the N-Queens Puzzle Using a Permutation Based Algorithm and Chronological Backtracking

Blog Entry © Monday, September 29, 2025, A Win32 C++ Chronological Backtracking N-Queens Puzzle Solver for a Small Number of Queens by James Pate Williams, Jr.

Blog Entry © Thursday, September 11, 2025, by James Pate Wiliams, Jr. Modeling the Friedmann Equation in the Early Universe