lib/math: re-fold F64_EXPBIAS to const f64info/f32info struct (#40)
Restore the Hare-faithful floatinfo struct defs (ref/hare/math/floats.ha
:117,126), removing the Drew-flattened-(b) #129-era bypass (F64_EXPBIAS:int
scalar). #149 (db7523e) now lowers cross-module &def to LEAQ, so the struct
exports are addressable via the stof consumer pattern (&math.f64info ->
f: *floatinfo -> f.expbias). First real consumer of A.2 struct-composite
static-init (DATA byte-validated: f64info/f32info 40B each).
ADD export def f64info/f32info: floatinfo (hex masks value-identical to
Hare's (1<<52)-1 etc.; A.2 helper folds bare literals only, documented
at-site). DELETE export def F64_EXPBIAS (zero consumers). KEEP NAN_BITS/
INF_BITS u64 sentinels (ruling b: def NAN=0.0/0.0 blocked by #147) +
F64_EXPONENT_BIAS:u64 (bit-ops alias, Hare keeps both).
Test 952: pointer-param row reads &math.f64info + &math.f32info through
*math.floatinfo, all 5 fields each (pointer-param not direct field-read,
dodges #150). Make test 184/184 incl 990-997 byte-id + combined_ww_fresh.
lib/math not compiler-imported -> no regen.
Unblocks fold-4 stof.ha.
This commit is contained in:
@@ -3,8 +3,9 @@
|
||||
// ref/hare/math/floats.ha (fold-1: classify/sign/bits; fold-2a:
|
||||
// issubnormalf64/normalizef64/frexpf64; strconv-foundation fold-1a:
|
||||
// F32 bit-layout + f32bits/f32frombits + floatinfo struct type;
|
||||
// fold-1b: NAN_BITS/INF_BITS sentinels + F64_EXPBIAS (flattened from
|
||||
// f64info per #129)). frexpf64's zero guard `n == 0f64` rides the #103
|
||||
// fold-1b: NAN_BITS/INF_BITS sentinels; γ-cleanup: f64info/f32info
|
||||
// instances re-folded once #149 lowered &math.f64info). frexpf64's
|
||||
// zero guard `n == 0f64` rides the #103
|
||||
// fix (no-decimal f64 literal now materialized into XMM) and its
|
||||
// (f64, i64) tuple return rides the #105 fix (tuple f64-word read).
|
||||
// The ldexp/modfrac/nextafter family stays deferred (need f64 DIVIDE).
|
||||
@@ -78,15 +79,6 @@ def F64_EXP_REMOVAL_MASK: u64 = ~(F64_EXPONENT_MASK << F64_MANTISSA_BITS);
|
||||
// ref/hare/math/floats.ha:84
|
||||
def F64_EXP_ZERO: u64 = (F64_EXPONENT_BIAS - 1) << F64_MANTISSA_BITS;
|
||||
|
||||
// flattened from f64info per #129 (cgen module-level struct-init gap);
|
||||
// cite ref/hare/math/floats.ha:117. Re-fold to const f64info: floatinfo
|
||||
// when #129 closes (γ-cleanup pattern per amalloc-drop precedent).
|
||||
// The existing F64_EXPONENT_BIAS:u64 above is the bit-ops alias; this
|
||||
// int-typed F64_EXPBIAS is the floatinfo.expbias-field counterpart and
|
||||
// drops the cast at the construction site (see ref/hare/strconv/stof.ha
|
||||
// :248,288 for the consumer pattern).
|
||||
export def F64_EXPBIAS: int = 1023;
|
||||
|
||||
// F32 bit-structure constants. ref/hare/math/floats.ha:27,30,33 declare
|
||||
// these as untyped int; ww has no untyped def, so they ride u32 (matching
|
||||
// the u32 bit container, the same way the F64 family rides u64 — see
|
||||
@@ -134,13 +126,6 @@ def F32_EXP_ZERO: u32 = (F32_EXPONENT_BIAS - 1u32) << F32_MANTISSA_BITS;
|
||||
// expbias field stays `int` — that keeps the fold-4 stof port byte-for-byte
|
||||
// against ref/hare/strconv/stof.ha:248,288 (`let e: int = 0` arithmetic
|
||||
// against `f.expbias` of the same type, no cast at use site).
|
||||
//
|
||||
// The companion `f64info` / `f32info` module-scope instances Hare exports
|
||||
// (ref/hare/math/floats.ha:117,126) are DEFERRED — ww's cgen doesn't
|
||||
// lower module-level struct lets-with-initializer (the symbol comes out
|
||||
// undefined at link time). Callers in the fold-4 stof port construct a
|
||||
// stack-local `floatinfo { ... }` and pass `&info` until that gap closes.
|
||||
// Repro logged with team lead.
|
||||
export type floatinfo = struct {
|
||||
// Bits in significand.
|
||||
mantbits: u64,
|
||||
@@ -154,6 +139,31 @@ export type floatinfo = struct {
|
||||
expmask: u64,
|
||||
};
|
||||
|
||||
// floatinfo instances for the f64 / f32 types, consumed by the
|
||||
// width-generic strconv helpers via &math.f64info (cross-module
|
||||
// address-of, lowered since #149). ref/hare/math/floats.ha:117,126.
|
||||
// Hare spells the masks (1 << 52) - 1 / (1 << 23) - 1; the #129 A.2
|
||||
// struct-composite static-init path folds only bare-literal field
|
||||
// initializers, not const-fold expressions, so the value-identical hex
|
||||
// literals are used here (0xFFFFFFFFFFFFF == (1<<52)-1, 0x7FFFFF ==
|
||||
// (1<<23)-1 — same hex-literal style as the NAN_BITS/INF_BITS sentinels
|
||||
// below). expbias rides `int` (the field type) with no suffix.
|
||||
export def f64info: floatinfo = floatinfo {
|
||||
mantbits = 52u64,
|
||||
expbits = 11u64,
|
||||
expbias = 1023,
|
||||
mantmask = 0xFFFFFFFFFFFFFu64,
|
||||
expmask = 0x7FFu64,
|
||||
};
|
||||
|
||||
export def f32info: floatinfo = floatinfo {
|
||||
mantbits = 23u64,
|
||||
expbits = 8u64,
|
||||
expbias = 127,
|
||||
mantmask = 0x7FFFFFu64,
|
||||
expmask = 0xFFu64,
|
||||
};
|
||||
|
||||
// IEEE-754 quiet-NaN and positive-Infinity f64 bit sentinels.
|
||||
// ref/hare/math/floats.ha:137,141. Hare exports `def NAN = 0.0/0.0;` and
|
||||
// `def INF = 1.0/0.0;` (untyped float def-fold); ww's cgen doesn't lower
|
||||
|
||||
@@ -327,20 +327,32 @@ static const struct row rows[] = {
|
||||
" if (math.isinf(1.23)) { return 7; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
/* F64_EXPBIAS — the f64info.expbias-field-typed counterpart of the
|
||||
* existing F64_EXPONENT_BIAS:u64. Flattened from f64info per #129.
|
||||
* Round-trips into a floatinfo struct's expbias field with zero
|
||||
* casts (the consumer pattern fold-4 stof will use). Cite ref/hare/
|
||||
* math/floats.ha:117 (f64info struct const) + :24 (the existing
|
||||
* untyped F64_EXPONENT_BIAS). */
|
||||
/* f64info / f32info module-scope instances, read cross-module through
|
||||
* a *floatinfo pointer parameter — the exact call shape stof's
|
||||
* eisel_lemire (`f: *floatinfo`) uses in fold-4. Address-of a
|
||||
* module-level def lowers to LEAQ since #149; the field reads
|
||||
* round-trip the static-init DATA the #129 A.2 path emits. Mirrors
|
||||
* ref/hare/math/floats.ha:117,126. Pointer-param (not direct
|
||||
* math.f64info.expbias) because a cross-module struct-field direct read
|
||||
* leaks the field name as an extern (#150, task list #48). */
|
||||
{ "package main;\n"
|
||||
"import math;\n"
|
||||
"fn rdbias(f: *math.floatinfo) int = { return f.expbias; };\n"
|
||||
"fn rdmant(f: *math.floatinfo) u64 = { return f.mantbits; };\n"
|
||||
"fn rdmask(f: *math.floatinfo) u64 = { return f.mantmask; };\n"
|
||||
"fn rdebits(f: *math.floatinfo) u64 = { return f.expbits; };\n"
|
||||
"fn rdemask(f: *math.floatinfo) u64 = { return f.expmask; };\n"
|
||||
"export fn main() i32 = {\n"
|
||||
" if (math.F64_EXPBIAS != 1023) { return 1; };\n"
|
||||
" let info: math.floatinfo;\n"
|
||||
" info.expbias = math.F64_EXPBIAS;\n"
|
||||
" if (info.expbias != 1023) { return 2; };\n"
|
||||
" if (info.expbias != math.F64_EXPBIAS) { return 3; };\n"
|
||||
" if (rdbias(&math.f64info) != 1023) { return 1; };\n"
|
||||
" if (rdmant(&math.f64info) != 52u64) { return 2; };\n"
|
||||
" if (rdmask(&math.f64info) != 0xFFFFFFFFFFFFFu64) { return 3; };\n"
|
||||
" if (rdbias(&math.f32info) != 127) { return 4; };\n"
|
||||
" if (rdmant(&math.f32info) != 23u64) { return 5; };\n"
|
||||
" if (rdmask(&math.f32info) != 0x7FFFFFu64) { return 6; };\n"
|
||||
" if (rdebits(&math.f64info) != 11u64) { return 7; };\n"
|
||||
" if (rdemask(&math.f64info) != 0x7FFu64) { return 8; };\n"
|
||||
" if (rdebits(&math.f32info) != 8u64) { return 9; };\n"
|
||||
" if (rdemask(&math.f32info) != 0xFFu64) { return 10; };\n"
|
||||
" return 0;\n"
|
||||
"};\n", 0 },
|
||||
{ NULL, 0 }
|
||||
|
||||
Reference in New Issue
Block a user