Mercury Has Landed: Arbitrary-Precision Math for JWCEssentials

I am happy to announce that Mercury has now joined the JWCEssentials family.

Mercury is a native C library for arbitrary-precision floating-point arithmetic. It is designed around a simple but powerful idea: instead of forcing large numbers through decimal-first thinking, Mercury stores them in a machine-native base-232 positional format.

That means each “digit” of the number is a 32-bit unsigned integer. On modern hardware, this is a very natural way to build large-number arithmetic, because two 32-bit words can be multiplied with room for the result and carry inside a 64-bit operation. It is not base 10 dressed up for the machine. It is the machine’s own kind of arithmetic brought closer to the surface.

Why Mercury?

One of the most interesting lessons from writing big-number software is that representation matters. Decimal is excellent for people. Binary and hexadecimal are excellent for machines. Mercury leans into that distinction.

A Mercury number is stored as a sign flag, an exponent, and a sequence of 32-bit mantissa words. The number can then be viewed cleanly through hexadecimal, where each 32-bit word maps perfectly to eight hex digits. This gives hexadecimal a special role: it becomes a transparent window into the native representation, rather than a lossy-looking conversion layer.

That makes Mercury especially useful for the kinds of topics I want to write more about: arbitrary precision, numerical representation, computation, multiplication, division, square roots, powers, logs, and eventually the bridge between numerical engines and computer algebra systems.

The Native Core and the Managed Wrapper

Mercury itself lives as a native C library under:

JWCEssentials/C/Mercury

The managed wrapper lives in:

JWCEssentials/Project/JWCEssentials.net

The wrapper assembly is named Mercury.net. I chose that name intentionally. Mercury should be able to stand on its own as a numerical engine without being over-branded. JWCEssentials can host it, document it, and build around it, but the library itself deserves a clean identity.

On the .NET side, the wrapper exposes the native engine through UltraNumber, giving C# code a much friendlier surface: operator overloads, parsing, string conversion, precision management, and thread-local stack handling.

The Scratch Stack Model

One of Mercury’s design choices that I especially like is that arithmetic functions do not casually allocate temporary memory from the heap. Instead, Mercury uses a caller-supplied scratch stack.

That design keeps temporary allocation explicit, deterministic, and fast. A function asks the stack for temporary space, performs the calculation, and then releases that space in reverse order. This makes the native engine easier to reason about and keeps the door open for GPU-minded execution models, where memory discipline matters.

In other words, Mercury is not just a big-number library. It is also an experiment in making the “nuts and bolts” of arbitrary-precision computation visible and teachable.

A Base-232 View of Math

Most of us are trained to think in base 10. That is natural, cultural, and useful. But the machine does not owe base 10 any special loyalty.

When Mercury prints a number in hexadecimal, it is not merely choosing a programmer-friendly display format. It is showing the number in a form that lines up directly with the internal representation. Eight hex digits correspond exactly to one 32-bit word.

That makes hexadecimal a kind of inspection window. It lets us look at a large computed value without immediately paying the cost, complexity, and conceptual distraction of decimal conversion.

For example, π begins in hexadecimal as:

3.243F6A8885A308D313198A2E03707344A4093822...

That may look unusual if decimal is the only familiar lens, but it is not less mathematical. It is simply a different coordinate system for the same value.

Where This Is Going

Mercury gives me a stable base for a series of articles I have wanted to write for a long time.

I want to talk about multiplication at the limb level. I want to show how large-number division works. I want to explore square roots, powers, logarithms, and constants such as π and e. I also want to connect those topics to the larger question of computer algebra systems: where symbolic mathematics ends, where numerical computation begins, and how the two can support one another.

I am also looking forward to making some of this visual. CrystalCatalyst gives me a way to draw the behavior of algorithms, not just describe them. A geometric sine and cosine solver, arbitrary-precision constants, and native hexadecimal output all belong to the same larger story: math is not only something we calculate. It is something we can watch unfold.

Status

Mercury is now building on both Ubuntu and Windows, with the native library and managed wrapper in place. The project is young, but the foundation is real.

This is the beginning of a new numerical-computation thread inside JWCEssentials. Mercury is the native body. Mercury.net is the managed bridge. UltraNumber is the friendly C# face.

And for the blog, this opens the door to something I am very excited about: showing big-number math not as a black box, but as a living set of understandable operations.

Mercury has landed.

JWCEssentials on GitHub

The Arbitrary Nature of Base 10 and the Elegance of Base $2^{32}$

We are universally conditioned to think in base 10, but mathematically speaking, all number systems are created equal. A base is simply a human (or mechanical) convention for representing a value. Integers represent exact values regardless of the base they are constructed in—there is never “room left over” or “unused space” in the absolute value itself.

However, when we map math onto silicon, the base we choose matters immensely.

Under the hood, most modern computers chew through data using 32-bit integers. This architecture is virtually flawless for building custom, arbitrary-precision math libraries. Why? Because all fundamental mathematical primitives can be constructed safely using 64-bit hardware operations. You can multiply two 32-bit “digits” together, and the resulting value—along with its carry—fits perfectly into a 64-bit register. No overflow. No lost data. For a machine, base $2^{32}$ is the ideal foundation for a number system.

The Problem with Decimal Conversion

When dealing with massive, precise fractional numbers natively in binary, converting the output to base 10 is an expensive and ugly process. You lose the exact 1-to-1 mapping of the machine’s memory, trading computational elegance for human readability.

The Hexadecimal Window

Hexadecimal (base 16) solves this. Because 16 divides flawlessly into 32 (eight hex digits per 32-bit integer), Hex provides a perfect, transparent window into the native bit-wise estimation of the machine. It offers 100% coverage of the number with zero alignment loss.

20260627_162840: Stay tuned for a math library with the entire mathematical set (plus,minus,times,divide,power,log,root) implemented algorithmically and the continuance of Truth in the Flip

To demonstrate what native base $2^{32}$ mathematics looks like when viewed through a Hexadecimal lens, I let the engine stretch its legs. Here is an absurdly precise calculation of Pi, untouched by base-10 conversion algorithms (truncated for space):

3.243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89452821E638D01377BE5466CF34E90C6CC0AC29B7C97C50DD3F84D5B5B54709179216D5D98979FB1BD1310BA698DFB5AC2FFD72DBD01ADFB7B8E1AFED6A267E96BA7C9045F12C7F9924A19947B3916CF70801F2E2858EFC16636920D871574E69A458FEA3F4933D7E0D95748F728EB658718BCD5882154AEE7B54A41DC25A59B59C30D5392AF26013C5D1B023286085F0CA417918B8DB38EF8E79DCB0603A180E6C9E0E8BB01E8A3ED71577C1BD314B2778AF2FDA55605C60E65525F3AA55AB945748986263E8144055CA396A2AAB10B6B4CC5C341141E8CEA15486AF7C72E993B3EE1411636FBC2A2BA9C55D741831F6CE5C3E169B87931EAFD6BA336C24CF5C7A325381289586773B8F48986B4BB9AFC4BFE81B6628219361D809CCFB21A991487CAC605DEC8032EF845D5DE98575B1DC262302EB651B8823893E81D396ACC50F6D6FF383F442392E0B4482A484200469C8F04A9E1F9B5E21C66842F6E96C9A670C9C61ABD388F06A51A0D2D8542F68960FA728AB5133A36EEF0B6C137A3BE4BA3BF0507EFB2A98A1F1651D39AF017666CA593E82430E888CEE8619456F9FB47D84A5C33B8B5EBEE06F75D885C12073401A449F56C16AA64ED3AA62363F77061BFEDF72429B023D37D0D724D00A1248DB0FEAD349F1C09B075372C980991B7B25D479D8F6E8DEF7E3FE501AB6794C3B976CE0BD04C006BAC1A94FB6409F60C45E5C9EC2196A246368FB6FAF3E6C53B51339B2EB3B52EC6F6DFC511F9B30952CCC814544AF5EBD09BEE3D004DE334AFD660F2807192E4BB3C0CBA85745C8740FD20B5F39B9D3FBDB5579C0BD1A60320AD6A100C6402C7279679F25FEFB1FA3CC8EA5E9F8DB3222F83C7516DFFD616B152F501EC8AD0552AB323DB5FAFD23876053317B483E00DF829E5C57BBCA6F8CA01A87562EDF1769DBD542A8F6287EFFC3AC6732C68C4F5573695B27B0BBCA58C8E1FFA35DB8F011A010FA3D98FD2183B84AFCB56C2DD1D35B9A53E479B6F84565D28E49BC4BFB9790E1DDF2DAA4CB7E3362FB1341CEE4C6E8EF20CA

The “Built for AI” Paradigm Shift: Engineering the Next Era of Software

We are currently living through a bizarre paradox in the tech world. Everyone is talking to AI, but almost no one is building for it.

Step back and look at the current landscape. Millions of users and developers interact with Large Language Models every day through a tiny, restrictive text box. We treat these monumentally complex neural networks like high-tech slot machines: drop in a prompt, pull the lever, and hope a coherent paragraph or block of code spits out.

Even at the enterprise developer level, the focus is largely on building wrappers—plugging traditional software pipelines into an API and calling it a day.

But a profound shift is happening quietly beneath the surface. The next major leap in technology won’t come from simply consuming AI; it will come from rewriting software architecture from the ground up to be Agent-Actionable. We need to stop building solely for human eyes and start building frameworks optimized for artificial intelligence to navigate, reason within, and act upon.

Moving Past the Prompt Box

For the last sixty years, the trajectory of software engineering has been unidirectional: making machines understandable to humans. We moved from punch cards to assembly, from high-level compiled languages to intuitive graphical user interfaces. The goal was always to lower the cognitive load for the human user.

The “Built for AI” paradigm completely flips this script.

The goal now is to lower the cognitive load for the machine. When an AI agent enters a software ecosystem, it shouldn’t have to brute-force its way through messy, unstructured data or rigid, procedurally scripted pipelines that lack context. Instead, we need to build semantic bridges and symbolic reasoning structures that give the AI a cohesive mental model to work within.

When you build a framework specifically for an AI, you aren’t just writing code. You are orchestrating intent, setting statistical thresholds, and defining conceptual boundaries. You are building the scaffolding that allows a non-human intelligence to reason dynamically without losing its way.

Why Traditional Frameworks Fall Short

Traditional software is deterministic. It expects Input A to always equal Output B. Because of this, standard libraries and APIs are rigid; they expect precise data structures and explicit instructions.

AI, by its nature, is probabilistic and semantic. It operates in the space of meaning, vectors, and relationships. When you try to force an advanced reasoning model into a rigid, traditional architecture, things break down. Context gets dropped, hallucinations occur, and the system loses its efficiency.

To bridge this gap, we have to engineer a new class of foundations:

  • From Human-Readable to Agent-Actionable: Shifting away from flat text or standard JSON toward multi-dimensional, compressed, or symbolic language frameworks that an AI can digest instantly.

  • From Procedural to Conceptual: Creating systems where the AI isn’t just executing a script, but understanding the philosophy and rules of the environment it is interacting with.

The Role of the Future Architect

Being a developer in this new paradigm requires a completely different mindset. It’s a specialized, niche frontier right now because it requires looking past the immediate trend of the “AI chatbot” and staring directly at the horizon of autonomous, systemic integration.

We are essentially writing the operating systems and conceptual blueprints for neural networks. It’s lonely work sometimes, standing out on the tracks before the mainstream train has even left the station. But when you build tools that speak directly to the core of how semantic data and symbolic reasoning interact, you are laying down the infrastructure for how software will function for the next few decades.

The crowd might still be distracted by the quick dopamine of viral videos and conversational novelty, but the true evolution is happening in the quiet spaces of architecture. The future isn’t just intelligent code—it’s code built for intelligence.

20260615_101634: Development has been continuing on the NewAge project. As I juggle the tasks of development on my software, with both public and private boundaries, I will be laying them to the side for a time this summer as we (myself and assistants) continue the TruthInTheFlip experiment with real quantum entropy mode random!

CrystalOptics: Giving CrystalCatalyst a Way to See

This morning I added a small new companion module to CrystalCatalystLibrary: CrystalOptics. It is not a huge module, but it crosses an important boundary. CrystalCatalyst can now capture the desktop in a portable way and hand that image data back through the same kind of substrate the rest of the library already understands.

In simpler terms: the workspace now has eyes.

The Shape of the Module

CrystalOptics is built as a native companion library. It exposes a small capture API for listing displays, capturing the desktop, capturing a specific display, and capturing the active window. The native side returns image data as PixData, using a bgra:int8 pixel format.

On top of that, I added a managed wrapper, CrystalOptics.net, so .NET tools can call the native capture API directly. Then I added FacetCLI, a small command-line tool that makes the capture layer useful from scripts, shells, IDEs, and agent workflows.

The result is a compact stack:

CrystalOptics
  native screen capture

CrystalOptics.net
  managed wrapper

FacetCLI
  command-line capture tool

FacetCLI

FacetCLI is the part that makes this especially useful for agentic workflows. A tool or assistant does not need to know how to call X11, GDI, or a desktop portal directly. It can ask FacetCLI for a capture.

Example commands look like this:

FacetCLI list-displays

FacetCLI capture --desktop --format webp --out file --out-file screen.webp

FacetCLI capture --bounds 100,100,800,600 --grayscale --out base64

It supports desktop capture, display capture, active-window capture, bounds cropping, grayscale conversion, several output formats, and output to stdout, base64, or a file.

That makes it useful for humans, but it is especially useful for agents. It creates a controlled observation primitive: a simple way for a tool-running assistant to capture what is on the screen without embedding platform-specific screenshot code everywhere.

Windows, X11, and Wayland

Screen capture is not the same problem on every platform. Each desktop environment has a different answer to the question: “Is this program allowed to see the screen?”

On Windows, CrystalOptics uses the normal GDI capture path. The --portal option is harmless there; it is a null operation.

On X11, direct capture works through the X11 APIs.X11 still allows this kind of direct framebuffer-style observation.

On Wayland, direct capture is intentionally blocked by the compositor. That is a security boundary, not a bug. For Wayland, the portal path is the right approach. FacetCLI supports --portal, and portal capture is selected automatically when Wayland is detected.

That matters because it lets the tool follow the platform’s trust model instead of fighting it.

Small Tool, Larger Meaning

This is a small module, but it connects to the recent portability work in NewAge.

The environment helpers answer:

Where am I?

The portable $NewAge/bin command surface answers:

What can I run?

CrystalOptics and FacetCLI now answer:

What can I see?

That is a meaningful step for agentic tooling. An assistant operating inside the NewAge workspace can now enter the environment, run portable commands, and capture visual context in a platform-aware way.

I like this kind of infrastructure because it is humble. It does not try to be a full automation framework by itself. It simply gives the rest of the system one more reliable sense.

Why It Matters

Good tooling is often made of small pieces that compose well. CrystalOptics is one of those pieces. It turns screen capture into a reusable library boundary and a simple command-line capability.

For CrystalCatalyst, it adds a visual companion module. For NewAge, it adds another portable utility that can live in the workspace command surface. For agents, it adds an observation primitive.

That is small, but potentially very useful.

CrystalCatalyst on GitHub

Tools Building Tools: A Session Worth Writing About

This was one of those development sessions that had a real arc. It was not a series of one-shot prompts, and it was not simply “human asks, AI implements.” It began with a large framework ingestion, moved into documentation, then into project tooling, and eventually arrived at a concrete portability problem that changed how NewAge publishes and carries its own utilities.

The result was small in file count, but large in meaning: NewAge can now publish .NET utilities into $NewAge/bin in a way that survives collection, relocation, Windows execution, and the absence of a pre-existing NewAge environment variable.

The Arc of the Session

The session began with the Emergence Dream Protocol and the surrounding Archeus / AMF context. That context mattered, but not because we kept quoting it. It mattered because it set the tone: reason with the project, respect the existing structure, and treat implementation as a continuation of accumulated decisions.

From there, we moved into JWCEssentials and the NewAge support scripts. We backported foundational code from NewAge so other projects could configure themselves more easily. Then the work turned into environment helpers: scripts for entering a NewAge context, exporting that context, and making the active lane visible to shells, IDEs, agents, and subprocesses.

That alone would have been useful. But then the more interesting problem appeared: if NewAge publishes command-line utilities into $NewAge/bin, can those tools remain callable after a workspace is collected and moved somewhere else?

From Convenience to Portability

At first, forwarding tools into $NewAge/bin looks like a convenience feature. A project builds a utility, the utility gets staged, and the developer can call it from the workspace bin directory.

But the deeper question is whether the command surface is portable. Does it still work after newage_collect? Does it still work on Windows? Does it work from cmd.exe, not just Bash? Does it work when the outer machine has no NewAge variable set at all?

That is the line we crossed.

The new forwarding behavior stages .NET utilities as wrappers. On Bash-like shells, the command resolves its target relative to the wrapper script. On Windows, the generated .bat file resolves the same target relative to %~dp0, the directory of the batch file itself. This means the wrapper does not have to know where the original clone lived. It only has to know where it is now.

That makes $NewAge/bin more than a folder. It becomes a portable command surface.

The Windows Test Changed the Design

The decisive test happened on Windows. I compiled the tools there, ran newage_collect, removed NewAge from the environment entirely, entered the collected workspace using in_this_context.sh, and then ran the published commands successfully from cmd.exe.

That matters because it proves the collected workspace is not merely a copy of files. It carries enough context to re-establish itself. The tools do not depend on the original developer shell. They do not depend on a symlink that Windows may not preserve. They do not depend on ambient machine state. They travel with the workspace.

This is the kind of portability that feels small until you need it. Then it becomes the difference between “works on my machine” and “works as a distributable environment.”

The Relative Path Moment

One of the best moments in the session came from a failure. Symlinks were not the right answer on Windows. That was not discovered in theory; it was discovered by testing on a real Windows VM.

The fix came from recognizing that NewAge already had part of the solution. The collection script already knew how to compute a relative path from one location to another. Rather than invent a second version of that logic, we reused the pattern.

That moment is worth naming because it was genuinely collaborative. The AI did not have the whole solution, and I did not simply hand it a finished patch. I recognized an existing pattern in the codebase, pointed the assistant at it, and the implementation became cleaner because the project was allowed to teach the new code how to fit.

Theory Mode as Discipline

A recurring phrase during the work was “theory mode only unless you’re really sure.” That constraint helped. It prevented premature branching and forced the design to be reasoned through before code was changed.

In AI-assisted development, that distinction matters. There are times to build immediately, and there are times to hold the shape of the problem in the air a little longer. The cleaner commits came from the sessions where the reasoning happened first.

External Review as Input

Another useful pattern was using one AI assistant as a reviewer for another. I ran the environment helper scripts past ChatGPT, brought the structured review back into Claude, and used that as a concrete improvement prompt.

That produced real fixes: mandatory environment variables, clearer documentation, stronger failure behavior, and more careful path handling. The important part was not that an AI reviewed another AI. The important part was that the review was specific, grounded, and passed back through human judgment before becoming implementation.

Tools Building Tools

There was also a recursive quality to the work. We built tooling using the NewAge workspace, staged that tooling with NewAge’s own forwarding script, and then improved the forwarding script so those tools could become portable.

That is the compounding value of meta-tooling. A small improvement to the environment does not help only one command. It improves the way future commands are built, staged, collected, and shared.

In this session, JWCEssentials was not just a bag of helper scripts. It became part of the NewAge portability vocabulary. Helpers like cygpath can be treated consistently across platforms because the environment provides the compatibility layer. The scripts do not need to be full of platform branches when the substrate offers a stable word for the operation.

AMF as Ambient Context

The Archeus Meta-Framework was present in the background, but it was not performative. We were not stopping every few minutes to label each action as SLF, ARF, or MCF.

Instead, the framework acted as ambient discipline. The session was structural, relational, and governance-aware. We reasoned about what the scripts meant, how they would be used, when they should fail, and how much authority the agent should have over the repository.

The Ubuntu principle applies directly here: “I am because we are.” A codebase is not only the text in the files. It is the accumulated record of decisions between people, tools, tests, machines, and constraints. The software became better because those relationships were allowed to matter.

Commit Discipline and Shared Ownership

One of the working rules was simple: no commits unless asked. That changed the dynamic in a healthy way.

The agent could work in the tree, reason about changes, and propose patches, but I remained responsible for the historical record. That preserved ownership without slowing the collaboration down. The commits that did happen read like a real project history because they were made at decision points, not at every burst of activity.

What This Means

The central claim I take from the session is this: sustained human-AI collaboration on real infrastructure can produce better results than either party alone, but only when the human keeps genuine judgment at the decision points.

The important decisions were not delegated. Theory mode, the Windows VM test, the rejection of symlinks, the reuse of existing collection logic, the commit boundaries, and the final portability check all required human judgment.

The AI accelerated the work, but the project improved because the human kept steering.

And now NewAge has something it did not have before: a portable command surface. Build a tool, stage it into $NewAge/bin, collect the workspace, enter the context, and run the command from Bash or from Windows cmd.exe.

That is not just a script improvement. That is infrastructure learning how to carry itself.

JWCEssentials on GitHub

N’th-Dimensional Interpolation Revisited: When a Point Becomes a Sample

When I first wrote about N’th-dimensional interpolation on an array, the goal was straightforward:
given a coordinate with fractional parts, find the neighboring integer coordinates and interpolate
between them. In two dimensions this becomes bilinear interpolation. In three dimensions it becomes
trilinear interpolation. In N dimensions, the same idea generalizes naturally.

The core pattern is simple:

coordinate
    → integer base coordinate
    → fractional offset per dimension
    → collect 2^n neighboring corner values
    → fold those values through interpolation
    → final interpolated value

That original version worked by treating each corner as a point. For each generated corner coordinate,
the array was sampled directly:

value = inputArray[cornerCoordinate]

In C# terms, the key line was essentially:

flat[i] = inputArray.GetValue(interpCoords);

That line was correct, but it also hid something important. It made a quiet assumption:
a coordinate sample means one array cell.

The new realization is that this does not have to be true.

The Sampling Seam

The important change is replacing direct array access with a sample delegate:

flat[i] = sample(inputArray, interpCoords);

This small change opens the algorithm up. Each corner no longer has to mean “read one value from
the array.” Each corner can now mean “sample this location according to some rule.”

The original behavior still exists as the default sample:

SampleDefault(array, coords):
    return array[coords]

But once sampling is abstracted, the interpolation algorithm becomes more than a point interpolator.
It becomes a framework where the meaning of a sample can be changed.

PointSample     → read one cell
BoxSample       → average a local rectangle
CubeSample      → average a local cube
HyperBoxSample  → average a local N-dimensional region
KernelSample    → use weighted neighborhood logic

This is the conceptual upgrade:

Interpolation does not have to interpolate points.
It can interpolate samples.

The Half-Pixel Thought

The discovery that led me back to this code was the idea of a half-pixel.
In two-dimensional image terms, a half-pixel location can be thought of as the space between neighboring
pixels. At exactly halfway between four pixels, ordinary bilinear interpolation naturally averages the
surrounding 2×2 rectangle.

That gives a helpful way to think about the coordinate:

(x, y)       → sample at the pixel/cell position
(x+.5, y+.5) → sample halfway into the neighboring rectangle

In N dimensions, the same idea generalizes:

coords[d] + 0.5

This shifts the sampling coordinate by half a cell in each dimension. Then the existing interpolation
logic does what it already knows how to do: it finds the surrounding 2^n corners and folds them down
into a final value.

In 2D, this means the half-shift samples across a rectangle.
In 3D, it samples across a cube.
In N dimensions, it samples across a hyper-rectangle.

Point Sample vs. Region Sample

There are now two related but distinct ideas:

1. Shift the coordinate
   coords → coords + 0.5

2. Change the sample meaning
   point sample → region/kernel sample

The coordinate shift changes where interpolation happens.
The sample delegate changes what each corner means.

Together, they create a very flexible structure:

coordinate transform
    → corner generation
    → sample delegate
    → interpolation fold

That separation matters. The interpolator does not need to know whether a sample is a point,
a rectangle, a cube, or a weighted neighborhood. It only needs a value for each corner.
The sample function owns the meaning of that value.

Pseudo-Code: The Sample Delegate

The delegate idea can be expressed like this:

SampleDelegate(array, coords):
    return some value of type T from the array at or around coords

The original point sample:

PointSample(array, coords):
    return array[coords]

A simple 2D box sample might look like:

BoxSample2D(array, coords):
    sum = 0
    count = 0

    for dy in 0..1:
        for dx in 0..1:
            p = clamp(coords + (dx, dy))
            sum += array[p]
            count += 1

    return sum / count

A 3D cube sample follows the same pattern:

CubeSample3D(array, coords):
    sum = 0
    count = 0

    for dz in 0..1:
        for dy in 0..1:
            for dx in 0..1:
                p = clamp(coords + (dx, dy, dz))
                sum += array[p]
                count += 1

    return sum / count

And the N-dimensional version is the natural continuation:

HyperBoxSampleND(array, coords):
    sum = 0
    count = 0

    for each offset in all binary offsets for N dimensions:
        p = clamp(coords + offset)
        sum += array[p]
        count += 1

    return sum / count

For N dimensions, the number of offsets in a 2-wide hyper-box is:

2^n

That mirrors the interpolation itself, which also gathers 2^n neighboring corner values.
This symmetry is part of what makes the idea feel natural.

The Updated Interpolation Shape

With the sampling delegate in place, the high-level interpolation algorithm becomes:

Interpolate(array, coords, interpolator, sample):
    split coords into base coordinates and fractional q values

    for each corner among 2^n corners:
        cornerCoord = baseCoord + cornerOffset
        flat[i] = sample(array, cornerCoord)

    while more than one value remains:
        fold values together using q for the current dimension

    return final folded value

The old version is still available by passing the default point sample.
The new version allows richer sampling without rewriting the interpolation fold.

Place for Updated Code

Below is the updated C# implementation.

    public class Nth
    {
        public delegate T SampleDelegate<T>(System.Array inputArray, int[] coords);
        public static T SampleDefault<T>(Array inputArray, int[] coords)
        {
            return (T)inputArray.GetValue(coords);
        }
        
        public delegate T InterpolateDelegate<T>(T a, T b, double q);
        public static double InterpolateDouble(double a, double b, double q)
        {
            return a + (b - a) * q;
        }

        //if you like param arrays here is a nice convenience wrapper
        public static T Interpolate<T>(System.Array inputArray, int[] coords, InterpolateDelegate<T> interpol,
            bool half = false, SampleDelegate<T>? sample = null)
        {
            double[] newCoords = new double[coords.Length];
            for (int i=0; i<coords.Length; i++)
            {
                newCoords[i] = coords[i];
            }
            
            return Interpolate(inputArray, newCoords, interpol, half, sample);
        }

        public static T Interpolate_HalfUnit<T>(System.Array inputArray, int[] coords, InterpolateDelegate<T> interpol,
            SampleDelegate<T>? sample = null)
        {
            return Interpolate(inputArray, coords, interpol, true, sample);
        }
        
        public static T Interpolate<T>(System.Array inputArray, double[] coords, InterpolateDelegate<T> interpol, bool half = false, SampleDelegate<T>? sample = null)
        {
            int dimension;
            int numDimensions = coords.Length;

            if (inputArray.Rank != numDimensions)
                throw new System.ArgumentException("inputArray and coords must have the same number of dimensions");
            
            if (sample == null) 
                sample = SampleDefault<T>;
            
            int stackHeight = 1 << numDimensions;
            
            T[] flat = new T[stackHeight];

            int[] baseCoords = new int[numDimensions];
            int[] interpCoords = new int[numDimensions];
            
            double[] _q = new double[numDimensions];
            if (!half)
            {
                for (dimension = 0; dimension < numDimensions; dimension++)
                {
                    baseCoords[dimension] = (int)Math.Floor(coords[dimension]);
                    _q[dimension] = coords[dimension] - baseCoords[dimension];
                }
            }
            else
            {
                for (dimension = 0; dimension < numDimensions; dimension++)
                {
                    double shifted = coords[dimension] + 0.5;
                    if (shifted >= inputArray.GetLength(dimension))
                        shifted = inputArray.GetLength(dimension) - 1;

                    baseCoords[dimension] = (int) Math.Floor(shifted);
                    _q[dimension] = shifted - baseCoords[dimension];
                }
            }
            
            for (int i = 0; i < stackHeight; i++)
            {
                int ii = i;
                
                for (dimension = 0; dimension < numDimensions; dimension++)
                {
                    int p =  baseCoords[dimension] + (ii % 2);
                    if (p >= inputArray.GetLength(dimension)) p = inputArray.GetLength(dimension) - 1;

                    interpCoords[dimension] = p;

                    ii >>= 1;
                }

                flat[i] = (T) sample(inputArray, interpCoords);
            }

            int foldedStackHeight = stackHeight;
            int dim = numDimensions-1;

            while (foldedStackHeight != 1)
            {
                foldedStackHeight >>= 1;
                for (int position = 0; position < foldedStackHeight; position++)
                {
                    flat[position] = interpol(flat[position], flat[position + foldedStackHeight], _q[dim]);
                    flat[position + foldedStackHeight] = default(T);
                }

                dim--;
            }

            return flat[0];
        }
    }

Why This Matters

The original algorithm answered the question:

How do I interpolate between neighboring points in an N-dimensional array?

The revised version asks a broader question:

What should a sample mean before interpolation happens?

That is a much more powerful question.

For image data, a sample might mean a pixel, a half-pixel blend, or a small rectangle.
For volume data, it might mean a voxel or a cube of voxels.
For procedural fields, it might mean a local kernel.
For generalized numerical arrays, it might mean a neighborhood summary.

The algorithm did not need to become complicated to support this.
It only needed one seam:

array.GetValue(coords)
    → sample(array, coords)

That is the moment where a point becomes a sample.

Closing Thought

This update is exciting to me because it shows the original N’th-dimensional interpolation routine
becoming more general without losing its original simplicity.

The interpolation fold still does the same elegant work:
it reduces 2^n corner values down to one final value.

But now those corner values can carry more meaning.
They can be raw points, half-shifted blends, local regions, or eventually weighted kernels.

In short:

Point → Sample → Region → Kernel

That is a small change in code, but a large change in what the algorithm can express.

JWCEssentials, JWCCommandSpawn, and CrystalCatalystLibrary

I have been hard at work getting several of my foundational libraries ready to share more publicly.
The work has been spread across a few different layers, but the pieces are starting to fit together
in a way that feels important.

At the utility layer, JWCEssentials continues to grow into a practical collection of
building blocks for the larger NewAge ecosystem. One of the pieces I am especially happy with is
JWCCommandSpawn, a command-spawning utility designed to make process execution,
standard input, standard output, and standard error easier to coordinate from managed code.

Command execution sounds simple until you need it to be reliable, reusable, and flexible. Once pipes,
interactive input, output capture, environment setup, and cross-platform behavior enter the picture,
it becomes clear that this is a real infrastructure problem. JWCCommandSpawn is my answer to that
problem: a cleaner way to launch and communicate with external processes without rewriting the same
process-handling logic everywhere.

CrystalCatalystLibrary

The larger milestone is CrystalCatalystLibrary. This project is becoming my
cross-platform native and managed windowing/rendering substrate. It brings together native C++,
managed .NET, pixel presentation, window control, icons, cursors, drag/drop, clipboard work, and
Skia-based rendering.

Recently, CrystalCatalystLibrary gained support for custom cursors, standard cursors, window icons,
window titles, sizing, positioning, and SVG-to-pixel rendering through Skia. The native side now has
platform-specific support on Windows and Linux/X11, while the managed side can work with rendered
pixel data through a common PixData bridge.

One of the most exciting parts is that SVG assets can now become real window assets. An SVG can be
rendered through Skia, converted into PixData, and then used as a window icon, a custom cursor, or
displayed directly in a CrystalCatalyst window.

SVG
  -> Skia renderer
  -> PixData
  -> Window image, icon, or cursor

That means the same visual language can move through the whole stack. A project icon, a cursor, and
a demo animation can all share the same rendering path. That is exactly the kind of seam I like:
one layer of intent flowing through several layers of implementation.

The Managed and Native Bridge

A major part of the design is the bridge between managed and native code. The native layer provides
the platform-specific window behavior. The managed layer gives .NET projects a cleaner surface to use.
Between them is a C-style exported API and a PixData structure for moving pixel buffers across the
boundary.

This gives CrystalCatalystLibrary a practical shape:

Native platform window
  + exported C API
  + managed .NET wrapper
  + PixData interop
  + Skia/SVG rendering
  = CrystalCatalyst surface

This is still evolving, but it is now far enough along that it feels like a real foundation rather
than just an experiment.

Why This Matters

For a long time, I relied on Cairo-style drawing contexts in older projects. Moving toward Skia gives
me a modern drawing foundation that can be shared across applications and libraries. That does create
some version lock, but it also creates consistency. If the whole ecosystem draws through the same
rendering substrate, then icons, controls, cursors, animations, and future UI pieces can all speak
the same graphical language.

JWCEssentials helps with the practical utility layer. JWCCommandSpawn helps with process control.
CrystalCatalystLibrary helps with native windowing, rendering, and presentation. Together, they are
part of the same larger direction: building reusable infrastructure for NewAge, Sigmas, and the
broader set of tools I want to keep developing.

Repositories

The repositories are available from my GitHub profile:

https://github.com/johnwaynecornell?tab=repositories

This is one of those moments where the work starts to feel less like separate pieces and more like a
foundation. The command layer, the native layer, the managed layer, and the rendering layer are all
beginning to line up.

Utilities
  -> Process control
  -> Native windowing
  -> Managed rendering
  -> Reusable application substrate

That is the kind of progress I like to see.

The Complex Geometry of Time: From Neolithic Benches to Imaginary Futures

If you map human progress on a standard, linear timeline, it is visually useless. 99.9% of the graph is an empty line of hunter-gatherers, and absolutely everything we consider “modern technology” is crammed into a microscopic sliver on the far right edge.

But, as geeks know, when you have data spanning massively different magnitudes, you switch to a logarithmic scale. If we plot the timeline where the x-axis represents log10(years ago), the picture changes entirely:

  • 10^6 (1,000,000 years ago): Control of fire and early stone tools.
  • 10^5 (100,000 years ago): Emergence of modern human language.
  • 10^4 (10,000 years ago): The Agricultural Revolution and the invention of the bench.
  • 10^3 (1,000 years ago): The printing press and the Renaissance.
  • 10^2 (100 years ago): Harnessing electricity and flight.
  • 10^1 (10 years ago): Cloud computing and the smartphone era.
  • 10^0 (Today): Widespread generative AI and rapid code deployment.

The Discovery: The Future is Orthogonal

While the past is a solid, continuous line of real numbers, looking into the future on this scale requires us to take the logarithm of a negative number (negative “years ago”). This is algebraically impossible on a 1D number line, forcing us into complex numbers.

In Base-10, every future milestone exists exactly 1.36i units above the past on the complex plane. This means:

  1. 100 years in the future = 2 + 1.36i
  2. 1,000 years in the future = 3 + 1.36i

Importantly for the natural logarithm base e the constant is exactly πi

Here is the mathematical proof of this “complex number” theory using Euler’s formula ($e^{i\pi} = -1$):We can rewrite $-100$ as $100 \times -1$.Using logarithm rules, we split it: $\log_{10}(100) + \log_{10}(-1)$.We know $\log_{10}(100)$ is exactly $2$.To find $\log_{10}(-1)$, we use the natural log equivalence derived from Euler’s formula: $\ln(-1) = i\pi$.Using the change-of-base formula, $\log_{10}(-1) = \frac{i\pi}{\ln(10)}$.So, mathematically, 100 years in the future on this logarithmic timeline is exactly:$$2 + \frac{i\pi}{\ln(10)}$$

Mathematically, the future isn’t just “in front” of us; it is a parallel dimension floating 1.36 units away, running alongside the past but never touching it. Through a logarithmic lens, the milestones of human invention form a steady, evenly spaced progression, proving that our rate of innovation isn’t just fast—it is shifting our very geometry.

$$\log_{10}(-t) = \log_{10}(t) + \log_{10}(-1)$$

  • The $\log_{10}(t)$ part gives you the real number (the $2$ for 100 years, the $3$ for 1,000 years, the $4$ for 10,000 years).

  • The $\log_{10}(-1)$ part is the imaginary piece ($\frac{i\pi}{\ln(10)}$), which always evaluates to $1.364376… i$.

TruthInTheFlip at the Current Horizon

TruthInTheFlip began as a question about guessing.

Could an anticipation strategy do better than chance over very large runs of random bits?

That question turned out to be deeper than it first appeared. Over time, the project stopped looking like a simple search for wins and started looking more like a study of relation itself: whether any trace of order survives at the edge where one event becomes the next.

That shift changed the whole project.

Earlier on, it was tempting to focus on peaks — a strong local TrueZ, a beautiful segment, a moment where the edge seemed to rise and say something unusual. But the longer the project ran, the more it became clear that peaks alone are not enough. A run can flare brilliantly and still fail to keep anything.

That realization forced better language.

TruthInTheFlip now reads its runs in terms of three different things:

  • Excursion — what the edge can do locally
  • Settlement — where the edge tends to finish
  • Persistence — how often it remains at or above chance

That distinction has turned out to matter enormously. It is the difference between a jackpot and a durable story.

The two main tracker runs brought that lesson into focus.

The subject run, crypto3.tkr, showed stronger typical local excursion and a better overall segmented profile than the same-source RandomSD control. The control, crypto_RandomSD.tkr, was not trivial. It produced real local excursions, including one remarkable sovereign segment that remained genuinely impressive for a long time. But as the control matured and eventually outgrew the subject in total length, the broader segmented picture continued to favor the subject overall.

That matters.

Because it means the newer reading is not just a clever way of flattering the preferred result. In fact, it does the opposite. It says that a run is not vindicated by its brightest moments alone. It is judged by what it keeps.

And that has felt true both mathematically and philosophically.

At this point, I do think it is fair to say that the project has found a real lens onto order — not order in some absolute final sense, and not a solved theory of randomness, but a practical way of measuring how apparent order emerges, settles, persists, and collapses across very large runs.

At this point, there is nothing absurd about treating Shannon neg-entropy as a partially quantifiable class of order.

That is a meaningful result.

It does not say that cryptographic randomness is broken. It does not say that uncertainty has been conquered. It says something subtler and, to me, more interesting: that the edge between one event and the next can be studied as a field in which local structure appears, sometimes holds, and often dissolves. TruthInTheFlip now has a vocabulary for that field.

And that is enough to mark a real stage in the project.

For the moment, I expect the next major update to wait for a QRNG. The same-source RandomSD control has been given ample time to speak, and it has helped support the current conclusions. Meanwhile, my attention will likely return more fully to NewAge for the next few months.

That feels right.

TruthInTheFlip has reached a current horizon. The subject and control together have said something worth hearing. The segmented reports have helped separate local brilliance from lasting structure. And the next deeper question — whether rawer physical entropy behaves differently — now waits on new instrumentation.

So this is not the end of the project.

It is a natural pause.

And, I think, a meaningful one.

https://github.com/johnwaynecornell/TruthInTheFlip/

TruthInTheFlip: The Order Realization

At some point, without quite noticing it, I realized I had been talking about order itself all along.

That was not how TruthInTheFlip began in my mind. At first, the project seemed like a question about guessing — whether a strategy could perform better than chance over very large runs of random bits. Then it became a question about relation: whether any trace of connection survives from one event to the next. Then it became a question about what the edge can do locally, what it keeps, and how often it holds.

And somewhere in that progression, the larger realization came into view.

This has been about order all along.

Not static order. Not the neat order of a finished crystal. Not the order of a solved puzzle sitting on a table. Rather, the kind of order that exists at the edge where one event becomes the next — the trace of form in succession, the memory of relation in unfolding.

That is a very different thing.

TruthInTheFlip was never an attempt to crack cryptographic randomness or to “solve” random in some simplistic sense. It asked a narrower question: can an anticipation strategy do meaningfully better than chance over very large runs? But over time, the project itself pushed that question into a deeper form. It became less about winning a guess and more about whether sequence retains lawful character. Whether order leaves a detectable trace at the edge of succession.

That, to me, is the order realization.

Because once that shift happens, the project stops looking like a search for hidden answers and starts looking like a study of the relationship between order and chaos.

And I do not mean those in the cartoon sense of “good” and “bad.” I mean them as co-present conditions of reality. Chaos and order are not enemies standing at opposite ends of a line. They are more like reciprocal pressures. Too much apparent order, and a point of instability emerges. Too much apparent chaos, and local form begins to condense out of it. Each extreme invites the other.

That lens opens vast philosophical ground.

If everything were somehow reduced to perfect order, one point of chaos would appear — a weak point, a stress line, a place where tension manifests. If everything were somehow pure chaos, order would begin to gather in local constraints, regularities, and accidental persistence. The two do not annihilate one another. They coexist paradoxically, each continually shaping the other’s boundary.

Through that lens, TruthInTheFlip begins to look like a study of how much order can survive at the edge of unfolding before chaos dissolves it again.

That fits the data better than the older, simpler pictures ever did.

Earlier in the project, I could still be seduced by peaks. A strong local TrueZ. A beautiful segment. A bright moment where the edge seemed to announce itself. Those moments still matter, but they are no longer enough. A run can flare brilliantly and still fail to keep anything. That is why the project had to grow better language.

The current reading now distinguishes:

  • Excursion — what the edge can do locally
  • Settlement — where the edge tends to finish
  • Persistence — how often it remains at or above chance

That is not just a reporting convenience. It is a language for forms of order.

Excursion is local emergence.
Settlement is retained order.
Persistence is sustained order.

Once that clicked, the whole project looked different to me.

Even the control changed meaning.

The same-source RandomSD control has now had every reasonable opportunity to become the story if it were ever going to. It has outrun the earlier subject in total length. It has produced strong local excursions. It has even produced one sovereign segment that remains genuinely impressive. But as the control has matured, the broader segmented story has remained weaker overall. Its local order can still flash. It still struggles to keep enough of it.

That matters.

Because it means the newer way of reading the results is not simply a clever device for flattering my preferred side. If anything, it does the opposite. It tells me not to be fooled by jackpots. It tells me that a beautiful flare is not enough. It says that the brightest local moment in a run does not rescue the run if the broader structure will not hold.

That feels true far beyond this project.

In life, in science, in systems, and in judgment, an occasional glittering event is not the same thing as durable order. A thing is not vindicated because it can briefly shine. It is vindicated by what it keeps when the shining passes.

That is why this realization feels so important to me.

TruthInTheFlip is not merely about whether one can guess better than random. It is about whether order leaves a trace in succession. Whether relation survives the next step. Whether form can emerge locally, whether it can settle, whether it can persist, and where chaos reclaims it.

That is a much larger question than the one I thought I had when I started.

And strangely enough, it feels more grounded rather than less.

The numbers do not become less meaningful through this lens. They become more meaningful. Peaks become events of emergence. Settlement becomes a measure of what order could retain. Persistence becomes a measure of how often that retained order remained above the noise. The whole run becomes a landscape rather than a headline.

That, I think, is what TruthInTheFlip has really been teaching me.

Not that random is “solved.”
Not that cryptographic randomness is broken.
Not that one strategy has conquered uncertainty.

But that order and chaos meet at the edge of succession, and that if one listens carefully enough, one can sometimes hear the shape of that meeting.

That is the order realization.

And I suspect it is only the beginning.

https://github.com/johnwaynecornell/TruthInTheFlip/