Artifact 32a19d7119018f185d31c780741397ced54dff63e1240a14ac5347df47c87e9f:
- File
internal/fsltype/julian_long.go
— part of check-in
[f7eb80beae]
at
2026-10-29 03:06:14
on branch main
— perf(fsltype): format a 53-bit text Julian day in float64, no math/big
Fossil's %.17g of a text Julian day is computed in the platform's long double, which this package emulates with big.Float at that precision. A 53-bit long double is a double, and big.Float at 53 bits with round-to-nearest-even is exactly IEEE double arithmetic over this range, so that case (wasm, macOS arm64, Windows) is now computed in float64, each product converted explicitly so none fuses into a multiply-add.
The big.Float path remains for the 64- and 113-bit long doubles and is left out of wasm builds, whose long double is 53 bits; a wasm TinyGo binary loses math/big's floating point, about 5 KB gzipped. A test checks the float64 path against the big.Float one at 53 bits over 50,000 random times and every ~1 s of three days, and the existing fossil-binary sweep passes unchanged. Stored times do not change. (user: [email protected], size: 1275) [annotate] [blame] [check-ins using] [more...]
//go:build !wasm package fsltype import "math/big" // printf17gLong is fossilPrintf17g in a long double with a prec-bit // significand, emulated with big.Float at that precision and // round-to-nearest-even. func printf17gLong(v0 float64, prec uint) string { if !(v0 > 0) || prec < 53 { panic("fsltype.printf17gLong: v0 must be positive and prec at least 53") } const precision = printf17gPrecision ld := func(f float64) *big.Float { return new(big.Float).SetPrec(prec).SetFloat64(f) } v := ld(v0) scale := func(by float64) { v.Mul(v, ld(by)) } exp := 0 for v.Cmp(ld(1e32)) >= 0 && exp <= 350 { scale(1e-32) exp += 32 } for v.Cmp(ld(1e8)) >= 0 && exp <= 350 { scale(1e-8) exp += 8 } for v.Cmp(ld(10)) >= 0 && exp <= 350 { scale(0.1) exp++ } for v.Cmp(ld(1e-8)) < 0 && exp >= -350 { scale(1e8) exp -= 8 } for v.Cmp(ld(1)) < 0 && exp >= -350 { scale(10) exp-- } v.Add(v, ld(printf17gRounder())) if v.Cmp(ld(10)) >= 0 { scale(0.1) exp++ } if exp < -4 || exp > precision { panic("fsltype.printf17gLong: exponent form is not used for Julian days") } ten := ld(10) return fossilDigits(exp, precision-exp, func() int64 { d, _ := v.Int64() v.Sub(v, new(big.Float).SetPrec(prec).SetInt64(d)) v.Mul(v, ten) return d }) }