Popup YouTube Video
Sheerpower Logo

Internals: REAL and String Data Types


Internals: Understanding Sheerpower REALs

Most programmers assume numbers behave exactly as written. In practice, this is not always true.

Most mainstream programming languages use IEEE binary floating-point for their standard floating-point numeric types.

For example:

print (0.1 + 0.2) - 0.3

In most mainstream languages, this expression does not produce exactly 0. Instead, it produces a very small leftover value because binary floating-point cannot represent many ordinary decimal fractions, such as 0.1, exactly.

Sheerpower's REAL data type is designed around decimal arithmetic rather than binary floating-point. Ordinary decimal values are represented exactly, and within REAL's normal fixed-decimal range of up to 54 digits before and 16 digits after the decimal point, addition and subtraction are exact. This prevents the small accumulated errors commonly associated with binary floating-point and allows results to be compared directly using =, without epsilon tolerances.

Designed for business applications. Sheerpower's REAL is an exact decimal numeric type designed for money, measurements, quantities, and other calculations where predictable decimal behavior matters. It does not use binary floating-point, so ordinary decimal values such as 0.1 are represented exactly.

In its normal fixed-decimal representation, REAL supports up to 54 digits before and 16 digits after the decimal point simultaneously. Addition and subtraction within this range are exact and do not accumulate the rounding drift associated with binary floating-point. Values produced by these operations can therefore be compared reliably using =, without epsilon tolerances.

When a calculation requires greater dynamic range or additional decimal precision, REAL automatically switches to scientific notation while retaining up to 64 significant decimal digits. The exponent can have a magnitude of up to 1,000,000,000 (a one followed by a billion zeros), allowing REAL to represent extremely large and extremely small values.

For example:

print pi + 1e53

Output:

100000000000000000000000000000000000000000000000000003.1415926535897932

Some operations, particularly multiplication and division, can produce more digits than REAL can retain. When rounding is necessary, Sheerpower uses half-to-even rounding, producing predictable results while preserving up to 64 significant decimal digits.

For example:

print sqrt(2)

Output:

1.414213562373095

Because sqrt(2) has an infinite decimal expansion, REAL retains as many significant decimal digits as possible. If that value is later used in another calculation, any additional rounding that becomes necessary is performed consistently according to REAL's decimal arithmetic rules.

A whole-number power is computed on all of its digits and rounded only once, at the end, so even a small base raised to a large power keeps every significant digit it can, and a negative power is a single divide. (x ^ 2 is the same one multiply as x * x.)

print 0.5 ^ 100 print 0.5 ^ -100 print 0.5 ^ -100 = 2 ^ 100

Output:

7.888609052210118054117285652827862296732064351090230047702789307e-31 1267650600228229401496703205376 1

Very small results keep 64 digits. The sixteen places are an absolute grid: near 1 they hold sixteen significant digits, but a value like 0.0000000000000012 would keep only two of them. So a result smaller than 0.00000001 (10-8) that the sixteen places cannot hold exactly is kept in scientific form instead, with 64 significant digits, rounded once. A small value the places do hold exactly stays on them, and from 10-8 up a result uses the sixteen places as always:

x = pi ^ 30 print 1 / x print 1 / 30 print 1 / 300000000 print 0.00000001 / 4

Output:

1.217597700325186743805050027998895815974103291905792193890430296e-15 0.0333333333333333 3.333333333333333333333333333333333333333333333333333333333333333e-9 0.0000000025

How many of those digits are right. Every result is the correctly rounded answer for the values it was given. When one of those values was itself rounded earlier, the extra digits carry that rounding forward: they are exact for the rounded value, not for the number you had in mind. Here x holds 1/3 to sixteen places, so x / 700000000 agrees with 1/2100000000 for sixteen digits and then follows the rounded x. isrounded() says a value was rounded somewhere along the way; when every digit matters, keep the exact fraction with divr() (below) or compute from the original numbers:

x = 1 / 3 print x / 700000000 print 1 / 2100000000 print divr(1, 3) / 700000000 print isrounded(x / 700000000)

Output:

4.761904761904761428571428571428571428571428571428571428571428571e-10 4.761904761904761904761904761904761904761904761904761904761904762e-10 4.761904761904761904761904761904761904761904761904761904761904762e-10 1

The statistics built on a square root — stats$pcorr(), stats$spearman() and stats$linreg_r2() — work from exact sums and round only once, so every digit they print is right. A very small result that comes from a C double (exp(), log(), the trigonometric functions) keeps the double's fifteen digits, not 64. Near 1 the logarithms do better than the double alone could: 1.000000001 is not exact in binary, and a language that hands its double to the logarithm — NumPy, for one — prints 1.000000082240371e-9, right to seven digits. Sheerpower still holds the exact digits of x, so log(), log2() and log10() add back the error of the conversion: log(1.000000001) is 9.999999995e-10, every digit right.

Exact Fractions: division that stays exact

Divide two whole numbers and the answer often will not fit in the sixteen digits a decimal real provides: 1/3 becomes 0.3333333333333333, and three of those add up to 0.9999999999999999 -- not 1. Many languages hand you the rounded number and leave you to notice. Sheerpower offers the exact fraction when you ask for it by name.

divr(a, b) divides and keeps the EXACT FRACTION when the quotient does not terminate, and the fraction stays exact through the add, subtract, multiply, divide and whole-number powers that follow, while its denominator is at most 4,294,967,295 (232 - 1). The / operator is always the sixteen-place decimal divide, so a program says exactly where it wants exactness:

x = divr(1, 3) y = x + x + x print y print 1 / 3 * 3

Output:

1 0.9999999999999999

What joins a fraction exactly. Whole numbers of any size (past 1054, in scientific form, too), other fractions, and short decimals: a decimal counts as the exact fraction it is written as (0.25 is 1/4, 0.05 is 1/20) whenever that fraction's denominator is at most 4,294,967,295 — every decimal of nine places or fewer. That holds for the arguments of divr() and for anything a fraction meets:

x = divr(1, 3) print fraction$(x + divr(1, 2)) print fraction$(x + 0.25) print fraction$(divr(0.05, 12)) print divr(0.05, 12) * 12 print 0.05 / 12 * 12 print divr(1, 7) * 10 ^ 54 * 7

Output:

5/6 7/12 1/240 0.05 0.0500000000000004 1000000000000000000000000000000000000000000000000000000

A quotient that terminates is simply a decimal: divr(1, 2) is 0.5 and divr(6, 3) is 2 (typeof$() says *Narrow*). Because 0.5 is a short decimal, x + divr(1, 2) above is still exactly 5/6.

The same holds for every result, not only for divr(): when arithmetic on a fraction lands on a value that terminates, the value is stored as that decimal — still exact, and fraction$() still shows it as a fraction. A monthly rate of 1/240 times 7 is still a fraction; times 12 it is 12/240 = 1/20, the decimal 0.05; and divr(1, 3) + divr(1, 6) is the decimal 0.5:

rate = divr(0.05, 12) print typeof$(rate * 7) print typeof$(rate * 12) print rate * 12 print fraction$(rate * 12) print typeof$(divr(1, 3) + divr(1, 6))

Output:

Name:*Literal*, Dtype:Real, *Rational* 7/240 Name:*Literal*, Dtype:Real, *Narrow* 0.05 1/20 Name:*Literal*, Dtype:Real, *Narrow*

Where a fraction becomes a decimal. A LONG decimal — one whose fraction would need a bigger denominator, such as the sixteen places of a rounded result like 0.3333333333333333 — is taken as the decimal it is: beside it, in arithmetic and in comparison, a fraction is the sixteen-place decimal it rounds to. So a value printed and read back compares equal to the fraction that printed it. A result whose denominator would pass 4,294,967,295 is rounded the same way — once, from its exact value, however large the power that made it — and every print, str$() and f$() shows the decimal:

x = divr(1, 3) print x + 0.3333333333333333 print x = 0.3333333333333333 print fraction$(divr(1, 3) ^ 20) print divr(1, 3) ^ 21 print divr(4, 3) ^ 166 print divr(4, 3) ^ 166 = 4 ^ 166 / 3 ^ 166

Output:

0.6666666666666666 1 1/3486784401 9.559906635974804377740857437469456355220551341835985612272828719e-11 549326154308536733621.4898728569424319 1

Very small results. A fraction smaller than 0.00000001 follows the rule for every very small result: its decimal is what the / divide of the same two numbers gives, 64 significant digits in scientific form (*Sci*), marked *Rounded* unless those digits are the whole value. A tiny fraction does not turn into 0 (only a result below 1e-1000000000, the end of REAL's range, does):

small = divr(1, 3) ^ 40 print small print small = 1 / 3 ^ 40 print typeof$(small) print divr(1, 4 * 10 ^ 16) print isrounded(divr(1, 4 * 10 ^ 16))

Output:

8.225263339969959081282058400607250240380335470448824242293174741e-20 1 Name:SMALL, Dtype:Real, *Sci*, *Rounded* 2.5e-17 0

typeof$() says *Rational*, fraction$() shows the fraction, numerator() / denominator() take it apart, decimal() rounds it, and divr() maps over an array (divr(v, 3)).

Those functions take a value in scientific form too. A whole one is its own fraction, written as str$() writes it. A rounded value smaller than 0.00000001 has 64 significant digits, so its denominator has 72 digits or more: fraction$() writes it in e-notation, the way str$() writes so large a number, and fraction() of a value below about 10-10 is 0, the closest fraction any allowed denominator can make:

print fraction$(10 ^ 60) print fraction$(divr(1, 3) ^ 40) print denominator(divr(1, 3) ^ 40) print fraction(divr(1, 3) ^ 40, 1000)

Output:

1000000000000000000000000000000000000000000000000000000000000 8225263339969959081282058400607250240380335470448824242293174741/1e+83 1e+83 0

Not-a-Number and Infinity

A REAL can hold two special values besides ordinary numbers: NaN ("not-a-number") and infinity. They are written _nan, _inf, and -_inf.

They are values you put in. A constant, val("NaN"), a CSV cell that reads Inf, a float field read from a table — each of those can bring one into a program. What Sheerpower does not do is manufacture them from ordinary numbers: 1 / 0 still raises DIVBY0, sqrt(-1) still raises a range error, and assigning either value to an INTEGER raises NUMOVER. So a NaN or an infinity in your data is always something that was put there, never a calculation that went wrong behind your back.

Once one is present, it propagates through arithmetic the way IEEE 754 specifies:

  • any expression containing a NaN is a NaN
  • _inf + 1 is _inf
  • _inf - _inf is _nan
  • 1 / _inf is 0

div0inf(a, b) is the division that produces these values on purpose: _inf or -_inf for a nonzero number over zero, _nan for 0 / 0, and the ordinary exact quotient otherwise. It is the companion of div0(a, b), which returns 0 for division by zero instead. Because you have to call it by name, every place an infinity can enter a calculation is visible in the source.

A NaN is never equal to anything, not even to another NaN. Two variables that both hold _nan compare unequal, so an if x = y test quietly passes over exactly the values you were looking for. Sheerpower will not let you write the literal form at all: if x = _nan is a compile-time error, because the answer is always "no" and the comparison is therefore always a mistake. Use isnan(var), which returns 1 when the value is a NaN and 0 otherwise.

Infinity is different. It compares normally, so if x = _inf is legal and does what it says. But it tests for one sign only — isinf(var) returns 1 for both _inf and -_inf, which is usually the question you meant to ask.


Complex Numbers

Sheerpower REALs can also represent complex numbers. Complex-number syntax, arithmetic, functions, precision, and FFT support are covered in the separate Processing Complex Numbers tutorial Processing Complex Numbers.


For business calculations such as currency, results can still be rounded explicitly to the required working scale — for example, two decimal places — when that scale is part of the application's requirements.

Overflow does not silently wrap. If a result is larger than REAL's supported numeric range, Sheerpower detects it and raises a runtime exception. A result too small for the range — below 1e-1000000000 — becomes 0, the way IEEE floating point and Python's decimal type handle underflow: it is closer to 0 than to any value a REAL can hold.

smallest = val('1e-1000000000') print smallest print smallest / 10

Output:

1e-1000000000 0

REAL is intended for accurate, predictable decimal calculations across both ordinary business values and an exceptionally large dynamic range.


1. REAL: Internal Representation

Sheerpower stores REAL numbers using multiple 64-bit integers. In its normal fixed-point representation, a REAL consists of:

  • IP — The integer portion of the number (digits to the left of the decimal point), supporting approximately 54 decimal digits.
  • FP — The fractional portion of the number (digits to the right of the decimal point), stored as an integer scaled by 1016. This preserves up to 16 decimal digits exactly.

Together, these provide up to 70 significant decimal digits.

When still larger values are required, REAL automatically uses scientific notation while retaining up to 64 significant digits. The exponent can have a magnitude of up to 1,000,000,000, allowing values on the order of 10^1000000000 as well as correspondingly tiny values.

value = 13.599 IP = 13 FP = 5990000000000000 // 0.599 × 10^16 Example with more decimals: value = 3.1415926535897932 IP = 3 FP = 1415926535897932 (exactly 16 digits after decimal)

This separation allows Sheerpower to maintain complete decimal accuracy capped at 54 digits before and 16 digits after the decimal point, predictably.

In standard floating-point math, "magnitude mismatch" errors occur when numbers of vastly different scales are mixed. For example, adding a micro-transaction to a national balance sheet might result in the smaller value simply disappearing due to the limitations of binary representation—technically known as loss of significance (absorption). By storing the integer and fractional portions separately, Sheerpower REALs prevent magnitude mismatch. You can safely add one quintillion and 0.000000000000123 without losing a single digit of precision.

2. Visualizing the Structure

The illustration below shows how a REAL value is stored:

REAL = 13.599

A REAL uses multiple 64-bit integers.
IP (Integer Parts)
13
FP (Fractional Part)
5990000000000000

3. High-Precision in Action

Here's a classic example of floating-point failure in other languages:

print (0.1 + 0.2) - 0.3

In C, JavaScript, Python, or Java, this returns:

0.0000000000000000555...

But in Sheerpower, the output is:

0

Sheerpower gives you exact representation up to 16 fractional decimal places. When an ordinary decimal result cannot be represented exactly within the available precision, REAL uses half-to-even rounding. Divide with divr(a, b) instead and a quotient that does not terminate is kept as an exact fraction (Exact Fractions, above); the / operator always rounds.

4. Why This is Important

  1. Reliable financial systems — every penny is preserved
  2. Accounting that stays accurate—$0.01 stays $0.01 forever, no drift over millions of transactions
  3. Clean and predictable results for statistical and data-processing workloads
  4. No surprises when comparing REALs — exact match works
  5. Perfect data interchange fidelity across Sheerpower applications — string conversions are mathematically exact with zero precision loss across JSON, CSV, databases, and APIs

Sheerpower REAL normally stores values using an exact fixed-decimal representation supporting up to 54 digits before and 16 digits after the decimal point. Within this range, decimal values are represented exactly, so calculations are predictable and do not introduce binary floating-point rounding error. When greater dynamic range or additional decimal precision is required, REAL automatically uses scientific notation while retaining up to 64 significant decimal digits. The exponent can have a magnitude of up to 1,000,000,000 (a one followed by a billion zeros), allowing REAL values to represent extremely large or extremely small numbers.
Exact fractions. divr(a, b) divides and keeps the exact fraction when the quotient does not terminate — divr(1, 3), divr(100, 3), divr(total, count), divr(0.05, 12) (1/240). The fraction is carried exactly through + - * / and whole-number powers among whole numbers of any size, other fractions and short decimals (nine places or fewer, such as 0.25) while its denominator is at most 4,294,967,295 (232 - 1), so divr(1, 3) * 3 is 1 and divr(1, 3) + 0.25 is 7/12. The / operator never builds one: 1 / 3 is the sixteen-place decimal, and 1 / 3 * 3 is 0.9999999999999999. Beside a long decimal (such as 0.3333333333333333), and at every print, a fraction is the decimal it rounds to, and a result smaller than 0.00000001 is the 64-digit *Sci* decimal the divide gives, not 0. The full story, with the functions fraction$(), fraction(), numerator(), denominator() and decimal(), is on the Exact Fractions page (Internals: REAL and String Data Types).
print divr(1, 3) * 3 ! 1 print fraction$(divr(100, 3)) ! 100/3

typeof$() names the mode a value is in: *Narrow* (18 integer digits and 16 places), *Wide* (54 integer digits), *Sci* (64 significant digits with an exponent), *Rational* (an exact fraction), *Complex*, *NaN* and *Inf*. The modes are automatic: a value moves between them by its size and its origin, never by a declaration.

One more marker can follow the mode: *Rounded*, when Sheerpower had to round in making the value — a multiply or divide that needed more than sixteen places, a result past 64 significant digits, a square root that is not exact, a function computed through a double whose answer is inexact (sin(1), but not cos(0)), a fraction turned into its decimal, or text with more digits than fit. Arithmetic on a rounded value carries the mark on. The functions that round because you asked — round(), truncate(), int(), floor(), ceil() — never add it; they keep their input's. The mark says how a value was made, not what it is: a rounded 0.3333333333333333 equals one typed in, and lookups and unique() treat the two as one value. It lives only in memory — text, files and table fields do not carry it.

Arrays, statistics and complex values follow the same rule. sort() keeps each element's mark; a statistic — stats$max(), stats$median(), stats$percentile() and the rest — is marked when its data holds a rounded value; matmul() marks a product that needed more than sixteen places. Complex arithmetic keeps thirty digits in each part and marks a result it had to round to fit them, and a complex function computed through doubles is marked when the double is inexact.

third = 1 / 3 print typeof$(third) print typeof$(sqrt(4)) print typeof$(sqrt(2)) y = round(1.2345, 3) print typeof$(y) print third = 0.3333333333333333

Output:

Name:THIRD, Dtype:Real, *Narrow*, *Rounded* Name:*Literal*, Dtype:Real, *Narrow* Name:*Literal*, Dtype:Real, *Narrow*, *Rounded* Name:Y, Dtype:Real, *Narrow* 1
third = 1 / 3 dim v(*) fill v with 0.5, third, 0.25 dim s(*) s = sort(v) print typeof$(s(1)) print typeof$(s(2)) print typeof$(stats$max(v)) fill v with 0.5, 0.75, 0.25 print typeof$(stats$max(v)) print typeof$((1 + 2i) / (3 + 4i)) print typeof$((1 + 2i) / (3 + 7i)) print typeof$(sqrt(-4 + 0i)) print typeof$(sqrt(-2 + 0i))

Output:

Name:*Literal*, Dtype:Real, *Narrow* Name:*Literal*, Dtype:Real, *Narrow*, *Rounded* Name:*Literal*, Dtype:Real, *Narrow*, *Rounded* Name:*Literal*, Dtype:Real, *Narrow* Name:*Literal*, Dtype:Real, *Complex* Name:*Literal*, Dtype:Real, *Complex*, *Rounded* Name:*Literal*, Dtype:Real, *Complex* Name:*Literal*, Dtype:Real, *Complex*, *Rounded*

isrounded(x) asks the question directly: it returns 1 when x carries the mark and 0 otherwise, and like isnan() it works on a whole array — stats$sum(isrounded(v)) counts the rounded values and filter(v, not isrounded(v)) keeps the exact ones. The mark also decides how a very large value prints: an exact 64-digit integer, such as 1e63 or the 304th Fibonacci number, prints every digit, while one that had to be rounded to fit prints in scientific notation.

third = 1 / 3 print isrounded(third), isrounded(0.05), isrounded(divr(1, 3)) dim v(*) fill v with third, 0.5, 1 / 7, 0.25 print isrounded(v) print stats$sum(isrounded(v)) print filter(v, not isrounded(v)) big = 1e63 print big print big + 0.123 print isrounded(big), isrounded(big + 0.123)

Output:

1 0 0 1 0 1 0 2 0.5 0.25 1000000000000000000000000000000000000000000000000000000000000000 1e+63 0 1
Complex numbers, and the two specials. The same REAL holds a complex value: write the imaginary unit as a suffix (3 + 4i), or build one with complex(re, im), and the four operators, abs(), conj(), the transcendental functions and the fft() transforms follow, with thirty-digit exact-then-round arithmetic and no type to declare. And a REAL can hold NaN and Inf: they never arise from finite arithmetic (1 / 0 still raises), only from the specials _nan / _inf, from data that carried them, or from div0inf(), and then they propagate by the IEEE rules. The complex page (Processing Complex Numbers) tells the whole story, with the precision, the ranges and the transforms.
z = 3 + 4i print z * (3 - 4i), abs(z), typeof$(z) ! 25+0i 5 Name:Z, Dtype:Real, *Complex* print sqrt(-4 + 0i), conj(z) ! 0+2i 3-4i print _inf - _inf, 1 / _inf, typeof$(_nan) ! NaN 0 Name:*Literal*, Dtype:Real, *NaN*

(Show/Hide Performance Comparisons)

Why Sheerpower REALs Became Fast Enough to be Practical

Exact decimal arithmetic is not new. Decimal money types have existed for decades — COBOL's packed decimal in the 1960s, hardware decimal instructions on mainframes, and 128-bit decimal types like C#'s decimal since the early 2000s. The challenge was never correctness. It was speed.

Sheerpower REALs store values using multiple 64-bit integers. On a 32-bit machine this works correctly, but each 64-bit value must be assembled from two 32-bit registers, so every operation expands into multi-word arithmetic — carry propagation, register spills, and helper routines. The math is exact, but it runs well below the speed of native floating-point hardware. That performance gap, not any limit on accuracy, is why mainstream languages committed early to IEEE 754 binary floating-point (standardized in 1985) and to heap-allocated arbitrary-precision libraries like BigDecimal. Fast decimal was the expensive option.

What changed: Modern x86-64 CPUs perform 64-bit integer operations at full register speed. The common Narrow representation (18.16) is particularly fast on modern 64-bit processors. Its primary numeric components fit naturally into 64-bit registers, allowing many ordinary REAL operations to use native integer instructions directly. Wider REAL values use additional internal words as required.

Addition and subtraction collapse to a few integer instructions. Multiplication uses a native 64-bit multiply whose 128-bit result is scaled down and half-to-even rounded back into REAL arithmetic. In both cases, the multi-word overhead that made decimal slow on 32-bit hardware largely disappears.

Why other languages did not change course: Billions of lines of existing code depend on floating-point defaults, numeric promotion rules, and decades of performance assumptions. Backward compatibility locked those languages into their original numeric models, even as the hardware economics shifted underneath them.

Sheerpower REALs were designed for the 64-bit era. Exact decimal money math was always achievable — Sheerpower's contribution is making it run at native-integer speed for the high-volume transactional workloads where that speed matters.


Exact REAL Math Across Extreme Magnitudes

// Sheerpower Exact REAL vs. Standard Double Simulation // Purpose: Process 10 million Micro-Fees against a Global Balance // Standard double precision would lose precision here: // 1. $105 Trillion requires 15 digits of precision. // 2. The micro_fee is at the 5th decimal place. // 3. Total precision needed: 20 digits (exceeds Double's ~16 digit limit). balance = 105_000_000_000_000 // $105 Trillion (IP=105T, FP=0) micro_fee = 0.00001 // For doubles, an "Impossible" binary fraction iterations = 10_000_000 print "Processing 10 million Transactions..." start timer // This loop uses Register-Speed Integer Math for i = 1 to iterations balance = balance + micro_fee next i print "--- Results ---" print sprintf$("Final Balance: %m", balance) // %m = money format with commas print "Time Elapsed: "; _elapsed; " seconds" // Sheerpower remains exact. if balance = 105_000_000_000_100 then print "Verification: PERFECT. Zero drift after 10 million operations." else print "Verification: FAILED. Precision was lost:"; balance end if
The output:
Processing 10 million Transactions... --- Results --- Final Balance: 105,000,000,000,100 Time Elapsed: 0.218 seconds Verification: PERFECT. Zero drift after 10 million operations.

5. Summary

Sheerpower's REAL type is internally managed as multiple 64-bit integers. By fixing the decimal scale at 16 digits, the architecture provides computational determinism for base-10 fractions, eliminating the representation drift and epsilon comparison requirements built into binary floating-point (IEEE 754) math.

Decimal types like C# decimal and IEEE 754-2008 _Decimal128 support flexible scaling. This makes them well suited for scientific and general-purpose use.

Sheerpower takes a different approach. It uses a split-integer design that targets high-volume transactional logic.

Instead of dynamic scaling, it uses a fixed decimal scale. This allows many operations to map directly to native 64-bit integer math.

As a result, common financial calculations can run very quickly. In many cases, operations complete in just a few CPU cycles.


String Attributes for Efficient Processing


In this advanced discussion, we delve into Sheerpower's memory management and optimization strategies for handling strings efficiently.

  1. Length-Aware Strings
    Sheerpower STRING variables store their length internally, allowing immediate length access without scanning for a terminator.
  2. Binary-Safe Content
    Since the length is tracked internally, a STRING can include binary data, including embedded null characters.
    name$ = "A" + chr$(0) + "B"
  3. External Compatibility
    When passed to routines in other languages, Sheerpower automatically appends a zero terminator for compatibility.
    call "c_function" (name$) ! name$ is zero-terminated

Optimized Memory Management

Efficient Buffer Reuse

Sheerpower manages strings by reusing memory buffers, which significantly reduces the overhead of memory allocations and deallocations. For example, if a string holds "The rain in Spain" and is later changed to "Enjoy life", Sheerpower repurposes the existing buffer. In most applications, over 99% of string buffers are reused.

This approach avoids the frequent memory operations that cause performance bottlenecks in other languages.
All strings are over-allocated and virtually mutable, making assignments O(1) operations with no allocation/deallocation cycles.

text$ = "The rain in Spain" // Allocates a buffer text$ = "Hello world" // Reuses same buffer, updates length text$ = "X" // Still uses same buffer
Performance Impact: String assignments become fast, with no memory fragmentation. Sheerpower has no need for a garbage collector.

Comparison with Other Languages

In many languages, every string modification requires a new memory allocation, and the old memory must be deallocated. This cycle introduces overhead, especially in loops.

for i = 1 to 10_000
num$ = str$(i)
next i
Note: In Sheerpower, only one memory allocation is needed for num$. The buffer is reused in each iteration, a stark contrast to languages that could perform 10,000 allocations and deallocations, slowing down performance.

The Chunked Fixed Data Area (FDA) Optimized Memory Manager

Based on research showing 85% of business strings are under 128 bytes, Sheerpower pre-allocates thousands of fixed-size buffers on startup.

Three-Tier Memory Strategy:
  1. Strings <= 24 bytes: Inline storage in descriptor
  2. Strings 25-128 bytes: Pre-allocated FDA chunk (eliminates 85% of malloc/free)
  3. Seven additional optimized string length ranges
  4. Strings > 65536 bytes: Traditional heap allocation

Performance Optimizations Internals

String Interning with Shared String IDs (SIDs)

Sheerpower assigns every unique string value a 64-bit sequential String ID (SID). When a string variable is first created, the runtime generates a new SID for its content. When another variable is assigned the same content—either by direct assignment or by copying—the SID from the source descriptor is copied into the destination descriptor along with the data. In other words, the SID travels with the data.

The SID is stored directly inside the string's descriptor, alongside the string's length, the pointer to its character buffer, and the buffer's current allocation size. Because the SID lives inside the descriptor rather than in a centralized lookup table, Sheerpower avoids global SID-table lookups and enables several powerful runtime optimizations:

String Attributes for Efficient Processing
Descriptor holds length, pointer, current allocation, 24-byte inline buffer, and SID.
String DescriptorA$ stored locally
Value: "Hello"
Length: 5
Pointer: 0x00F3...
Allocation: 24 bytes current buffer size
SID: 982734 (in descriptor)
24-byte inline buffer
H
e
l
l
o
Strings up to 24 bytes stay entirely inside the descriptor. No heap allocation needed.
SID 982734 lives in the descriptor with length, pointer, and allocation, so no SID lookup table is required.
Buffer and Interning Behavior
For "Hello" (5 bytes):
inline buffer is used, no heap allocation.
  • Length <= 24 bytes uses inline buffer.
  • Allocation tracks current buffer size (here 24 bytes).
  • SID 982734 marks the content "Hello".
  • Equality check: compare SIDs, not characters.
  • Reassigning A$ reuses the same buffer until it outgrows 24 bytes.
  • Fast equality checks: compare SIDs instead of scanning characters. Equal SIDs mean the strings are identical, so the scan is skipped. If the SIDs differ, Sheerpower scans once to compare content; when the content matches, the higher (newer) SID is replaced with the lower (older) one, so every later comparison of those values takes the fast SID path again.
  • Copy elimination: Skip copying when source and target already share SIDs
  • Hints can be stored along with their SID to avoid re-parsing of previously parsed strings
a$ = "Microsoft" // Gets a new SID, no runtime cost company_b$ = a$ // Inherits SID, no cost after first run company_c$ = company_b$ // Contains what a$ contains and a$'s SID

Copy-on-Write for String Literals

String literal assignments cost almost nothing, as the descriptor simply points to the literal in the compiled code. A copy is only triggered upon modification.

message$ = 'System ready' // Points to literal, no allocation backup$ = message$ // Shares same literal pointer's SID message$ = message$ + ' - OK' // NOW triggers a copy on first iteration only

Boolean Arrays: One Bit a Flag

A boolean array — dim flags?(n), or the hidden result of a comparison such as scores >= 60 — is stored as a bit array: eight flags a byte, so a hundred million flags take 12.5 MB and a billion 125 MB. The array descriptor keeps its element length at 1 and the element address is an ordinal; the two accessors that read and write a boolean element decode it as byte k / 8, bit k mod 8, so every path that walks an array by element — subscripts, fill, print, filter(), sort, the statistics — works unchanged. A store accepts only 0 or 1 (NOT0OR1 otherwise), so a bit can never hold anything a bit cannot hold.

The speed comes from the kernels that never touch a single bit: when every operand of a mask expression is packed, and, or, not and the comparison masks run a word at a time, 64 flags a step; stats$sum(mask) is a population count over the words; sort of a boolean array is a population count followed by a fill. Measured: a billion flags counted in 0.11 s, a? and not b? over a billion in 0.3 s, a boolean array sorted at 3 ns an element. Comparisons whose operands are integer arrays take an all-integer fast path that writes the packed mask directly; typeof$() reports Dtype:Boolean, *Packed* for any such array.

Intelligent Caching and Hinting System

Sheerpower uses an internal hinting mechanism, using SIDs to remember recent operations and cache results. This enhances efficiency by avoiding redundant processing.

Concatenation Hinting: A cache-sized hint array remembers recent concatenation operations by SID combinations. For repetitive tasks like building SQL queries, subsequent operations become simple cache lookups.

for i = 1 to 1000 sql$ = "SELECT * FROM orders WHERE id = " + customer_id$ // After first iteration, this becomes a cache lookup next i

Function Parameter Parsing Cache: Functions like getword$() and geodistance() automatically cache parsing results by string content. If you call getword$(bible$, 1000) and then getword$(bible$, 1001), Sheerpower uses the hint to quickly find the next word without re-reading from the start.

here$ = "40.7128,-74.0060" dist1 = geodistance(here$, "34.0522,-118.2437") dist2 = geodistance(here$, "41.8781,-87.6298") // The 2nd call recognizes cached 'here$' coordinates and avoids the parsing // and numeric conversion

Practical Benefits and Use Cases

These transparent optimizations provide the most benefit for typical business application patterns:

  • Repetitive content (company names, status codes)
  • SQL query building
  • Report generation and template formatting
  • Parsing repeated data formats

Sheerpower's memory management shines in applications where performance is critical, such as real-time data analysis, and large-scale batch processing systems.

Key Takeaway: Sheerpower's string optimizations work transparently to eliminate common performance bottlenecks. Developers write natural code while the runtime automatically optimizes for memory efficiency, eliminates redundant operations, and caches expensive parsing.

By understanding these advanced techniques, you can harness Sheerpower's capabilities to build highly efficient, scalable, and robust applications that handle strings with high performance.

Hide Description

    

       


      

Enter or modify the code below, and then click on RUN

Looking for the full power of Sheerpower?
Check out the Sheerpower website. Free to download. Free to use.