An unjetted library for basic mathematical and special function support.
We support the following functions and special functions:
-
++add,$+$ addition -
++sub,$-$ subtraction -
++mul,$\times$ multiplication -
++div,$/$ division -
++mod, modulo (remainder after division) -
++fma,$\text{fma}$ fused multiply-add -
++sgn,$\text{sgn}$ signum (also++sig) -
++neg,$-$ unary negation -
++factorial,$!$ factorial -
++abs,$\text{abs}$ -
++exp,$\exp$ -
++expm1,$\exp - 1$ -
++sin,$\sin$ -
++cos,$\cos$ -
++tan,$\tan$ -
++pow-n,$\text{pow}$ to integer power -
++log,$\log$ (natural logarithm) -
++log-10,$\log_{10}$ (log base-10) -
++log-2,$\log_{2}$ (log base-2) -
++pow,$\text{pow}$ -
++sqrt,$\sqrt{}$ (also++sqt) -
++cbrt,$\sqrt[3]{}$ (also++cbt) -
++arg(alias for++absin real values)
Logical functions:
-
++lth,$<$ -
++lte$\leq$ (also++leq) -
++gth,$>$ -
++gte,$\geq$ (also++geq) -
++equ,$=$ -
++neq,$\neq$ ++is-close++all-close++is-int
Constants (to machine accuracy):
-
++tau,$\tau = 2 \pi$ -
++pi,$\pi$ -
++e,$e$ (base of natural logarithm) -
++phi,$\phi$ , Euler's constant -
++sqt2,$\sqrt{2}$ -
++invsqt2,$\frac{1}{\sqrt{2}}$ -
++log2,$\log 2$ -
++invlog2,$\frac{1}{\log 2}$ -
++log10,$\log 10$ -
++huge, largest valid number inbloqwidth -
++tiny, smallest valid number inbloqsize
It would be nice to have the following special functions as well:
$\arcsin$ $\arccos$ $\arctan$ $\sinh$ $\cosh$ $\tanh$
We do not envision including the Bessel functions and other more abstruse functions.
We use naïve algorithms which are highly reproducible. We special-case some arguments to make them tractable without catastrophic cancellation.
A library for universal numbers (posits, quires, and valids) per the 2022 Posit Standard (Posit Working Group, John Gustafson chair).
We implement the three standard precisions:
$\text{posit}\langle 8,2\rangle$ $\text{posit}\langle 16,2\rangle$ $\text{posit}\langle 32,2\rangle$
Standard, not legacy. The 2022 Posit Standard fixes the exponent size at
es = 2for every width (§2 defines the exponent field as a 2-bit unsigned integer). This differs from the original 2017 draft (and from SoftPosit's fastp8/p16types), which scaledeswith width asposit<8,0>,posit<16,1>,posit<32,2>. Onlyposit32coincides between the two conventions;posit8andposit16have different bit layouts. We target the standard. The reference oracle for 8- and 16-bit posits is therefore SoftPosit'spX2(es=2 at any width) path, not the fastp8/p16types;p32is used directly.
A posit of precision
| field | width | meaning |
|---|---|---|
| sign |
1 bit | integer |
| regime |
|
run of bits equal to |
| exponent |
2 bits | unsigned es = 2); may be truncated past the LSB, then treated as 0 |
| fraction |
up to |
unsigned |
The represented value (with useed
Exceptions (all bits except
Key constants per width (§3, Table 1;
| property | posit8 | posit16 | posit32 | |
|---|---|---|---|---|
| fraction length | 0–3 | 0–11 | 0–27 |
|
| quire bits | 128 | 256 | 512 | |
| decimals to round-trip | 2 | 5 | 10 | — |
Posits have exactly one rounding mode (§4.1): round-to-nearest, ties-to-even, and saturating — a magnitude above ++fmm, ++rsqrt, ++exp-minus-1, ++hypot, …) are evaluated exactly and rounded once.
Posit ordering is identical to two's-complement signed-integer ordering of the raw bits (§5.3), so comparisons need no decoding — a single signed compare suffices. NaR shares the bit pattern of the most-negative integer, so it compares less than every real posit; NaR == NaR is true and ++sign of NaR is NaR.
The quire is a fixed-point exact accumulator of
| aura | meaning | width |
|---|---|---|
@rpb @rph @rps @rpd |
posit | byte (8), half (16), single (32), double (64) |
@rqb @rqh @rqs |
quire | for posit8 / posit16 / posit32 |
@rvb @rvh @rvs |
valid (interval) | byte / half / single |
The @rq* quire auras nest under @rq (quad-precision float) by Hoon's prefix-nesting rule; this overlap is accepted intentionally. There is currently no literal syntax or pretty-printer for posit auras — values are written as bit-casts, e.g. `@rpb`0b100.0000 for
lib/unum.hoon implements the es = 2 layout above as a single generic core ++pp (keyed on bloq), specialized into ++rpb / ++rph / ++rps / ++rpd / ++rpq (posit8/16/32/64/128). The g-layer record +$up mirrors the standard library float +$fn. Each width exposes:
-
decode / encode —
++sea(@→+$up),++bit(+$up→@, round-to-nearest-even, saturating) -
constants —
++zero++nar++one++maxpos++minpos++huge++tiny, and++pi++tau++e++phi++sqt2++invsqt2++log2++invlog2++log10(correctly rounded at every width) -
comparison / sign —
++gth++lth++gte++lte++equ++neq,++neg++abs++sgn -
arithmetic —
++add++sub++mul++div(correctly rounded),++fma(fused multiply-add),++sqt(square root) -
rounding —
++roundwith++rnd(nearest-even) /++flr(floor) /++cel(ceil) -
integer conversion —
++sun(@u→),++san(@s→),++toi(→(unit @s)) -
IEEE-754 conversion —
++to-rh++to-rs++to-rd++to-rqand++from-rh++from-rs++from-rd++from-rq, value-based across any posit/float width pair -
quire (the
16n-bit exact accumulator) —++p-to-q++q-to-p++q-mul-add++q-mul-sub++q-add-p++q-sub-p++q-add-q++q-sub-q++q-negate, and++fdp(fused dot product, single rounding) -
elementary —
++exp++sin++cos++tan++pow-n++log++log-2++log-10++pow++is-close(naive Taylor series in the/lib/mathstyle: reproducible, accurate near 0, not range-reduced)
Arithmetic is verified against SoftPosit (the reference C implementation, via its Python wrapper): exhaustively over all posit8 pairs and sampled at posit16/32, with the offline harness in tools/posit_check.py; the on-ship suite is tests/lib/unum-core and tests/lib/unum-fns.
- the standard-name alias interface (below):
++negate++addition++compare-less++sin-pi++compound++root-n++fmm++hypot++arctan2etc., and the inverse / hyperbolic /*-plus-1/*-minus-1elementary functions ++next/++prior/++nearest-int/++ceil/++floorunder their standard names (the behaviors exist as++rnd/++flr/++cel)- valids (the interval unum class,
@rv*) - jets (the library is pure Hoon; SoftPosit's C is the spec for a future jet)
The following is the planned second interface for /lib/unum: standard-named aliases over the implemented operations above, plus the not-yet-written functions. One interface hews to the /lib/math and /lib/saloon conventions; this one aliases in the 2022 Posit Standard names, slightly modified to adhere to Hoon name requirements.
++negate←(sub 0 val)++abs← no change++sign←++sgn++nearest-int++ceil++floor++next++prior
++compare-equal←++equ++compare-not-equal←!(equ val)++compare-greater←++gth++compare-greater-equal←++gte++compare-less←++lth++compare-less-equal←++lte
++addition←++add++subtraction←++sub++multiplication←++mul++division←++div
++sqrt← no change++rsqrt← TODO++exp← no change++exp-minus-1←++expm1++exp2← no change++exp2-minus-1←++exp2m1++exp10← no change++exp10-minus-1←++exp10m1++log← no change++log-plus-1←++logp1++log2← no change++log2-plus-1←++log2p1++log10← no change++log10-plus-1←++log10p1++sin← no change++sin-pi←(sin (mul pi val))++cos← no change++cos-pi←(cos (mul pi val))++tan← no change++tan-pi←(tan (mul pi val))++arcsin← no change++arcsin-pi←(arcsin (div val pi))++arccos← no change++arccos-pi←(arccos (div val pi))++arctan← no change++arctan-pi←(arctan (div val pi))++sinh← no change++cosh← no change++tanh← no change++arcsinh← no change++arccosh← no change++arctanh← no change
++hypot←(sqt (mul val-1 val-1) (mul val-2 val-2))++pow← no change++arctan2← ??? complex++arctan2-pi←(div (arctan2 val) pi)
++fmm←:(mul val-1 val-2 val-3)
++compound←(pow (add val 1) int)++root-n←(pow val (div 1 int))
++p-to-q++q-negate++q-abs++q-add-p++q-sub-p++q-add-q++q-sub-q++q-mul-add++q-mul-sub++q-to-p
++p8-to-16++p8-to-32++p16-to-8++p16-to-32++p32-to-8++p32-to-16