Long and Double

Extended mode adds the Long signed 64-bit integer type and the Double IEEE 754 binary64 floating-point type. They are real language and ABI types: values remain 64 bits in expressions, calls, returns, variables, Fields, arrays, collections, Data, Banks, streams, the debugger, and UserLib calls. Compile with --mode extended or select Extended in Program Options. Original mode neither reserves these names nor accepts their literals or annotations.

Declarations and literals

TypeAnnotationDefaultLiteral forms
Long:Long0L5000000000L, $1122334455667788L, %1010L
Double:Double0.0D1.5D, 1D, 6.022e23D, .25D

Long ranges from -9223372036854775808L through 9223372036854775807L. Double has 53 bits of significand precision, about 15 to 17 significant decimal digits. A suffix is required to make a wide literal; an unsuffixed whole number remains Int and an unsuffixed decimal remains Float.

Dialect "modern"

Global ticks:Long = 5000000000L
Local precise:Double = 9007199254740991.0D
Dim samples:Double(63)

Type Measurement
    Field sequence:Long = 1L
    Field value:Double = 0.0D
End Type

:Long and :Double use named annotations and therefore require Dialect "modern". They are valid for Globals, Locals, Constants, parameters, Function and Method returns, Fields, dynamic arrays, Extended fixed arrays, and collection element/key/value types.

Promotion and conversion

For numeric arithmetic and comparison, Double dominates every numeric type. Long combined with Float also produces Double so a Long is never silently narrowed to Float. Otherwise Long dominates Int. Comparisons still return Int True or False.

ConversionBehavior
Int to Long; Float to DoubleExact.
Long to DoubleRounded to the nearest representable binary64 value, ties to even.
Int or Long to FloatRounded to binary32 precision.
Float or Double to LongTruncated toward zero; NaN, infinity, and out-of-range values raise a runtime error.
Float or Double to IntUses the characterized legacy Int conversion behavior.
String to Long/DoubleThe whole String must be a valid number; trailing non-numeric text raises a runtime error.
Any numeric type to StringProduces a round-trip decimal representation; Double preserves negative zero.

The explicit conversions are Long(value) and Double(value). The existing Int, Float, and Str conversions accept the new types.

Long arithmetic

Long addition, subtraction, multiplication, negation, and left shift use two's-complement modulo-264 results. And, Or, Xor, and ~ operate on all 64 bits. Shift counts are masked to 0 through 63, including negative counts. Shr is logical and Sar preserves the sign bit. Division truncates toward zero; division or Mod by zero raises a runtime error. The otherwise unrepresentable LongMin / -1L result wraps to LongMin and its remainder is zero.

Double arithmetic and determinism

Double expression results are binary64 values rounded to nearest, ties to even. Generated code does not retain wider x87 intermediates. All arithmetic NaNs are canonicalized to quiet NaN bits $7ff8000000000000L; comparisons with NaN follow IEEE rules, so every ordered comparison and equality is False and inequality is True. Signed zero is preserved. Double division by positive or negative zero follows IEEE 754, producing a signed infinity for a nonzero numerator and the canonical NaN for zero divided by zero.

The following deterministic Double commands use degrees for angles and a pinned fdlibm implementation shared by constant folding and runtime execution:

SinD  CosD  TanD  ASinD  ACosD  ATanD  ATan2D
SqrtD  ExpD  LogD  Log10D  PowD  ModD
FloorD  CeilD  TruncD  RoundD

Extended mode also provides raw-radian variants for algorithms whose angle values are already expressed in radians:

SinRadD  CosRadD  TanRadD
ASinRadD  ACosRadD  ATanRadD  ATan2RadD

The forward functions consume radians and the inverse functions return radians. ATan2RadD(y,x) keeps the same parameter order as ATan2D. These commands call the pinned fdlibm implementation directly, preserve signed zero, follow its infinity and quadrant behavior, and canonicalize every NaN result to $7ff8000000000000L. They do not perform a degree/radian conversion and do not change any existing degree-based command.

RoundD rounds to the nearest integral Double with ties to even. Domain errors return the canonical NaN; overflow produces infinity where IEEE 754 specifies it. These commands and Double arithmetic have matching raw result bits in supported 32-bit and 64-bit builds. A native UserLib must preserve the floating-point environment across a call.

Raw bit casts

CommandResult
FloatBits(float)Returns the unchanged 32-bit representation as Int.
FloatFromBits(int)Creates a Float from unchanged bits.
DoubleBits(double)Returns the unchanged 64-bit representation as Long.
DoubleFromBits(long)Creates a Double from unchanged bits.

Bit casts do not perform a numeric conversion and preserve every bit, including NaN payloads and signed zero. A later arithmetic operation may apply the canonical-NaN rule.

Storage, Data, Banks, and streams

Long and Double retain their type in scalar variables, Fields, dynamic and fixed arrays, multidimensional arrays, List/Map/Set/Queue/Stack values, calls, returns, and mixed Data tables. Read converts the next item to the type of its destination; Restore works as usual.

Data 5000000000L, 0.1D
Read id:Long, fraction:Double

Banks use PeekLong/PokeLong and PeekDouble/PokeDouble. Streams use ReadLong/WriteLong and ReadDouble/WriteDouble. Each reads or writes exactly eight bytes in the same little-endian format used by existing Int and Float commands. Unaligned Bank offsets are supported; debug builds bounds-check all eight bytes.

Double Map and Set keys compare numerically. Positive and negative zero are the same key. NaN is rejected as a key because it cannot form a stable equality relation.

Functions, Methods, Interfaces, and UserLibs

Function Accumulate:Long(total:Long, amount:Long)
    Return total + amount
End Function

Function Hypotenuse:Double(x:Double, y:Double)
    Return SqrtD(x*x + y*y)
End Function

Wide values use the same declaration, default-argument, recursion, Method, and Interface rules as other basic values. The compiler preserves the complete 64-bit value through the 32-bit and 64-bit internal ABIs. The debugger displays Long as signed decimal and Double with enough digits to reconstruct the same bits.

UserLib declarations use readable annotations such as EchoLong:Long(value:Long) and EchoDouble:Double(value:Double). See the bundled userlibs/UserLibs.txt for the exact native ABI rules.

Complete sample

See samples/language/11_Long_And_Double.bb for a runnable self-checking program that combines declarations, arrays, Fields, Functions, bit casts, storage, and deterministic math.