Blog Entry © Saturday, November 28, 2025, by James Pate Williams, Jr. Fair Coin and Fair Dice Probabilities

Blog Entry © Tuesday 25, 2025, by James Pate Williams, Jr. Enumeration of the Tic-Tac-Toe Game Tree

/*
 *  Board.h
 *  Permutation
 *
 *  Created by James Pate Williams, Jr. on 7/21/08.
 *	Modified on Monday 11/24/2025 
 *  Copyright 2008 James Pate Williams, Jr. All rights reserved.
 *
 */

#ifndef _Board_
#define _Board_

#include <fstream>
#include <vector>

class Board {
	private:
		
		char state[9];
		std::vector<std::vector<char>> board;

	public:
		
		Board(void);
		Board(const Board &board);
		Board(const char b[3][3]);
		Board(const std::vector<char> &v);
		
		char GetState(int n) const;
		void PrintBoard(int n) const;
		void WriteBoard(std::ofstream &out) const;
		
		friend bool operator == (const Board &b1, const Board &b2);
		friend bool operator != (const Board &b1, const Board &b2);
		friend bool Found(const Board &initial, const Board &board);
		friend bool Win(const Board b, char winner[8]);
		friend bool LegalBoard(
			bool& legal, bool& won, char& whoWon, const Board b);
		friend void PrintBoard(char board[3][3], int number);
		
		static const char CharX, CharO, CharS;
};

#endif

/*
 *  Board.cpp
 *  Permutation
 *
 *  Created by James Pate Williams, Jr. on 7/21/08.
 *  Copyright 2008 James Pate Williams, Jr. All rights reserved.
 *
 */

#include <algorithm>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <vector>
#include "Board.h"

const char Board::CharO = 'o';
const char Board::CharX = 'x';
const char Board::CharS = '_';

Board::Board(void) {
	board.resize(3, std::vector<char>(3));
	for (int i = 0; i < 9; i++)
		state[i] = '\0';
}

Board::Board(const Board &b) {
	board.resize(3, std::vector<char>(3));
	for (int i = 0; i < 3; i++)
		for (int j = 0; j < 3; j++)
			state[3 * i + j] = board[i][j] = b.state[3 * i + j];
}

Board::Board(const char b[3][3]) {
	board.resize(3, std::vector<char>(3));
	for (int i = 0; i < 3; i++)
		for (int j = 0; j < 3; j++)
			state[3 * i + j] = board[i][j] = b[i][j];
}

Board::Board(const std::vector<char> &v) {
	board.resize(3, std::vector<char>(3));
	for (int i = 0; i < 3; i++)
		for (int j = 0; j < 3; j++)
			state[3 * i + j] = board[i][j] = v[3LL * i + j];
}

char Board::GetState(int n) const {
	return state[n];
}

void Board::PrintBoard(int n) const  {
	std::cout << n << std::endl;
	
	for (int i = 0; i < 3; i++) {
	
		for (int j = 0; j < 3; j++)
			std::cout << state[3 * i + j];
				
		std::cout << std::endl;
	}
	
	std::cout << std::endl;
	std::cout << std::endl;
}

void Board::WriteBoard(std::ofstream &out) const {
	for (int i = 0; i < 9; i++) 
		out << state[i];
				
	out << std::endl;
}

bool operator == (const Board &b1, const Board &b2) {
	int i, equal = 0;
	
	for (i = 0; i < 9; i++)
		if (b1.state[i] == b2.state[i])
			equal++;

	return equal == 9;
}

bool operator != (const Board &b1, const Board &b2) {
	for (int i = 0; i < 9; i++)
		if (b1.state[i] == b2.state[i])
			return false;
	
	return true;
}

bool Found(const Board &initial, const Board &board) {

	// reflections
	
	if (initial.state[0] == board.state[6] && initial.state[1] == board.state[7] &&
		initial.state[2] == board.state[8] && initial.state[3] == board.state[3] &&
		initial.state[4] == board.state[4] && initial.state[5] == board.state[5] &&
		initial.state[6] == board.state[0] && initial.state[7] == board.state[1] &&
		initial.state[8] == board.state[2])
		return true;
		
	if (initial.state[0] == board.state[2] && initial.state[1] == board.state[1] &&
		initial.state[2] == board.state[0] && initial.state[3] == board.state[5] &&
		initial.state[4] == board.state[4] && initial.state[5] == board.state[3] &&
		initial.state[6] == board.state[8] && initial.state[7] == board.state[7] &&
		initial.state[8] == board.state[6])
		return true;
	
	if (initial.state[0] == board.state[0] && initial.state[1] == board.state[3] &&
		initial.state[2] == board.state[6] && initial.state[3] == board.state[1] &&
		initial.state[4] == board.state[4] && initial.state[5] == board.state[7] &&
		initial.state[6] == board.state[2] && initial.state[7] == board.state[5] &&
		initial.state[8] == board.state[8])
		return true;

	if (initial.state[0] == board.state[8] && initial.state[1] == board.state[5] &&
		initial.state[2] == board.state[2] && initial.state[3] == board.state[7] &&
		initial.state[4] == board.state[4] && initial.state[5] == board.state[1] &&
		initial.state[6] == board.state[6] && initial.state[7] == board.state[3] &&
		initial.state[8] == board.state[0])
		return true;

	// rotations
	
	if (initial.state[0] == board.state[6] && initial.state[1] == board.state[3] &&
		initial.state[2] == board.state[0] && initial.state[3] == board.state[7] &&
		initial.state[4] == board.state[4] && initial.state[5] == board.state[1] &&
		initial.state[6] == board.state[8] && initial.state[7] == board.state[5] &&
		initial.state[8] == board.state[2])
		return true;
			
	if (initial.state[0] == board.state[8] && initial.state[1] == board.state[7] &&
		initial.state[2] == board.state[6] && initial.state[3] == board.state[5] &&
		initial.state[4] == board.state[4] && initial.state[5] == board.state[3] &&
		initial.state[6] == board.state[2] && initial.state[7] == board.state[1] &&
		initial.state[8] == board.state[0])
		return true;
	
	if (initial.state[0] == board.state[2] && initial.state[1] == board.state[5] &&
		initial.state[2] == board.state[8] && initial.state[3] == board.state[1] &&
		initial.state[4] == board.state[4] && initial.state[5] == board.state[7] &&
		initial.state[6] == board.state[0] && initial.state[7] == board.state[3] &&
		initial.state[8] == board.state[6])
		return true;
			
	// equal

	return initial == board;
}

bool Win(const Board b, char winner[8]) {
	bool win = false;
	
	for (int i = 0; i < 8; i++)
		winner[i] = Board::CharS;

	if (b.board[0][0] == b.board[0][1] && b.board[0][0] == 
		b.board[0][2] && b.board[0][0] != Board::CharS) {
		winner[0] = b.board[0][0];
		win = true;
	}
	
	if (b.board[1][0] == b.board[1][1] && b.board[1][0] ==
		b.board[1][2] && b.board[1][0] != Board::CharS)  {
		winner[1] = b.board[1][0];
		win = true;
	}
	
	if (b.board[2][0] == b.board[2][1] && b.board[2][0] == 
		b.board[2][2] && b.board[2][0] != Board::CharS)  {
		winner[2] = b.board[2][0];
		win = true;
	}
	
	if (b.board[0][0] == b.board[1][0] && b.board[0][0] == 
		b.board[2][0] && b.board[0][0] != Board::CharS)  {
		winner[3] = b.board[0][0];
		win = true;
	}
	
	if (b.board[0][1] == b.board[1][1] && b.board[0][1] == 
		b.board[2][1] && b.board[0][1] != Board::CharS)  {
		winner[4] = b.board[0][1];
		win = true;
	}
	
	if (b.board[0][2] == b.board[1][2] && b.board[0][2] == 
		b.board[2][2] && b.board[0][2] != Board::CharS)  {
		winner[5] = b.board[0][2];
		win = true;
	}
	
	if (b.board[0][0] == b.board[1][1] && b.board[0][0] == 
		b.board[2][2] && b.board[0][0] != Board::CharS)  {
		winner[6] = b.board[0][0];
		win = true;
	}                
	
	if (b.board[0][2] == b.board[1][1] && b.board[0][2] == 
		b.board[2][0] && b.board[0][2] != Board::CharS)  {
		winner[7] = b.board[0][2];
		win = true;
	}

	return win;
}
	
void PrintBoard(char board[3][3], int number) {
	
	std::cout << "number = " << number << std::endl;
	std::cout << std::endl;

	for (int i = 0; i < 3; i++) {
	
		for (int j = 0; j < 3; j++)
			std::cout << board[i][j];
		
		std:: cout << std::endl;
	}

	std::cout << std::endl;
}

bool LegalBoard(
	bool &legal, bool &won, char &whoWon, const Board b) {
	bool winO, winX;
	char winner[8];
	int countO = 0, countS = 0, countX = 0;
	int i, j, oWins = 0, xWins = 0;
	
	legal = won = false;
	
	for (i = 0; i < 3; i++) {
	
		for (j = 0; j < 3; j++) {
			if (b.board[i][j] == Board::CharO)
				countO++;
			else if (b.board[i][j] == Board::CharX)
				countX++;
			else if (b.board[i][j] == Board::CharS)
				countS++;
		}
	}

	if ((countX >= 3 || countO >= 3) && Win(b, winner)) {
	
		for (i = 0; i < 8; i++) {
			if (winner[i] == Board::CharX)
				xWins++;
			else if (winner[i] == Board::CharO)
				oWins++;
		}
		
		winX = (xWins  >= 1 && oWins == 0) && 
			   (countX <= 5 && countO <= 4 && countX == countO + 1);
		
		winO = (xWins  == 0 && oWins >= 1) &&
			   (countO <= 5 && countX <= 4 && countO == countX + 1);
		
		legal = won = winX || winO;

		if (won && winX)
			whoWon = Board::CharX;
		else if (won && winO)
			whoWon = Board::CharO;
	}
	else
		legal = (countX <= 5 && countO <= 4 && countX == countO + 1) ||
			    (countO <= 5 && countX <= 4 && countO == countX + 1);
			  
	return legal;
}

#define _WriteBV_
#include <algorithm>

#ifdef _WriteBV_
#include <fstream>
#endif

#include <iomanip>
#include <iostream>
#include <vector>
#include "Board.h"

static int Compare(const void *vPtr1, const void *vPtr2) {
	char *cPtr1 = (char *) vPtr1;
	char *cPtr2 = (char *) vPtr2;

	return strcmp(cPtr1, cPtr2);
}

static void EnumerateTicTacToe(void) {
	bool legal, won;
	char b[3][3], whoWon;
	char tree[3][3][3][3][3][3][3][3][3];
	int i0, i1, i2, i3, i4, i5, i6, i7, i8;
	int legals = 0, number = 0, wCount = 0;
	int xCount = 0, oCount = 0;
	int bvSize, i, j;

	std::vector<Board> boardVector;
	
	for (i0 = 0; i0 < 3; i0++) {
	for (i1 = 0; i1 < 3; i1++) {
	for (i2 = 0; i2 < 3; i2++) {
	for (i3 = 0; i3 < 3; i3++) {
	for (i4 = 0; i4 < 3; i4++) {
	for (i5 = 0; i5 < 3; i5++) {
	for (i6 = 0; i6 < 3; i6++) {
	for (i7 = 0; i7 < 3; i7++) {
	for (i8 = 0; i8 < 3; i8++) {
		if (i0 == 0)
			b[0][0] = tree[i0][i1][i2][i3][i4][i5][i6][i7][i8] = Board::CharX;
		else if (i0 == 1)
			b[0][0] = tree[i0][i1][i2][i3][i4][i5][i6][i7][i8] = Board::CharO;
		else if (i0 == 2)
			b[0][0] = tree[i0][i1][i2][i3][i4][i5][i6][i7][i8] = Board::CharS;
				
		if (i1 == 0)
			b[0][1] = tree[i0][i1][i2][i3][i4][i5][i6][i7][i8] = Board::CharX;
		else if (i1 == 1)
			b[0][1] = tree[i0][i1][i2][i3][i4][i5][i6][i7][i8] = Board::CharO;
		else if (i1 == 2)
			b[0][1] = tree[i0][i1][i2][i3][i4][i5][i6][i7][i8] = Board::CharS;

		if (i2 == 0)
			b[0][2] = tree[i0][i1][i2][i3][i4][i5][i6][i7][i8] = Board::CharX;
		else if (i2 == 1)
			b[0][2] = tree[i0][i1][i2][i3][i4][i5][i6][i7][i8] = Board::CharO;
		else if (i2 == 2)
			b[0][2] = tree[i0][i1][i2][i3][i4][i5][i6][i7][i8] = Board::CharS;

		if (i3 == 0)
			b[1][0] = tree[i0][i1][i2][i3][i4][i5][i6][i7][i8] = Board::CharX;
		else if (i3 == 1)
			b[1][0] = tree[i0][i1][i2][i3][i4][i5][i6][i7][i8] = Board::CharO;
		else if (i3 == 2)
			b[1][0] = tree[i0][i1][i2][i3][i4][i5][i6][i7][i8] = Board::CharS;

		if (i4 == 0)
			b[1][1] = tree[i0][i1][i2][i3][i4][i5][i6][i7][i8] = Board::CharX;
		else if (i4 == 1)
			b[1][1] = tree[i0][i1][i2][i3][i4][i5][i6][i7][i8] = Board::CharO;
		else if (i4 == 2)
			b[1][1] = tree[i0][i1][i2][i3][i4][i5][i6][i7][i8] = Board::CharS;
			
		if (i5 == 0)
			b[1][2] = tree[i0][i1][i2][i3][i4][i5][i6][i7][i8] = Board::CharX;
		else if (i5 == 1)
			b[1][2] = tree[i0][i1][i2][i3][i4][i5][i6][i7][i8] = Board::CharO;
		else if (i5 == 2)
			b[1][2] = tree[i0][i1][i2][i3][i4][i5][i6][i7][i8] = Board::CharS;
			
		if (i6 == 0)
			b[2][0] = tree[i0][i1][i2][i3][i4][i5][i6][i7][i8] = Board::CharX;
		else if (i6 == 1)
			b[2][0] = tree[i0][i1][i2][i3][i4][i5][i6][i7][i8] = Board::CharO;
		else if (i6 == 2)
			b[2][0] = tree[i0][i1][i2][i3][i4][i5][i6][i7][i8] = Board::CharS;
			
		if (i7 == 0)
			b[2][1] = tree[i0][i1][i2][i3][i4][i5][i6][i7][i8] = Board::CharX;
		else if (i7 == 1)
			b[2][1] = tree[i0][i1][i2][i3][i4][i5][i6][i7][i8] = Board::CharO;
		else if (i7 == 2)
			b[2][1] = tree[i0][i1][i2][i3][i4][i5][i6][i7][i8] = Board::CharS;
			
		if (i8 == 0)
			b[2][2] = tree[i0][i1][i2][i3][i4][i5][i6][i7][i8] = Board::CharX;
		else if (i8 == 1)
			b[2][2] = tree[i0][i1][i2][i3][i4][i5][i6][i7][i8] = Board::CharO;
		else if (i8 == 2)
			b[2][2] = tree[i0][i1][i2][i3][i4][i5][i6][i7][i8] = Board::CharS;
		
		Board bb(b);

		if (LegalBoard(legal, won, whoWon, bb)) {
			Board board(b);

			legals++;
		
			if (won) {
				wCount++;
				
				if (whoWon == Board::CharX)
					xCount++;
				else if (whoWon == Board::CharO)
					oCount++;
			}
			
			boardVector.push_back(board);
		}
		
		number++;

	}}}}}}}}}

	for (i = 0; i < boardVector.size() - 1; i++)
		for (j = i; j < boardVector.size(); j++)
			if (Found(boardVector[i], boardVector[j]))
				boardVector.erase(boardVector.begin() + j);

	bvSize = (int)boardVector.size();
	std::cout << std::setw(4) << "legal total = " << legals << std::endl;
	std::cout << std::setw(4) << "xWins total = " << xCount << std::endl;
	std::cout << std::setw(4) << "oWins total = " << xCount << std::endl;
	std::cout << std::setw(4) << "oxWin total = " << xCount + oCount << std::endl;
	std::cout << std::setw(4) << "unique size = " << boardVector.size();
	std::cout << std::endl;
	
#ifdef _WriteBV_
 
	std::cout << std::endl;
	std::ofstream outFile("Tic TacToe Game Tree Enumeration.txt");
	std::cout << std::endl;
	
	for (i = 0; i < bvSize; i++) {
		boardVector[i].PrintBoard(i + 1);
		boardVector[i].WriteBoard(outFile);
	}

#endif
}

int main (int argc, char * const argv[]) {
	EnumerateTicTacToe();
    return 0;
}

Blog Entry © Monday, November 24, 2025, by James Pate Williams, Jr., A* Informed Search Application to Solve the 15-Tile Puzzle

Blog Entry © Sunday, November 23, 2025, by James Pate Williams, Jr. Modification of My A* Informed Search Solver for the 8-Tile Puzzle

Blog Entry © Friday, November 21, 2025, by James Pate Williams, Jr., Win32 C/C++ Desktop GUI Solution of the 15-Tile Puzzle Using Iterative Deepening A* Informed Seach Algorithm

Blog Entry © Monday, November 17, 2025, by James Pate Williams, Jr. An Elitist Evolutionary Hill Climber to Solve the 8-Tile Puzzle

Blog Entry © Wednesday, September 3, 2025, by James Pate Williams, Jr. Solution of Exercise 1.11 in Modern Quantum Chemistry an Introduction to Advanced Electronic Structure Theory © 1996 by Attila Szabo and Neil S. Ostlund

// EigenVV2x2.cpp (c) Wednesday, September 3, 2025
// by James Pate Williams, Jr., BA, BS, MSwE, PhD
// Solution to Exercise 1.11 in "Quantum Chemistry
// an Introduction to Advanced Electronic Structure
// Theory (c) 1996 by Attila Szabo and Neil S. Ostlund 

#include "pch.h"
#include "framework.h"
#include "EigenVV2x2.h"

#define MAX_LOADSTRING 100

// Global Variables:
HINSTANCE hInst;                                // current instance
WCHAR szTitle[MAX_LOADSTRING];                  // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING];            // the main window class name
std::wstring text;                              // output wide string

// Forward declarations of functions included in this code module:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: Place code here.

    // Initialize global strings
    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadStringW(hInstance, IDC_EIGENVV2X2, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // Perform application initialization:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

    HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_EIGENVV2X2));

    MSG msg;

    // Main message loop:
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}

//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEXW wcex;

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_EIGENVV2X2));
    wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_EIGENVV2X2);
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassExW(&wcex);
}

//
//   FUNCTION: InitInstance(HINSTANCE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // Store instance handle in our global variable

   HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

#define IDC_STATIC1         1000
#define IDC_STATIC2         1010
#define IDC_STATIC3         1020
#define IDC_STATIC4         1030

#define IDC_EDIT_A11        2000
#define IDC_EDIT_A12        2010
#define IDC_EDIT_A21        2020
#define IDC_EDIT_A22        2030
#define IDC_EDIT_MULTILINE  3000

#define IDC_BUTTON_COMPUTE  4000
#define IDC_BUTTON_CANCEL   4010

//
//  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  PURPOSE: Processes messages for the main window.
//
//  WM_COMMAND  - process the application menu
//  WM_PAINT    - Paint the main window
//  WM_DESTROY  - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static HFONT hFont = { };
    static HWND hEditMultiline = { };
    static HWND hEditA11 = { };
    static HWND hEditA12 = { };
    static HWND hEditA21 = { };
    static HWND hEditA22 = { };

    switch (message)
    {
    case WM_CREATE:
    {
        hFont = CreateFont(16, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
            ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
            DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, L"Courier New Bold");

        CreateWindowEx(0, L"STATIC", L"A[1][1]:", WS_CHILD | WS_VISIBLE,
            10, 10, 80, 20, hWnd, (HMENU)IDC_STATIC1, hInst, NULL);
        CreateWindowEx(0, L"STATIC", L"A[1][2]:", WS_CHILD | WS_VISIBLE,
            10, 40, 80, 20, hWnd, (HMENU)IDC_STATIC2, hInst, NULL);
        CreateWindowEx(0, L"STATIC", L"A[2][1]:", WS_CHILD | WS_VISIBLE,
            10, 70, 80, 20, hWnd, (HMENU)IDC_STATIC3, hInst, NULL);
        CreateWindowEx(0, L"STATIC", L"A[2][2]:", WS_CHILD | WS_VISIBLE,
            10, 100, 80, 20, hWnd, (HMENU)IDC_STATIC4, hInst, NULL);

        hEditA11 = CreateWindowEx(0, L"EDIT", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER,
            100, 10, 200, 20, hWnd, (HMENU)IDC_EDIT_A11, hInst, NULL);
        hEditA12 = CreateWindowEx(0, L"EDIT", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER,
            100, 40, 200, 20, hWnd, (HMENU)IDC_EDIT_A12, hInst, NULL);
        hEditA21 = CreateWindowEx(0, L"EDIT", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER,
            100, 70, 200, 20, hWnd, (HMENU)IDC_EDIT_A21, hInst, NULL);
        hEditA22 = CreateWindowEx(0, L"EDIT", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER,
            100, 100, 200, 20, hWnd, (HMENU)IDC_EDIT_A22, hInst, NULL);

        hEditMultiline = CreateWindowEx(
            WS_EX_CLIENTEDGE,                       // Extended style for sunken border
            TEXT("EDIT"),                           // Class name
            TEXT(""),                               // Initial text (can be blank)
            WS_CHILD | WS_VISIBLE | WS_VSCROLL | ES_AUTOHSCROLL |
            ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL | WS_HSCROLL | WS_VSCROLL,
            310, 10, 300, 300,                      // Position and size
            hWnd,                                   // Parent window handle
            (HMENU)IDC_EDIT_MULTILINE,              // Unique control ID
            hInst,                                  // Application instance
            NULL                                    // Extra parameter
        );

        CreateWindowEx(0, L"BUTTON", L"Compute", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
            10, 130, 80, 30, hWnd, (HMENU)IDC_BUTTON_COMPUTE, hInst, NULL);
        CreateWindowEx(0, L"BUTTON", L"Cancel", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
            220, 130, 80, 30, hWnd, (HMENU)IDC_BUTTON_CANCEL, hInst, NULL);

        SendMessage(hEditMultiline, WM_SETFONT, (WPARAM)hFont, TRUE);
        SetDlgItemText(hWnd, IDC_EDIT_A11, L"3");
        SetDlgItemText(hWnd, IDC_EDIT_A12, L"1");
        SetDlgItemText(hWnd, IDC_EDIT_A21, L"1");
        SetDlgItemText(hWnd, IDC_EDIT_A22, L"3");
    }
    break;
    case WM_COMMAND:
        {
            int wmId = LOWORD(wParam);
            // Parse the menu selections:
            switch (wmId)
            {
            case IDM_ABOUT:
                DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                break;
            case IDC_BUTTON_COMPUTE:
            {
                WCHAR line[128] = L"";

                text = L"";

                // eigenvalues
                std::vector<double> omega(3);
                // matrix
                std::vector<std::vector<double>> A(3,
                    std::vector<double>(3));
                std::vector<std::vector<double>> B(3,
                    std::vector<double>(3));
                // eigenvectors
                std::vector<std::vector<double>> c(3,
                    std::vector<double>(3));

                GetWindowText(hEditA11, line, 128);
                std::wstring A11Str(line);
                A[1][1] = std::stod(A11Str);
                GetWindowText(hEditA12, line, 128);
                std::wstring A12Str(line);
                A[1][2] = std::stod(A12Str);
                GetWindowText(hEditA21, line, 128);
                std::wstring A21Str(line);
                A[2][1] = std::stod(A21Str);
                GetWindowText(hEditA22, line, 128);
                std::wstring A22Str(line);
                A[2][2] = std::stod(A22Str);
                
                double term1 = A[1][1] + A[2][2];
                double term2 = pow(A[2][2] - A[1][1], 2.0);
                double term3 = 4.0 * A[1][2] * A[2][1];

                // compute eigenvalues

                omega[1] = 0.5 * (term1 - sqrt(term2 + term3));
                omega[2] = 0.5 * (term1 + sqrt(term2 + term3));

                swprintf_s(line, L"Eigenvalues:\r\n\r\n");
                text += std::wstring(line);
                swprintf_s(line, L"omega 1 = %13.10lf\r\n", omega[1]);
                text += std::wstring(line);
                swprintf_s(line, L"omega 2 = %13.10lf\r\n\r\n", omega[2]);
                text += std::wstring(line);

                // compute eigenvalues using a unitary transformation 
                // matrix A must be symmetric

                double theta0 = 0.0;

                if (A[1][1] == A[2][2])
                {
                    theta0 = 0.5 * acos(0.0);
                }

                else
                {
                    theta0 = 0.5 * atan(2.0 * A[1][2] /
                        (A[1][1] - A[2][2]));
                }

                // compute the eigenvalues
                
                omega[1] = A[1][1] * pow(cos(theta0), 2.0) +
                    A[2][2] * pow(sin(theta0), 2.0) +
                    A[1][2] * sin(2.0 * theta0);
                omega[2] = A[1][1] * pow(cos(theta0), 2.0) +
                    A[2][2] * pow(sin(theta0), 2.0) -
                    A[1][2] * sin(2.0 * theta0);
                
                swprintf_s(line, L"Eigenvalues:\r\n\r\n");
                text += std::wstring(line);
                swprintf_s(line, L"omega 1 = %13.10lf\r\n", omega[1]);
                text += std::wstring(line);
                swprintf_s(line, L"omega 2 = %13.10lf\r\n\r\n", omega[2]);
                text += std::wstring(line);

                // compute eigenvectors

                c[1][1] = cos(theta0);
                c[1][2] = sin(theta0);
                c[2][1] = sin(theta0);
                c[2][2] = -cos(theta0);

                swprintf_s(line, L"Eigenvectors:\r\n\r\n");
                text += std::wstring(line);
                swprintf_s(line, L"c 11 = %13.10lf\r\n", c[1][1]);
                text += std::wstring(line);
                swprintf_s(line, L"c 12 = %13.10lf\r\n", c[1][2]);
                text += std::wstring(line);
                swprintf_s(line, L"c 21 = %13.10lf\r\n", c[2][1]);
                text += std::wstring(line);
                swprintf_s(line, L"c 22 = %13.10lf\r\n", c[2][2]);
                text += std::wstring(line);
                SetWindowText(hEditMultiline, text.c_str());
                break;
            }
            case IDC_BUTTON_CANCEL:
            {
                PostQuitMessage(0);
                break;
            }
            break;
            case IDM_EXIT:
                DestroyWindow(hWnd);
                break;
            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
        break;
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            // TODO: Add any drawing code that uses hdc here...
            EndPaint(hWnd, &ps);
        }
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}

Blog Entry © Sunday, March 29, 2025, by James Pate Williams, Jr., BA, BS, Master of Software Engineering, PhD Slater Determinant Coefficients for Z = 2 to 4

Enter the atomic number Z (2 to 6 or 0 to quit): 2
2       1       1       +       a(1)b(2)
1       0       0       -       a(2)b(1)
# Even Permutations = 1
Enter the atomic number Z (2 to 6 or 0 to quit): 3
6       3       1       +       a(1)b(2)c(3)
5       2       0       -       a(1)b(3)c(2)
4       2       0       -       a(2)b(1)c(3)
3       1       1       +       a(2)b(3)c(1)
2       1       1       +       a(3)b(1)c(2)
1       0       0       -       a(3)b(2)c(1)
# Even Permutations = 3
Enter the atomic number Z (2 to 6 or 0 to quit): 4
24      12      0       +       a(1)b(2)c(3)d(4)
23      11      1       -       a(1)b(2)c(4)d(3)
22      11      1       -       a(1)b(3)c(2)d(4)
21      10      0       +       a(1)b(3)c(4)d(2)
20      10      0       +       a(1)b(4)c(2)d(3)
19      9       1       -       a(1)b(4)c(3)d(2)
18      9       1       -       a(2)b(1)c(3)d(4)
17      8       0       +       a(2)b(1)c(4)d(3)
16      8       0       +       a(2)b(3)c(1)d(4)
15      7       1       -       a(2)b(3)c(4)d(1)
14      7       1       -       a(2)b(4)c(1)d(3)
13      6       0       +       a(2)b(4)c(3)d(1)
12      6       0       +       a(3)b(1)c(2)d(4)
11      5       1       -       a(3)b(1)c(4)d(2)
10      5       1       -       a(3)b(2)c(1)d(4)
9       4       0       +       a(3)b(2)c(4)d(1)
8       4       0       +       a(3)b(4)c(1)d(2)
7       3       1       -       a(3)b(4)c(2)d(1)
6       3       1       -       a(4)b(1)c(2)d(3)
5       2       0       +       a(4)b(1)c(3)d(2)
4       2       0       +       a(4)b(2)c(1)d(3)
3       1       1       -       a(4)b(2)c(3)d(1)
2       1       1       -       a(4)b(3)c(1)d(2)
1       0       0       +       a(4)b(3)c(2)d(1)
# Even Permutations = 12
Enter the atomic number Z (2 to 6 or 0 to quit):
// AOPermutations.cpp : This file contains the 'main' function.
// Program execution begins and ends there.
// Copyright (c) Saturday, March 29, 2025
// by James Pate Williams, Jr., BA, BS, MSwE, PhD
// Signs of the atomic orbitals in a Slater Determinant

#include <algorithm>
#include <iostream>
#include <string>
#include <vector>

int main()
{
    char alpha[] = { 'a', 'b', 'c', 'd', 'e', 'f' }, line[128] = {};
    int factorial[7] = { 1, 1, 2, 6, 24, 120, 720 };

    while (true)
    {
        int col = 0, counter = 0, row = 0, sign = 1, t = 0, Z = 0, zfact = 0;
        int numberEven = 0;
        std::cout << "Enter the atomic number Z (2 to 6 or 0 to quit): ";
        std::cin.getline(line, 127);
        std::string str(line);
        Z = std::stoi(str);

        if (Z == 0)
        {
            break;
        }

        if (Z < 2 || Z > 6)
        {
            std::cout << "Illegal Z, please try again" << std::endl;
            continue;
        }

        zfact = factorial[Z];

        std::vector<char> orb(Z);
        std::vector<int> tmp(Z), vec(Z);

        for (int i = 0; i < Z; i++)
        {
            orb[i] = alpha[i];
            vec[i] = i + 1;
        }

        do
        {
            for (int i = 0; i < (int)vec.size(); i++)
            {
                tmp[i] = vec[i];
            }

            t = 0;

            do
            {
                t++;
            } while (std::next_permutation(tmp.begin(), tmp.end()));

            std::cout << t << '\t' << t / 2 << '\t';
            std::cout << (t / 2 & 1) << '\t';

            if (Z == 2 || Z == 3)
            {
                if ((t / 2 & 1) == 0)
                {
                    std::cout << "-\t";
                }

                else
                {
                    std::cout << "+\t";
                    numberEven++;
                }
            }

            else
            {
                if ((t / 2 & 1) == 1)
                {
                    std::cout << "-\t";
                }

                else
                {
                    std::cout << "+\t";
                    numberEven++;
                }
            }

            for (int i = 0; i < Z; i++)
            {
                std::cout << orb[i] << '(' << vec[i] << ')';
            }

            row++;
            std::cout << std::endl;

            if (zfact != 2 && row == zfact)
            {
                std::cout << std::endl;
                break;
            }

            row %= Z;
        } while (std::next_permutation(vec.begin(), vec.end()));

        std::cout << "# Even Permutations = ";
        std::cout << numberEven << std::endl;
    }

    return 0;
}

Blog Entry © Thursday, January 23, 2025, by James Pate Williams, Jr. Fresnel Integral Tables and Source Code

Fresnel Cosine Integral

x C(x) Lau C(x) NBS % Difference
-0.620000 -0.5977736837 -0.5970137789 0.1272033494
-0.570400 -0.5556807496 -0.5553215257 0.0646666400
-0.520800 -0.5114255691 -0.5112670118 0.0310078114
-0.471200 -0.4655007132 -0.4654362526 0.0138485424
-0.421600 -0.4183252709 -0.4183015697 0.0056659009
-0.372000 -0.3702461017 -0.3702384156 0.0020759626
-0.322400 -0.3215416213 -0.3215395006 0.0006595409
-0.272800 -0.2724274481 -0.2724269764 0.0001731156
-0.223200 -0.2230633569 -0.2230632794 0.0000347412
-0.173600 -0.1735611006 -0.1735610925 0.0000046509
-0.124000 -0.1239927667 -0.1239927663 0.0000003151
-0.074400 -0.0743994375 -0.0743994375 0.0000000053
-0.024800 -0.0247999977 -0.0247999977 0.0000000000
0.024800 0.0247999977 0.0247999977 0.0000000000
0.074400 0.0743994375 0.0743994375 0.0000000053
0.124000 0.1239927667 0.1239927663 0.0000003151
0.173600 0.1735611006 0.1735610925 0.0000046509
0.223200 0.2230633569 0.2230632794 0.0000347412
0.272800 0.2724274481 0.2724269764 0.0001731156
0.322400 0.3215416213 0.3215395006 0.0006595409
0.372000 0.3702461017 0.3702384156 0.0020759626
0.421600 0.4183252709 0.4183015697 0.0056659009
0.471200 0.4655007132 0.4654362526 0.0138485424
0.520800 0.5114255691 0.5112670118 0.0310078114
0.570400 0.5556807496 0.5553215257 0.0646666400
0.620000 0.5977736837 0.5970137789 0.1272033494

Fresnel Sine Integral

x S(x) Lau S(x) Integral % Difference
-0.6200000000 -0.1215759428 -0.1215759428 0.0000000000
-0.5704000000 -0.0953732384 -0.0953732384 0.0000000000
-0.5208000000 -0.0730090407 -0.0730090407 0.0000000000
-0.4712000000 -0.0543049498 -0.0543049498 0.0000000000
-0.4216000000 -0.0390194784 -0.0390194784 0.0000000000
-0.3720000000 -0.0268634258 -0.0268634258 0.0000000000
-0.3224000000 -0.0175128445 -0.0175128445 0.0000000000
-0.2728000000 -0.0106195909 -0.0106195909 0.0000000000
-0.2232000000 -0.0058195744 -0.0058195744 0.0000000000
-0.1736000000 -0.0027389132 -0.0027389132 0.0000000000
-0.1240000000 -0.0009982644 -0.0009982644 0.0000000000
-0.0744000000 -0.0002156329 -0.0002156329 0.0000000000
-0.0248000000 -0.0000079864 -0.0000079864 0.0000000000
0.0248000000 0.0000079864 0.0000079864 0.0000000000
0.0744000000 0.0002156329 0.0002156329 0.0000000000
0.1240000000 0.0009982644 0.0009982644 0.0000000000
0.1736000000 0.0027389132 0.0027389132 0.0000000000
0.2232000000 0.0058195744 0.0058195744 0.0000000000
0.2728000000 0.0106195909 0.0106195909 0.0000000000
0.3224000000 0.0175128445 0.0175128445 0.0000000000
0.3720000000 0.0268634258 0.0268634258 0.0000000000
0.4216000000 0.0390194784 0.0390194784 0.0000000000
0.4712000000 0.0543049498 0.0543049498 0.0000000000
0.5208000000 0.0730090407 0.0730090407 0.0000000000
0.5704000000 0.0953732384 0.0953732384 0.0000000000
0.6200000000 0.1215759428 0.1215759428 0.0000000000

// FresnelFunctions.cpp : Defines the entry point for the application.
// (c) Thursday, January 23, 2025, by James Pate Williams, Jr.
// Tables of Fresnel Integrals C(x) and S(x)
// References: "A Numerical Library in C for Scientists and Engineers"
// (c) 1995 by H. T. Lau also the National Bureau of Standards and
// https://nvlpubs.nist.gov/nistpubs/jres/102/3/j23mie.pdf
// https://digital.library.unt.edu/ark:/67531/metadc40301/m2/1/high_res_d/applmathser55_w.pdf

#include "framework.h"
#include "FresnelFunctions.h"
#include <chrono>
#include <cwchar>
#include <vector>

#define MAX_LOADSTRING 100

// resource definitions

#define IDC_EDIT1 201
#define IDC_EDIT2 202
#define IDC_EDIT3 203
#define IDC_EDIT4 204
#define IDC_EDIT5 205

#define IDC_STATIC1 301
#define IDC_STATIC2 302
#define IDC_STATIC3 303
#define IDC_STATIC4 304

#define IDC_BUTTON_COMPUTE 401
#define IDC_BUTTON_CLEAR 402

// Global Variables:

HINSTANCE hInst;                                // current instance
WCHAR szTitle[MAX_LOADSTRING];                  // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING];            // the main window class name
WCHAR buffer[16834], line[128];

// Forward declarations of functions included in this code module:

ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    // TODO: Place code here.

    // Initialize global strings

    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadStringW(hInstance, IDC_FRESNELFUNCTIONS, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    // Perform application initialization:

    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }

    HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_FRESNELFUNCTIONS));

    MSG msg;

    // Main message loop:

    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}
//
//  FUNCTION: MyRegisterClass()
//
//  PURPOSE: Registers the window class.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEXW wcex = { };

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_FRESNELFUNCTIONS));
    wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_FRESNELFUNCTIONS);
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassExW(&wcex);
}
//
//   FUNCTION: InitInstance(HINSTANCE, int)
//
//   PURPOSE: Saves instance handle and creates main window
//
//   COMMENTS:
//
//        In this function, we save the instance handle in a global variable and
//        create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // Store instance handle in our global variable

   HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);

   if (!hWnd)
   {
      return FALSE;
   }

   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

void fg_lau(double, double*, double*);

void fresnel_lau(double x, double* c, double* s)
{
	double absx, x3, x4, a, p, q, f, g, c1, s1;

	absx = fabs(x);
	if (absx <= 1.2) {
		a = x * x;
		x3 = a * x;
		x4 = a * a;
		p = (((5.47711385682687e-6 * x4 - 5.28079651372623e-4) * x4 +
			1.76193952543491e-2) * x4 - 1.99460898826184e-1) * x4 + 1.0;
		q = (((1.18938901422876e-7 * x4 + 1.55237885276994e-5) * x4 +
			1.09957215025642e-3) * x4 + 4.72792112010453e-2) * x4 + 1.0;
		*c = x * p / q;
		p = (((6.71748466625141e-7 * x4 - 8.45557284352777e-5) * x4 +
			3.87782123463683e-3) * x4 - 7.07489915144523e-2) * x4 +
			5.23598775598299e-1;
		q = (((5.95281227678410e-8 * x4 + 9.62690875939034e-6) * x4 +
			8.17091942152134e-4) * x4 + 4.11223151142384e-2) * x4 + 1.0;
		*s = x3 * p / q;
	}
	else if (absx <= 1.6) {
		a = x * x;
		x3 = a * x;
		x4 = a * a;
		p = ((((-5.68293310121871e-8 * x4 + 1.02365435056106e-5) * x4 -
			6.71376034694922e-4) * x4 + 1.91870279431747e-2) * x4 -
			2.07073360335324e-1) * x4 + 1.00000000000111e0;
		q = ((((4.41701374065010e-10 * x4 + 8.77945377892369e-8) * x4 +
			1.01344630866749e-5) * x4 + 7.88905245052360e-4) * x4 +
			3.96667496952323e-2) * x4 + 1.0;
		*c = x * p / q;
		p = ((((-5.76765815593089e-9 * x4 + 1.28531043742725e-6) * x4 -
			1.09540023911435e-4) * x4 + 4.30730526504367e-3) * x4 -
			7.37766914010191e-2) * x4 + 5.23598775598344e-1;
		q = ((((2.05539124458580e-10 * x4 + 5.03090581246612e-8) * x4 +
			6.87086265718620e-6) * x4 + 6.18224620195473e-4) * x4 +
			3.53398342767472e-2) * x4 + 1.0;
		*s = x3 * p / q;
	}
	else if (absx < 1.0e15) {
		fg_lau(x, &f, &g);
		a = x * x;
		a = (a - floor(a / 4.0) * 4.0) * 1.57079632679490;
		c1 = cos(a);
		s1 = sin(a);
		a = (x < 0.0) ? -0.5 : 0.5;
		*c = f * s1 - g * c1 + a;
		*s = -f * c1 - g * s1 + a;
	}
	else
		*c = *s = ((x > 0.0) ? 0.5 : -0.5);
}

void fg_lau(double x, double* f, double* g)
{
	double absx, c, s, c1, s1, a, xinv, x3inv, c4, p, q;

	absx = fabs(x);
	if (absx <= 1.6) {
		fresnel_lau(x, &c, &s);
		a = x * x * 1.57079632679490;
		c1 = cos(a);
		s1 = sin(a);
		a = (x < 0.0) ? -0.5 : 0.5;
		p = a - c;
		q = a - s;
		*f = q * c1 - p * s1;
		*g = p * c1 + q * s1;
	}
	else if (absx <= 1.9) {
		xinv = 1.0 / x;
		a = xinv * xinv;
		x3inv = a * xinv;
		c4 = a * a;
		p = (((1.35304235540388e1 * c4 + 6.98534261601021e1) * c4 +
			4.80340655577925e1) * c4 + 8.03588122803942e0) * c4 +
			3.18309268504906e-1;
		q = (((6.55630640083916e1 * c4 + 2.49561993805172e2) * c4 +
			1.57611005580123e2) * c4 + 2.55491618435795e1) * c4 + 1.0;
		*f = xinv * p / q;
		p = ((((2.05421432498501e1 * c4 + 1.96232037971663e2) * c4 +
			1.99182818678903e2) * c4 + 5.31122813480989e1) * c4 +
			4.44533827550512e0) * c4 + 1.01320618810275e-1;
		q = ((((1.01379483396003e3 * c4 + 3.48112147856545e3) * c4 +
			2.54473133181822e3) * c4 + 5.83590575716429e2) * c4 +
			4.53925019673689e1) * c4 + 1.0;
		*g = x3inv * p / q;
	}
	else if (absx <= 2.4) {
		xinv = 1.0 / x;
		a = xinv * xinv;
		x3inv = a * xinv;
		c4 = a * a;
		p = ((((7.17703249365140e2 * c4 + 3.09145161574430e3) * c4 +
			1.93007640786716e3) * c4 + 3.39837134926984e2) * c4 +
			1.95883941021969e1) * c4 + 3.18309881822017e-1;
		q = ((((3.36121699180551e3 * c4 + 1.09334248988809e4) * c4 +
			6.33747155851144e3) * c4 + 1.08535067500650e3) * c4 +
			6.18427138172887e1) * c4 + 1.0;
		*f = xinv * p / q;
		p = ((((3.13330163068756e2 * c4 + 1.59268006085354e3) * c4 +
			9.08311749529594e2) * c4 + 1.40959617911316e2) * c4 +
			7.11205001789783e0) * c4 + 1.01321161761805e-1;
		q = ((((1.15149832376261e4 * c4 + 2.41315567213370e4) * c4 +
			1.06729678030581e4) * c4 + 1.49051922797329e3) * c4 +
			7.17128596939302e1) * c4 + 1.0;
		*g = x3inv * p / q;
	}
	else {
		xinv = 1.0 / x;
		a = xinv * xinv;
		x3inv = a * xinv;
		c4 = a * a;
		p = ((((2.61294753225142e4 * c4 + 6.13547113614700e4) * c4 +
			1.34922028171857e4) * c4 + 8.16343401784375e2) * c4 +
			1.64797712841246e1) * c4 + 9.67546032967090e-2;
		q = ((((1.37012364817226e6 * c4 + 1.00105478900791e6) * c4 +
			1.65946462621853e5) * c4 + 9.01827596231524e3) * c4 +
			1.73871690673649e2) * c4 + 1.0;
		*f = (c4 * (-p) / q + 0.318309886183791) * xinv;
		p = (((((1.72590224654837e6 * c4 + 6.66907061668636e6) * c4 +
			1.77758950838030e6) * c4 + 1.35678867813756e5) * c4 +
			3.87754141746378e3) * c4 + 4.31710157823358e1) * c4 +
			1.53989733819769e-1;
		q = (((((1.40622441123580e8 * c4 + 9.38695862531635e7) * c4 +
			1.62095600500232e7) * c4 + 1.02878693056688e6) * c4 +
			2.69183180396243e4) * c4 + 2.86733194975899e2) * c4 + 1.0;
		*g = (c4 * (-p) / q + 0.101321183642338) * x3inv;
	}
}

double S(double z)
{
	int n = 768;
	double a = 0.0;
	double b = z;
	double h = (b - a) / n;
	double h2 = 2.0 * h;
	double s = 0.0;
	double t = 0.0;
	double x = a + h;
	double pi = 4.0 * atan(1.0);
	
	for (int i = 1; i < n; i += 2)
	{
		s += sin(pi * x * x / 2.0);
		x += h2;
	}

	x = a + h2;

	for (int i = 2; i < n; i += 2)
	{
		t += sin(pi * x * x / 2.0);
		x += h2;
	}

	double endA = 0.0;
	double endB = sin(pi * z * z / 2.0);
	return h * (endA + 4 * s + 2 * t + endB) / 3.0;
}

void fresnel_nbs(double x, double* c, double* s)
{
	double pi = 4.0 * atan(1.0);

	*c = x - pi * pi * pow(x, 5.0) / 40.0 -
		pi * pi * pi * pi * pow(x, 9.0) / 3456.0;
	// the following computation is in error
	*s = -pi / 6.0 + pi * pi * pi * pow(x, 7.0) / 336.0 -
		pow(pi, 5.0) * pow(x, 11.0) / 42240.0;
	// resort to Simpson's Rule with n = 16384
	*s = S(x);
} 

//
//  FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  PURPOSE: Processes messages for the main window.
//
//  WM_COMMAND  - process the application menu
//  WM_PAINT    - Paint the main window
//  WM_DESTROY  - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	double lt = 0.0, rt = 0.0;
	int cors = 1, nPts = 0;
	WCHAR* endPt;
	static HWND hwndEdit1 = 0, hwndEdit2 = 0;
	static HWND hwndEdit3 = 0, hwndEdit4 = 0, hwndEdit5 = 0;

	switch (message)
	{
	case WM_CREATE:
	{
		CreateWindowEx(0, L"STATIC", L"Lt Point:", WS_CHILD | WS_VISIBLE,
			10, 10, 80, 20, hWnd, (HMENU)IDC_STATIC1, GetModuleHandle(NULL), NULL);
		CreateWindowEx(0, L"STATIC", L"Rt Point:", WS_CHILD | WS_VISIBLE,
			10, 40, 80, 20, hWnd, (HMENU)IDC_STATIC2, GetModuleHandle(NULL), NULL);
		CreateWindowEx(0, L"STATIC", L"n Points:", WS_CHILD | WS_VISIBLE,
			10, 70, 80, 20, hWnd, (HMENU)IDC_STATIC3, GetModuleHandle(NULL), NULL);
		CreateWindowEx(0, L"STATIC", L"C 1, S, 2:", WS_CHILD | WS_VISIBLE,
			10, 100, 80, 20, hWnd, (HMENU)IDC_STATIC4, GetModuleHandle(NULL), NULL);

		hwndEdit1 = CreateWindowEx(0, L"EDIT", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER,
			100, 10, 200, 20, hWnd, (HMENU)IDC_EDIT1, GetModuleHandle(NULL), NULL);
		hwndEdit2 = CreateWindowEx(0, L"EDIT", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER,
			100, 40, 200, 20, hWnd, (HMENU)IDC_EDIT2, GetModuleHandle(NULL), NULL);
		hwndEdit3 = CreateWindowEx(0, L"EDIT", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER,
			100, 70, 200, 20, hWnd, (HMENU)IDC_EDIT3, GetModuleHandle(NULL), NULL);
		hwndEdit4 = CreateWindowEx(0, L"EDIT", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER,
			100, 100, 200, 20, hWnd, (HMENU)IDC_EDIT4, GetModuleHandle(NULL), NULL);
		hwndEdit5 = CreateWindowEx(0, L"EDIT", NULL, WS_CHILD | WS_VISIBLE | WS_BORDER
			| ES_MULTILINE, 100, 170, 400, 400, hWnd, (HMENU)IDC_EDIT5,
			GetModuleHandle(NULL), NULL);

		CreateWindowEx(0, L"BUTTON", L"Compute", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
			10, 130, 80, 30, hWnd, (HMENU)IDC_BUTTON_COMPUTE, GetModuleHandle(NULL), NULL);
		CreateWindowEx(0, L"BUTTON", L"Clear", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
			220, 130, 80, 30, hWnd, (HMENU)IDC_BUTTON_CLEAR, GetModuleHandle(NULL), NULL);

		SetDlgItemText(hWnd, IDC_EDIT1, L"-0.62");
		SetDlgItemText(hWnd, IDC_EDIT2, L"+0.62");
		SetDlgItemText(hWnd, IDC_EDIT3, L"25");
		SetDlgItemText(hWnd, IDC_EDIT4, L"1");
	}
    case WM_COMMAND:
        {
            int wmId = LOWORD(wParam);

            // Parse the menu selections:
			
			switch (wmId)
			{
			case IDC_BUTTON_COMPUTE:
			{
				buffer[0] = { '/0' };
				GetWindowText(hwndEdit1, line, 127);
				lt = wcstod(line, &endPt);

				if (!(lt >= -0.62 && lt <= 0.50))
				{
					MessageBox(hWnd, L"Must be -0.62 <= lt <= 0.50", L"Warning",
						MB_OK | MB_ICONWARNING);
					return 0;
				}

				GetWindowText(hwndEdit2, line, 127);
				rt = wcstod(line, &endPt);

				if (!(rt >= 0.51 && rt <= 0.62))
				{
					MessageBox(hWnd, L"Must be 0.51 <= rt <= 0.62", L"Warning",
						MB_OK | MB_ICONWARNING);
					return 0;
				}

				nPts = GetDlgItemInt(hWnd, IDC_EDIT3, FALSE, FALSE);

				if (nPts < 1 || nPts > 25)
				{
					MessageBox(hWnd, L"n-points must be >= 1 & <= 25", L"Warning",
						MB_OK | MB_ICONWARNING);
					return 0;
				}

				cors = GetDlgItemInt(hWnd, IDC_EDIT4, FALSE, FALSE);

				if (!(cors == 1 || cors == 2))
				{
					MessageBox(hWnd, L"C(x) = 1 or S(x) = 2", L"Warning",
						MB_OK | MB_ICONWARNING);
					return 0;
				}

				if (cors == 1)
				{
					wsprintf(line, L"Fresnel Cosine Integral\r\n\r\n");
					wcscpy_s(buffer, 16383, line);
					wsprintf(line, L"x\t\tC(x) Lau\t\tC(x) NBS\t\t%% Difference\r\n");
					wcscat_s(buffer, 16383, line);
				}

				else if (cors == 2)
				{
					wsprintf(line, L"Fresnel Sine Integral\r\n\r\n");
					wcscpy_s(buffer, 16383, line);
					wsprintf(line, L"x\t\tS(x) Lau\t\tS(x) Integral\t%% Difference\r\n");
					wcscat_s(buffer, 16383, line);
				}

				double deltaX = (rt - lt) / nPts, x = lt;

				for (int i = 0; i <= nPts; i++)
				{
					double c1 = 0.0, c2 = 0.0, s1 = 0.0, s2 = 0.0;
					double percentDifference = 0.0;
					double cx = x, sx = x;

					fresnel_lau(cx, &c1, &s1);
					fresnel_nbs(sx, &c2, &s2);

					if (cors == 1)
					{
						percentDifference = fabs(c1 - c2) / fabs((c1 + c2) / 2.0);
						swprintf_s(
							line, L"%13.6lf\t%13.10lf\t%13.10lf\t%13.10lf\r\n",
							cx, c1, c2, 100.0 * percentDifference);
						wcscat_s(buffer, 16383, line);
					}

					else if (cors == 2)
					{
						percentDifference = fabs(s1 - s2) / fabs((s1 + s2) / 2.0);
						swprintf_s(
							line, L"%13.10lf\t%13.10lf\t%13.10lf\t%13.10lf\r\n",
							sx, s1, s2, 100.0 * percentDifference);
						wcscat_s(buffer, 16383, line);
					}

					x += deltaX;
				}

				SetDlgItemText(hWnd, IDC_EDIT5, buffer);
			}
			break;
			case IDC_BUTTON_CLEAR:
			{
				wcscpy_s(buffer, 16383, L"\0");
				SetDlgItemText(hWnd, IDC_EDIT5, buffer);
			}
			break;
            case IDM_ABOUT:
                DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                break;
            case IDM_EXIT:
                DestroyWindow(hWnd);
                break;
            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
        break;
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            // TODO: Add any drawing code that uses hdc here...
            EndPaint(hWnd, &ps);
        }
        break;
	case WM_SIZE:
		if (hwndEdit5)
		{
			RECT rcClient;
			GetClientRect(hWnd, &rcClient);
			SetWindowPos(hwndEdit5, NULL, 10, 170, rcClient.right - 20,
				rcClient.bottom - 20, SWP_NOZORDER);
		}
		break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}

// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;

    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}

Blog Entry © Thursday, January 23, 2025, by James Pate Williams, Jr. Ackermann’s Super-Exponential Recursive Function in Vanilla C Programming Language

i = 2
j = 1
a(2, 1) =
4
# decimal digits = 1
enter another set (n to quit)? y
i = 2
j = 2
a(2, 2) =
16
# decimal digits = 2
enter another set (n to quit)? y
i = 2
j = 3
a(2, 3) =
65536
# decimal digits = 5
enter another set (n to quit)? y
i = 2
j = 4
a(2, 4) =
200352993040684646497907235156025575044782547556975141926501697371089\
405955631145308950613088093334810103823434290726318182294938211881266886\
950636476154702916504187191635158796634721944293092798208430910485599057\
015931895963952486337236720300291696959215610876494888925409080591145703\
767520850020667156370236612635974714480711177481588091413574272096719015\
183628256061809145885269982614142503012339110827360384376787644904320596\
037912449090570756031403507616256247603186379312648470374378295497561377\
098160461441330869211810248595915238019533103029216280016056867010565164\
...
506264233788565146467060429856478196846159366328895429978072254226479040\
061601975197500746054515006029180663827149701611098795133663377137843441\
619405312144529185518013657555866761501937302969193207612000925506508158\
327550849934076879725236998702356793102680413674571895664143185267905471\
716996299036301554564509004480278905570196832831363071899769915316667920\
895876857229060091547291963638167359667395997571032601557192023734858052\
112811745861006515259888384311451189488055212914577569914657753004138471\
712457796504817585639507289533753975582208777750607233944558789590571915\
6736
# decimal digits = 19729
enter another set (n to quit)?
/* 
** Computation of Akermann's super
** exponential function by James
** Pate Williams, Jr. (c) Tuesday,
** August 27, 2024 lip version
*/

#include <stdio.h>
#include "lip.h"

verylong Ackermann(verylong zi, verylong zj) {
	verylong a = 0;
	if (zscompare(zi, 1) == 0) {
		verylong ztwo = 0;
		zintoz(2, &ztwo);
		zexp(ztwo, zj, &a);
		return a;
	}
	else if (zscompare(zj, 1) == 0)
	{
		verylong ztwo = 0, ziminus1 = 0;
		zintoz(2, &ztwo);
		zsadd(zi, -1, &ziminus1);
		return Ackermann(ziminus1, ztwo);
	}
	else if (
		zscompare(zi, 2) >= 0 &&
		zscompare(zj, 2) >= 0) {
		verylong ziminus1 = 0;
		verylong zjminus1 = 0;
		verylong temp = 0;
		zsadd(zi, -1, &ziminus1);
		zsadd(zj, -1, &zjminus1);
		if (zscompare(ziminus1, 1) >= 0 &&
			zscompare(zjminus1, 1) >= 0) {
			return
				Ackermann(ziminus1, Ackermann(zi, zjminus1));
		}
	}
	return 0;
}

int DigitCount(verylong za) {
	int count = 0;
	while (zscompare(za, 0) > 0) {
		zsdiv(za, 10, &za);
		count++;
	}
	return count;
}

int main(void) {
	for (;;) {
		char buffer[256] = { '\0' };
		int i = 0, j = 0, number = 0;
		verylong za = 0, zi = 0, zj = 0;
		buffer[0] = '\0';
		printf_s("i = ");
		scanf_s("%d", &i);
		printf_s("j = ");
		scanf_s("%d", &j);
		zintoz(i, &zi);
		zintoz(j, &zj);
		printf_s("a(%d, %d) = \n", i, j);
		za = Ackermann(zi, zj);
		zwriteln(za);
		number = DigitCount(za);
		printf_s("# decimal digits = %d\n",
			number);
		printf_s("enter another set (n to quit)? ");
		scanf_s("%s", buffer, sizeof(buffer));
		zfree(&za);
		if (buffer[0] == 'n')
			break;
	}
	return 0;
}