Digits #
Conversions between natural numbers and big-endian or little-endian lists of digits in a given
base. The digits are represented as elements of Fin base.
The definitions are simple specifications. They are replaced at runtime, using csimp, by
divide-and-conquer implementations, which are subquadratic when combined with the subquadratic
multiplication and division of Nat.
Construct a natural number from a big-endian list of digits in the given base:
ofFinDigits (base := 10) [2,3,4] = 234 -- 2*10^2 + 3*10^1 + 4*10^0
ofFinDigits (base := 2) [0,1,0,0] = 4 -- 0*2^3 + 1*2^2 + 0*2^1 + 0*2^0
ofFinDigits (base := b) [] = 0 -- any base, including "base 0" and "base 1"
There are no valid inputs other than [] in "base 0". In "base 1", the only valid digit is 0
and therefore ofFinDigits (base := 1) l = 0.
Equations
- Nat.ofFinDigits l = List.foldl (fun (n : Nat) (d : Fin base) => n * base + ↑d) 0 l
Instances For
Construct a natural number from a little-endian list of digits in the given base:
ofFinDigitsRev (base := 10) [4,3,2] = 234 -- 2*10^2 + 3*10^1 + 4*10^0
ofFinDigitsRev (base := 2) [0,0,1,0] = 4 -- 0*2^3 + 1*2^2 + 0*2^1 + 0*2^0
ofFinDigitsRev (base := b) [] = 0 -- any base, including "base 0" and "base 1"
There are no valid inputs other than [] in "base 0". In "base 1", the only valid digit is 0
and therefore ofFinDigitsRev (base := 1) l = 0.
Equations
- Nat.ofFinDigitsRev l = List.foldr (fun (d : Fin base) (n : Nat) => n * base + ↑d) 0 l
Instances For
The prec least significant digits of n in the given base, listed in big-endian order.
Only "base 0" is invalid, this is ensured by a NeZero base instance. In "base 1" the result is
always a list of 0s with length prec.
toFinDigitsFixed 123 10 3 = ([1,2,3] : List (Fin 10))
toFinDigitsFixed 123 10 2 = ([2,3] : List (Fin 10))
toFinDigitsFixed 4 2 4 = ([0,1,0,0] : List (Fin 2))
toFinDigitsFixed 12345 1 5 = ([0,0,0,0,0] : List (Fin 1))
Equations
- n.toFinDigitsFixed base 0 = []
- n.toFinDigitsFixed base prec_2.succ = (n / base).toFinDigitsFixed base prec_2 ++ [Fin.ofNat base n]
Instances For
The prec least significant digits of n in the given base, listed in little-endian order.
Only "base 0" is invalid, this is ensured by a NeZero base instance. In "base 1" the result is
always a list of 0s with length prec.
toFinDigitsFixedRev 123 10 3 = ([3,2,1] : List (Fin 10))
toFinDigitsFixedRev 123 10 2 = ([3,2] : List (Fin 10))
toFinDigitsFixedRev 4 2 4 = ([0,0,1,0] : List (Fin 2))
toFinDigitsFixedRev 12345 1 5 = ([0,0,0,0,0] : List (Fin 1))
Equations
- n.toFinDigitsFixedRev base 0 = []
- n.toFinDigitsFixedRev base prec_2.succ = Fin.ofNat base n :: (n / base).toFinDigitsFixedRev base prec_2
Instances For
Big-endian list of digits of a natural number n in a given base.
When n is zero, the result is the empty list. Otherwise, the most significant digit is nonzero.
The base should be at least 2, the result is always the empty list in "base 0" and "base 1".
toFinDigits 123 10 = ([1,2,3] : List (Fin 10))
toFinDigits 4 2 = ([1,0,0] : List (Fin 2))
toFinDigits 0 12345 = ([] : List (Fin 12345))
Equations
Instances For
Little-endian list of digits of a natural number n in a given base.
When n is zero, the result is the empty list. Otherwise, the most significant digit is nonzero.
The base should be at least 2, the result is always the empty list in "base 0" and "base 1".
toFinDigitsRev 123 10 = ([3,2,1] : List (Fin 10))
toFinDigitsRev 4 2 = ([0,0,1] : List (Fin 2))
toFinDigitsRev 0 12345 = ([] : List (Fin 12345))
Equations
Instances For
Lemmas #
In "base 0" and "base 1", the only valid digits are zeros and ofFinDigits is always 0.
In "base 1", toFinDigitsFixed is a list of zeros.
In "base 0" and "base 1", toFinDigits is always the empty list.
The most significant digit of toFinDigits n base is nonzero.
Subquadratic implementations #
The definitions and theorems in the Nat.Internal namespace implement the functions above at
runtime via csimp. They are public only because csimp requires it. They are not intended as part
of the public API and they may change without warning.
Each implementation splits its input roughly in half and falls back to a simple loop on small
inputs, where computing base ^ k and splitting would cost more than it saves. The cutoffs are
16 digits for ofFinDigits and toFinDigitsFixed, and a split size of at least 8 digits for
toFinDigits. They were picked by judgment rather than tuned by benchmarks. Correctness does not
depend on them.
Divide-and-conquer implementation of Nat.ofFinDigits.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Divide-and-conquer implementation of Nat.toFinDigitsFixed.
Equations
- Nat.Internal.toFinDigitsFixed n base prec = Nat.Internal.toFinDigitsFixed.loopSplit✝ base n prec []
Instances For
Divide-and-conquer implementation of Nat.toFinDigits.
Equations
- Nat.Internal.toFinDigits n base = if hbase : base < 2 then [] else Nat.Internal.toFinDigits.loopSplit✝ base ⋯ n []