# `gno.land/p/moul/xmath/v1`
`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.
```go
xmath.MaxInt(3, 7) // 7
xmath.ClampInt64(x, 0, 100) // x, bounded to [0,100]
xmath.AbsFloat64(-2.5) // 2.5
xmath.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`](../../../tools/xmathgen) and carry a `DO NOT EDIT` header.
Edit the generator, never the output:
```sh
go -C tools run ./xmathgen # rewrite both files
go -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.
```go
xmath.MulDiv(pot, stake, total) // this stake's cut, rounded toward zero
xmath.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.
### Why `v1` even though adding a function is non-breaking
It is non-breaking **for this repo**, and that is not the constraint that
matters. `p/` packages are always public, and a live public path can never be
redeployed, so functions added in place at `v0` reach `main` and never reach the
chain. `v1` is the only way `MulDiv` becomes importable by anybody.
The bump is free here: `xmath` has **zero importers**, in this repo and across
every package deployed on `gnoland-1`. `v0` stays resolvable for nobody in
particular.
<!-- BEGIN GNOCONTRACTS FOOTER (generated by `make readmes`; do not edit below) -->
---
Part of **[moul/gno-contracts](https://github.com/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](https://github.com/moul/gno-contracts/blob/main/DISCLAIMER.md).
<!-- END GNOCONTRACTS FOOTER -->
Signatures reconstructed verbatim from vm/qfuncs — interface params keep their inline definitions.