/p/nym-moultest123/xmath/v0
gno.land/p/nym-moultest123/xmath
Max, Min, Clamp, Abs and Sign for every built-in numeric type, one
concrete function per type. Gno has no generics, so the alternative is writing
the same three-line helper again in each realm.
1xmath.MaxInt(3, 7) // 7
2xmath.ClampInt64(x, 0, 100) // x, bounded to [0,100]
3xmath.AbsFloat64(-2.5) // 2.5
4xmath.SignInt(-9) // -1
| type | functions |
|---|---|
int, int8, int16, int32, int64 |
Max, Min, Clamp, Abs, Sign |
uint, uint8, uint16, uint32, uint64 |
Max, Min, Clamp |
float32, float64 |
Max, Min, Clamp, Abs, Sign |
Unsigned types get no Abs or Sign: both are trivially themselves and 1, and
offering them would only invite an overflow bug at the call site.
The name is the type suffix: MaxInt8, MinUint64, ClampFloat32.
Sign returns -1, 0 or 1. Clamp does not validate its bounds: calling it
with min > max returns one bound or the other depending on the value, so
check the bounds yourself if they are computed.
Generated
xmath.gen.gno and xmath.gen_test.gno are written by
tools/xmathgen and carry a DO NOT EDIT header.
Edit the generator, never the output:
1go -C tools run ./xmathgen # rewrite both files
2go -C tools run ./xmathgen -check # fail if they are stale
Adding a type is one row in the types table in tools/xmathgen/main.go; it
expands to 5 functions plus their tests.
The header used to name a generator.go that was never committed, so it was a
rule nobody could follow. The generator above was reconstructed from the output
it describes and reproduces both committed files byte for byte, which
go test ./tools/xmathgen asserts on every run.
MulDiv: the proportional share, through a 128-bit intermediate
Hand-written rather than generated, in muldiv.gno, because it is one function
and not a per-type family.
1xmath.MulDiv(pot, stake, total) // this stake's cut, rounded toward zero
2xmath.MulDivUp(pot, stake, total) // the same ratio, rounded away from zero
a*b/c computes a*b first, and an int64 product that does not fit wraps
silently to a plausible number. Measured with a = 2^62, b = 4, c = 8:
the true share is 2305843009213693952 and the naive form answers 0,
because 2^62 * 4 is exactly 2^64 and wraps to zero. Nothing fails, nothing
logs, and a payout split is simply wrong.
Ten realms deployed on gnoland-1 carry their own copy of this, all reaching
for math/bits the same way: bubblerumble (several versions) and kourt,
whose mulDiv128 is the same function with its own panic strings. It had no
owner in p/moul or p/nt until now.
MulDiv panics rather than returning a wrong number: on a negative operand, on
a denominator at or below zero, and on a quotient that does not fit.
MulDivUp exists because rounding is a money question, not a style one.
Rounding a fee down and a payout up is how a pool pays out more than it holds.
Use MulDiv for what someone receives and MulDivUp for what someone owes;
TestRoundingDirectionIsTheMoneyQuestion pins that they never differ by more
than one and never cross.
Adding these is a non-breaking change, so xmath stays at its current
version and every existing importer is untouched.
Part of moul/gno-contracts — moul's versioned gno.land contracts. See the repository for the full catalog, build/test tooling, and usage.
⚠️ Disclaimer: provided as-is, without warranty; not security-audited. Full disclaimer: DISCLAIMER.