Blog Entry © Wednesday, May 27, 2026, by James Pate Williams, Jr. and Microsoft’s Copilot Grade School Arithmetic

#pragma once
#include <stdint.h>

/* Algorithm due to Microsft's Coilot 
function udiv_restoring(N, D, n) :
    R = 0
    Q = 0

    negD = (~D + 1)

    for i from n - 1 down to 0
    {
        R = (R << 1) | ((N >> i) & 1)

    T = R + negD

    if MSB(T) == 0:
        R = T
        Q = Q | (1 << i)

    return (Q, R) 
 */

class Arithmetic
{
public:
    static bool udiv_restoring(
        uint32_t numer,
        uint32_t denom,
        uint32_t& quo,
        uint32_t& rem,
        int n);
    static bool umul_shift_add(
        uint32_t a,
        uint32_t b,
        uint64_t& product,
        int n);
};

#include <cstdint>
#include "Arithmetic.h"

static inline uint32_t mask_n(int bits) {
    return (bits >= 32) ? 0xFFFFFFFFu : ((1u << bits) - 1u);
}

static inline uint32_t msb(uint32_t x, int bits) {
    // returns top bit of a 'bits'-wide value
    return (x >> (bits - 1)) & 1u;
}

bool Arithmetic::udiv_restoring(
    uint32_t numer,
    uint32_t denom,
    uint32_t& quo,
    uint32_t& rem,
    int n)
{
    if (denom == 0 || n <= 0 || n > 32) return false;
    
    if (numer == 0)
    {
        quo = rem = 0;
        return true;
    }

    quo = 0;
    rem = 0;

    if (n == 32) {
        uint64_t R = 0;
        uint64_t D = (uint64_t)denom;
        uint64_t maskW = (1ull << 33) - 1ull;           // 33-bit mask
        uint64_t negD = ((~D) + 1ull) & maskW;          // 33-bit two's complement

        for (int i = n - 1; i >= 0; --i) {
            R = ((R << 1) | ((numer >> i) & 1u)) & maskW;

            uint64_t T = (R + negD) & maskW;         // R - D

            // Sign bit is bit 32 (the 33rd bit)
            if (((T >> 32) & 1ull) == 0ull) {
                R = T;
                quo |= (1u << i);
            }
        }
        rem = (uint32_t)(R & 0xFFFFFFFFu);
        return true;
    }

    // n < 32 case: we can keep everything in uint32_t using (n+1) bits
    uint32_t maskN = mask_n(n);
    uint32_t maskW = mask_n(n + 1);

    uint32_t N = numer & maskN;
    uint32_t D = denom & maskN;

    // Two's complement of D in (n+1) bits
    uint32_t Dw = D;                  // placed in low bits of (n+1)-wide register
    uint32_t negD = ((~Dw) + 1u) & maskW;

    uint32_t R = 0;

    for (int i = n - 1; i >= 0; --i) {
        R = ((R << 1) | ((N >> i) & 1u)) & maskW;

        uint32_t T = (R + negD) & maskW;            // trial subtract: R - D (in w bits)

        if (msb(T, n + 1) == 0) {                   // non-negative in (n+1) bits
            R = T;
            quo |= (1u << i);
        }
    }

    rem = R & maskN;                                // remainder fits in n bits
    return true;
}

bool Arithmetic::umul_shift_add(
    uint32_t a,
    uint32_t b,
    uint64_t& product,
    int n)
{
    if (n <= 0 || n > 32) return false;

    uint64_t A = a;    // promote to avoid overflow
    uint32_t B = b;

    product = 0;

    for (int i = 0; i < n; ++i) {
        if (B & 1u) {
            product += A;
        }

        A <<= 1;
        B >>= 1;
    }

    return true;
}

#include <chrono>
#include <cstdint>
#include <iostream>
#include <limits>
#include <random>
#include <string>
#include "Arithmetic.h"

namespace {

    constexpr int TESTS_PER_N = 200000;

    uint32_t make_mask(int n) {
        return (n == 32) ? 0xFFFFFFFFu : ((1u << n) - 1u);
    }

    void clear_bad_input() {
        std::cin.clear();
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    }

    template <typename TrialFn>
    double run_suite(const char* label, TrialFn trial, bool verbose) {
        std::mt19937 rng(12345); // deterministic

        auto t0 = std::chrono::high_resolution_clock::now();

        for (int n = 1; n <= 32; ++n) {
            const uint32_t mask = make_mask(n);

            for (int i = 0; i < TESTS_PER_N; ++i) {
                if (!trial(rng, mask, n)) {
                    std::cout << label << ": FAILED (n=" << n << ", i=" << i << ")\n";
                    return -1.0;
                }
            }

            if (verbose) {
                std::cout << "n=" << n << " passed\n";
            }
        }

        auto t1 = std::chrono::high_resolution_clock::now();
        double secs = std::chrono::duration<double>(t1 - t0).count();

        std::cout << label << " runtime = " << secs << " sec\n";
        return secs;
    }

    bool trial_division(std::mt19937& rng, uint32_t mask, int n) {
        const uint32_t numer = rng() & mask;
        const uint32_t denom = (rng() & mask) | 1u; // ensure non-zero

        uint32_t q = 0, r = 0;
        if (!Arithmetic::udiv_restoring(numer, denom, q, r, n)) {
            std::cout << "Failure numer=" << numer << " denom=" << denom << "\n";
            return false;
        }

        const uint32_t q2 = numer / denom;
        const uint32_t r2 = numer % denom;

        if (q != q2 || r != r2) {
            std::cout << "Mismatch n=" << n
                << " numer=" << numer
                << " denom=" << denom
                << " got q=" << q << " r=" << r
                << " expected q=" << q2 << " r=" << r2 << "\n";
            return false;
        }
        return true;
    }

    bool trial_multiplication(std::mt19937& rng, uint32_t mask, int n) {
        const uint32_t a = rng() & mask;
        const uint32_t b = rng() & mask;

        uint64_t prod = 0;
        if (!Arithmetic::umul_shift_add(a, b, prod, n)) {
            std::cout << "Failure a=" << a << " b=" << b << "\n";
            return false;
        }

        const uint64_t expected = static_cast<uint64_t>(a) * static_cast<uint64_t>(b);
        if (prod != expected) {
            std::cout << "Mismatch n=" << n
                << " a=" << a
                << " b=" << b
                << " got=" << prod
                << " expected=" << expected << "\n";
            return false;
        }
        return true;
    }

} // namespace

int main() {
    bool verbose = true;

    while (true) {
        std::cout << "\nArithmetic Lab\n";
        std::cout << "1. Test Division (restoring)\n";
        std::cout << "2. Test Multiplication (shift-add)\n";
        std::cout << "3. Run ALL tests\n";
        std::cout << "4. Toggle verbose (currently " << (verbose ? "ON" : "OFF") << ")\n";
        std::cout << "5. Exit\n";
        std::cout << "Choice: ";

        int choice = 0;
        if (!(std::cin >> choice)) {
            clear_bad_input();
            std::cout << "Invalid input. Please enter a number.\n";
            continue;
        }

        if (choice == 1) {
            run_suite("Division test", trial_division, verbose);
        }
        else if (choice == 2) {
            run_suite("Multiplication test", trial_multiplication, verbose);
        }
        else if (choice == 3) {
            const double d = run_suite("Division test", trial_division, verbose);
            if (d >= 0.0) run_suite("Multiplication test", trial_multiplication, verbose);
        }
        else if (choice == 4) {
            verbose = !verbose;
        }
        else if (choice == 5) {
            return 0;
        }
        else {
            std::cout << "Invalid choice.\n";
        }
    }
}

Blog Entry (c) Tuesday, May 26, 2026, by James Pate Williams, Jr. and Microsoft’s Copilot Hydrogen-Like Atomic Radial Wave Functions

Included a downloadable PDF and Microsoft Excel Workbook.

Blog Entry (c) Monday, May 25, 2026, by James Pate Williams, Jr. Quantum Mechanical Linear Harmonic Oscillator

Blog Entry (c) Friday, May 22, 2024, by James Pate Williams, Jr. and Microsoft’s Copilot (AI Agent)

Cheerwing U12S Mini RC Helicopter with Camera Remote Control Helicopter for Kids and Adults Preflight and Start Checklist found on Amazon.com

Blog Entry © Sunday, May 17, 2026, by James Pate Williams, Jr. Derivation of the Time Independent Free Particle Schrödinger Equation in Confocal Parabolic Coordinates

Blog Entry © Saturday, May 16, 2026, by James Pate Williams, Jr. Some More Linear Algebra Examples

Blog Entry © Thursday, May 14, 2026, by James Pate Williams, Jr. More Numerical Integration Results

// NumericalIntegrals.cpp (c) Thursday, May 14, 2026
// by James Pate Williams, Jr., BA, BS, MSwE, PhD

#include <iomanip>
#include <iostream>
#include <vector>
#include <stdlib.h>

static double f(double x) {
    return sin(x);
}

static double MonteCarlo(double a, double b,
    double (*f)(double), int n){ 
    double sum = 0;

    for (int i = 0; i < n; i++) {
        double x = (b - a) * (double)rand() / RAND_MAX;

        sum += f(x);
    }

    return (b - a) * sum / n;
}

static double Factorial(int n) {
    double factorial = 1.0;

    for (int i = 2; i <= n; i++)
        factorial *= i;

    return factorial;
}

static double Series(double a, double b, int n)
{
    double sumA = 0.0, sumB = 0.0;
    int sign = 1;

    for (int i = 0; i <= n; i++) {
        sumA += sign * pow(a, 2 * i + 2) /
            Factorial(2 * i + 2);

        sign *= -1;
    }

    sign = 1;

    for (int i = 0; i <= n; i++) {      
        sumB += sign * pow(b, 2 * i + 2) /
            Factorial(2 * i + 2);

        sign *= -1;
    }

    return sumB - sumA;
}

static double CompositeTrapezoidalRule(
    double a, double b, int n) {
    double pi = 4.0 * atan(1.0);
    double endPts = 0.5 * (f(a) + f(b));
    double sum = 0, xk = 0.0;
    double h = (b - a) / n;

    for (int k = 1; k <= n - 1; k++) {
        xk = a + k * h;
        sum += f(xk);
    }

    return h * (0.5 * endPts + sum);
}

static double SimpsonsRule(
    int n, double a, double b, double(*fx)(double)) {
    double h = (b - a) / n;
    double h2 = 2.0 * h;
    double s = 0.0;
    double t = 0.0;
    double x = a + h;

    for (int i = 1; i < n; i += 2) {
        s += fx(x);
        x += h2;
    }

    x = a + h2;

    for (int i = 2; i < n; i += 2) {
        t += fx(x);
        x += h2;
    }

    return h * (fx(a) + 4 * s + 2 * t + fx(b)) / 3.0;
}

static void Romberg(double a, double b,
    double (*f)(double), int mStart, int nRow,
    std::vector<std::vector<double>>& T) {
    int m = mStart;
    double h = (b - a) / m;
    double sum = 0.5 * (f(a) + f(b));

    if (m > 1) {
        for (int i = 1; i <= m - 1; i++) {
            sum += f(a + i * h);
        }
    }

    T[0][0] = sum * h;

    std::cout << "romberg t-table" << std::endl;
    std::cout << std::fixed;
    std::cout << std::setprecision(5) << T[0][0];
    std::cout << std::endl;

    if (nRow < 2)
        return;

    for (int k = 2; k <= nRow; k++) {
        h /= 2.0;
        m *= 2;
        sum = 0.0;

        for (int i = 1; i <= m; i += 2) {
            sum += f(a + i * h);
        }

        T[k][1] = 0.5 * T[k - 1LL][1] + sum * h;

        for (int j = 1; j <= k - 1; j++) {
            T[k - 1LL][j] = T[k][j] - T[k - 1LL][j];
            T[k][j + 1LL] = T[k][j] + T[k - 1LL][j] /
                (pow(4.0, j) - 1.0);
        }

        for (int j = 1; j <= k; j++) {
            std::cout << std::fixed;
            std::cout << std::setprecision(5);
            std::cout << T[k][j] << '\t';
        }

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

    if (nRow < 3) {
        return;
    }

    std::cout << "table of ratios" << std::endl;
    double ratio = 0.0;

    for (int k = 1; k <= nRow - 2; k++) {
        for (int j = 1; j <= k; j++) {
            if (T[k + 1LL][j] == 0.0) {
                ratio = 0.0;
            }

            else {
                ratio = T[k][j] / T[k + 1LL][j];
            }

            T[k][j] = ratio;
        }

        for (int j = 1; j <= k; j++) {
            std::cout << std::fixed;
            std::cout << std::setprecision(5);
            std::cout << T[k][j] << '\t';
        }

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

double MonteCarloVolume(double R, int n)
{
    double pi = 4.0 * atan(1.0), pi2 = 2.0 * pi;
    double R2 = R * R, sum = 0;

    for (int i = 0; i < n; i++)
    {
        double r = R2 * (double)rand() / RAND_MAX;
        double t = pi * (double)rand() / RAND_MAX;
        double p = pi2 * (double)rand() / RAND_MAX;
        sum += r * r * sin(t);
    }

    return R * pi * pi2 * sum / n;
}

int main()
{
    srand(1);
    std::vector<std::vector<double>> T;
    T.resize(35);
    for (int i = 0; i < 35; i++) {
        T[i].resize(35);
    }
    Romberg(0.0, 2.0, f, 2, 7, T);
    std::cout << std::setprecision(11);
    std::cout << "analytic integral of sine = " << -cos(2.0) + cos(0.0);
    std::cout << std::endl;
    std::cout << "simpson's rule integral   = " << SimpsonsRule(500, 0, 2.0, f);
    std::cout << std::endl;
    std::cout << "monte carlo integral      = " << MonteCarlo(0.0, 2.0, f, 2130);
    std::cout << std::endl;
    std::cout << "infinite series integral  = " << Series(0.0, 2.0, 16);
    std::cout << std::endl;
    double integral = CompositeTrapezoidalRule(0.0, 2.0, 175000000);
    std::cout << "romberg integral          = " << integral << std::endl;
    std::cout << "actual spherical volume   = " << 4.0 * 4.0 * atan(1.0) / 3.0;
    std::cout << std::endl;
    double volume = MonteCarloVolume(1.0, 1000000);
    std::cout << "approx spherical volume   = " << volume;
    std::cout << std::endl;
}

Blog Entry © Wednesday, May 13, 2026, by James Pate Williams, Jr. Adaptive n-Quadrature Versus Monte Carlo Integration

Blog Entry © Monday, May 11, 2026, by James Pate Williams, Jr., Laplace Equation in a Solid Cylinder