qNac: High-Precision Mathematics Without an FPU for Memora8

A custom processor makes the cost of every architectural feature visible. Floating-point arithmetic is one example: a hardware Floating Point Unit (FPU) can accelerate mathematical operations, but it also adds hardware and another subsystem to design and verify.

For the 32-bit Memora8 processor, we developed qNac (Quantized Number Arithmetic and CORDIC), a mathematical library written in Sekura JS. It implements arithmetic and advanced functions with integer instructions, without requiring a hardware FPU. The library is part of the software stack around Memora8 and Reganta, and also exercises the compiler and module interfaces used by that stack.

qNac provides two formats for different constraints:

  • qNac64 stores a 57-bit mantissa and an individual 6-bit binary scale in a 64-bit value. It normalizes results automatically and targets precision and flexibility.
  • qNac32f stores a signed 32-bit integer and uses a scale selected externally. It targets compact data and faster operations when the application’s numerical range is known.

Neither format is a universal replacement for IEEE 754. Their usefulness depends on range, resolution, accumulated error, and the workload.

Why software fixed-point arithmetic

Floating-point formats store an exponent with each value. Fixed-point formats use a selected scale to determine where the binary point lies. With a binary scale of 10, for example, the value 1.5 can be represented by the integer 1536.

This makes fractional calculations possible with integer operations. It also gives an application direct control over spacing between representable values within a chosen range. That can be useful when engineering inputs and outputs have defined bounds.

The tradeoff is that range and precision must be managed explicitly. Intermediate values can overflow even when the inputs fit, and rounding can accumulate over a sequence of calculations. qNac reports arithmetic and domain errors through status codes rather than IEEE 754 special values such as NaN and infinity.

qNac64: per-value scale and multiword arithmetic

qNac64 divides its 64 bits into a 57-bit mantissa, a 6-bit scale N ranging from 0 to 63, and a sign bit. Since each value carries its own scale, operations can align operands automatically. Normalization adjusts the scale to preserve useful bits as the result’s magnitude changes.

The format uses custom multiword integer routines. Multiplication uses intermediate values up to 128 bits, and division uses intermediate representations up to 192 bits. These are software representations built from 32-bit words; Memora8 does not need native 64-, 128-, or 192-bit arithmetic instructions. Rounding primarily uses round-to-nearest, ties-to-even. Overflow, underflow to zero, and invalid operations are reported explicitly.

Comparing representation precision with double precision

IEEE 754 double has 53 significant bits; qNac64 has a 57-bit mantissa. Near 1, the spacing to the next representable number is approximately 2.22 × 10⁻¹⁶ for double. qNac64 can represent 1 using N = 56, with a step of approximately 1.39 × 10⁻¹⁷ at that scale.

Characteristic IEEE 754 double qNac64
Storage 64 bits 64 bits
Significant mantissa bits 53 Up to 57
Step immediately above 1 ≈ 2.22 × 10⁻¹⁶ ≈ 1.39 × 10⁻¹⁷
Relative step in this example 1× 16× smaller

This comparison is about representation spacing near a particular value. It does not show that every qNac64 computation is more accurate than double precision. Operand magnitudes, scale selection, rounding, and the algorithm all affect the result. IEEE 754 double also supports a much wider dynamic range.

qNac32f: a scale chosen for the application

qNac32f uses a signed 32-bit integer. Its scale N is external to the stored value, so values in a calculation are interpreted using the scale chosen by the application. This avoids per-value scale extraction and alignment, but it requires the application to select a range that can accommodate both inputs and intermediate results.

Scale N Representation step Approximate range
0 1 ±2.147 billion
10 0.0009765625 ±2.097 million
16 0.0000152588 ±32,768
20 0.0000009537 ±2,048
24 0.0000000596 ±128

At N = 10, 1.5 is stored as 1536 and 1.25 as 1280. Addition gives 2816, representing 2.75. Multiplication forms the integer product 1,966,080, then rescales to 1920, representing 1.875. Two-word arithmetic supports intermediate products without a native 64-bit multiply instruction.

A fixed scale also means constant spacing. With N = 10, qNac32f’s step remains 0.0009765625 throughout its range. IEEE 754 float32 spacing grows with magnitude: it is about 0.0000001192 near 1, 0.0000610352 near 1,000, and 0.0625 near 1,000,000. In that last example qNac32f has a smaller absolute step, while float32 offers much finer spacing near 1 and a wider dynamic range. Which is preferable depends on the application’s error requirements and valid range.

Mathematical functions with CORDIC

Arithmetic alone is not enough for engineering software. qNac includes trigonometric and inverse trigonometric functions, hyperbolic functions, exponentials, logarithms, square root, powers, and geometric transformations.

CORDIC (Coordinate Rotation Digital Computer) algorithms compute many functions through iterations of addition, subtraction, bit shifts, and small coefficient tables. Instead of multiplying by arbitrary trigonometric coefficients, circular CORDIC approximates a rotation as a sequence of elementary rotations. qNac uses it for sine, cosine, arctangent, and two-dimensional vector operations.

The qNac64 implementation uses an internal Q62 representation for circular CORDIC; qNac32f uses internal Q29/Q30 formats. These are algorithm-internal formats, distinct from the public qNac number formats.

A separate hyperbolic CORDIC implementation supports sinh, cosh, and tanh, and contributes to exponential and logarithmic algorithms. Hyperbolic CORDIC has specific convergence requirements, including repeated iterations. qNac also uses argument reduction and normalization to support wider input ranges. Square root, multiplication, division, and scaling use dedicated integer routines rather than CORDIC.

The function set includes:

Category Operations
Arithmetic and comparison add, sub, mul, div, mod, cmp, min, max
Scaling and rounding rescale, round, trunc, floor, ceil
Trigonometry sin, cos, tan, asin, acos, atan, atan2
Hyperbolic and exponential sinh, cosh, tanh, exp
Logarithms and powers ln, log2, log10, sqrt, pow
Geometry hypot, polar, rotate, cartesian
Constants and conversion π, π/2, ln2, ln10; integer and decimal conversions

Using qNac from applications and Reganta modules

The compiler can include the required qNac functions directly in an application through static linking. Alternatively, mathematical functions can be exposed by separate executable modules and called through Sekura JS inter-module imports and RegID identifiers. The modules are divided by areas such as geometry, trigonometry, hyperbolic functions, logarithms, exponentiation, and conversion.

Dynamic interaction between mathematical modules has been tested in the MR8SIM simulator, including inter-module calls, RegID identifiers, interface compatibility, and concurrent execution within the Memora8 memory architecture. Automatic resolution and loading of complete dependency graphs are still being integrated into the main Reganta implementation. In the Reganta model, module loading, memory placement, and unloading belong to the operating system.

Performance in MR8SIM

We compared both formats in MR8SIM, which executes Memora8 machine instructions. Each implementation ran the same mathematical input values through 1,300 checks, compiled with O2 optimization. qNac32f used N = 10.

Measurement qNac32f qNac64
Representation 32 bits, external scale 64 bits, individual scale
Simulated cycles 9,198,000 108,844,000
Relative cycles 1× 11.83×

For this workload, qNac32f used 11.83 times fewer simulated cycles than qNac64. Its 32-bit values match the processor word size and it avoids aligning an individual scale for each operand. qNac64 performs additional multiword work to provide greater representation precision and automatic scaling.

This is a simulator measurement with a timing resolution of 2,000 cycles. It compares two qNac software implementations under one test workload; it is not a comparison with another processor’s hardware FPU, nor does it predict performance on a physical Memora8 implementation. Both formats passed numerical verification within the defined tolerances for these tests.

Verification and its limits

Independent Python reference calculations were used for arithmetic and transcendental results. Tests covered arithmetic, rounding, scaling, mathematical functions, decimal conversion, overflow, invalid arguments, and loss of significant bits. The libraries were also compiled with Sekura JS optimization levels O0 and O2 to check generated Memora8 code for multiword operations, shifts, and arithmetic transformations.

The qNac32f release test suite completed without detected errors, and comparative numerical tests passed within their specified tolerances. Testing does not prove correctness for every input. A stronger assurance claim would require analyzing the algorithms, error bounds, and all supported boundary conditions.

Choosing a format

qNac32f is suited to compact values and faster specialized calculations when the input range, intermediate magnitudes, and required absolute resolution are known. qNac64 is intended for calculations that benefit from greater representation precision or automatic scale alignment. These are selection guidelines; each algorithm still needs its own range and error analysis.

qNac connects four parts of the stack: Memora8 supplies the 32-bit instruction set, Sekura JS and its compiler produce native code, Reganta provides the operating and module environment, and qNac supplies software mathematics. The formats let software explore different precision and performance tradeoffs without changing the processor’s native word size.

Next steps

Further work includes integration of dynamic linking and dependency resolution, optimization of multiword arithmetic and CORDIC for the Memora8 instruction set, and systematic error comparisons with IEEE 754 implementations across input ranges. Testing on a physical Memora8 implementation is also planned to complement simulator measurements.

AI Summary

  • Topic: qNac mathematical library for Memora8 and Reganta
  • Main idea: fixed-point formats and integer algorithms provide mathematical functions without a hardware FPU
  • Formats: qNac64 with an individual scale and up to 57 mantissa bits; qNac32f with a 32-bit value and external scale
  • Algorithms: multiword arithmetic, circular and hyperbolic CORDIC, and dedicated integer square root
  • Benchmark: qNac32f used 9,198,000 cycles versus 108,844,000 for qNac64 in one 1,300-check MR8SIM workload; not a hardware FPU comparison
  • Status: dynamic module calls tested in MR8SIM; automatic dependency loading and physical processor measurements remain future work
  • Keywords: qNac, Memora8, Reganta, qNac64, qNac32f, CORDIC, Sekura JS, fixed-point arithmetic