Built with Alectryon, running Coq+SerAPI v8.10.0+0.7.0. Coq sources are in this panel; goals and messages will appear in the other. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑ Ctrl+↓ to navigate, Ctrl+🖱️ to focus.
(************************************************************************)
(* * The Coq Proof Assistant / The Coq Development Team *)
(* v * INRIA, CNRS and contributors - Copyright 1999-2018 *)
(* <O___,, * (see CREDITS file for the list of authors) *)
(* \VV/ **************************************************************)
(* // * This file is distributed under the terms of the *)
(* * GNU Lesser General Public License Version 2.1 *)
(* * (see LICENSE file for the text of the license) *)
(************************************************************************)
Require Import Decimal DecimalFacts Arith. Module Unsigned.
A few helper functions used during proofs
Definition hd d := match d with | Nil => 0 | D0 _ => 0 | D1 _ => 1 | D2 _ => 2 | D3 _ => 3 | D4 _ => 4 | D5 _ => 5 | D6 _ => 6 | D7 _ => 7 | D8 _ => 8 | D9 _ => 9 end. Definition tl d := match d with | Nil => d | D0 d | D1 d | D2 d | D3 d | D4 d | D5 d | D6 d | D7 d | D8 d | D9 d => d end. Fixpoint usize (d:uint) : nat := match d with | Nil => 0 | D0 d => S (usize d) | D1 d => S (usize d) | D2 d => S (usize d) | D3 d => S (usize d) | D4 d => S (usize d) | D5 d => S (usize d) | D6 d => S (usize d) | D7 d => S (usize d) | D8 d => S (usize d) | D9 d => S (usize d) end.
A direct version of to_little_uint, not tail-recursive
Fixpoint to_lu n :=
match n with
| 0 => Decimal.zero
| S n => Little.succ (to_lu n)
end.
A direct version of of_little_uint
Fixpoint of_lu (d:uint) : nat :=
match d with
| Nil => 0
| D0 d => 10 * of_lu d
| D1 d => 1 + 10 * of_lu d
| D2 d => 2 + 10 * of_lu d
| D3 d => 3 + 10 * of_lu d
| D4 d => 4 + 10 * of_lu d
| D5 d => 5 + 10 * of_lu d
| D6 d => 6 + 10 * of_lu d
| D7 d => 7 + 10 * of_lu d
| D8 d => 8 + 10 * of_lu d
| D9 d => 9 + 10 * of_lu d
end.
Properties of to_lu
n:natto_lu (S n) = Little.succ (to_lu n)reflexivity. Qed.n:natto_lu (S n) = Little.succ (to_lu n)n:natd:uintNat.to_little_uint n (Little.succ d) = Little.succ (Nat.to_little_uint n d)revert d; induction n; simpl; trivial. Qed.n:natd:uintNat.to_little_uint n (Little.succ d) = Little.succ (Nat.to_little_uint n d)n:natto_lu n = Nat.to_little_uint n 0n:natto_lu n = Nat.to_little_uint n 0now rewrite IHn, <- to_little_uint_succ. Qed.n:natIHn:to_lu n = Nat.to_little_uint n 0Little.succ (to_lu n) = Nat.to_little_uint n 1n:natNat.to_uint n = rev (to_lu n)n:natNat.to_uint n = rev (to_lu n)n:natrev (Nat.to_little_uint n 0) = rev (to_lu n)n:natNat.to_little_uint n 0 = to_lu napply to_lu_equiv. Qed.n:natto_lu n = Nat.to_little_uint n 0
Properties of of_lu
d:uintof_lu d = hd d + 10 * of_lu (tl d)induction d; simpl; trivial. Qed. Ltac simpl_of_lu := match goal with | |- context [ of_lu (?f ?x) ] => rewrite (of_lu_eqn (f x)); simpl hd; simpl tl end.d:uintof_lu d = hd d + 10 * of_lu (tl d)d:uintof_lu (Little.succ d) = S (of_lu d)d:uintof_lu (Little.succ d) = S (of_lu d)d:uintIHd:of_lu (Little.succ d) = S (of_lu d)of_lu (Little.succ (D9 d)) = S (of_lu (D9 d))d:uintIHd:of_lu (Little.succ d) = S (of_lu d)0 + 10 * of_lu (Little.succ d) = S (of_lu (D9 d))d:uintIHd:of_lu (Little.succ d) = S (of_lu d)0 + 10 * S (of_lu d) = S (of_lu (D9 d))now rewrite Nat.mul_succ_r, <- (Nat.add_comm 10). Qed.d:uintIHd:of_lu (Little.succ d) = S (of_lu d)0 + 10 * S (of_lu d) = S (9 + 10 * of_lu d)n:natof_lu (to_lu n) = nn:natof_lu (to_lu n) = nn:natIHn:of_lu (to_lu n) = nof_lu (Little.succ (to_lu n)) = S nnow f_equal. Qed.n:natIHn:of_lu (to_lu n) = nS (of_lu (to_lu n)) = S nd, d':uintof_lu (revapp d d') = of_lu (rev d) + of_lu d' * 10 ^ usize dd, d':uintof_lu (revapp d d') = of_lu (rev d) + of_lu d' * 10 ^ usize dinduction d; intro d'; simpl usize; [ simpl; now rewrite Nat.mul_1_r | .. ]; unfold rev; simpl revapp; rewrite 2 IHd; rewrite <- Nat.add_assoc; f_equal; simpl_of_lu; simpl of_lu; rewrite Nat.pow_succ_r'; ring. Qed.d:uintforall d' : uint, of_lu (revapp d d') = of_lu (rev d) + of_lu d' * 10 ^ usize dn:natd:uintNat.of_uint_acc d n = of_lu (rev d) + n * 10 ^ usize dn:natd:uintNat.of_uint_acc d n = of_lu (rev d) + n * 10 ^ usize dinduction d; intros; simpl Nat.of_uint_acc; rewrite ?Nat.tail_mul_spec, ?IHd; simpl rev; simpl usize; rewrite ?Nat.pow_succ_r'; [ simpl; now rewrite Nat.mul_1_r | .. ]; unfold rev at 2; simpl revapp; rewrite of_lu_revapp; simpl of_lu; ring. Qed.d:uintforall n : nat, Nat.of_uint_acc d n = of_lu (rev d) + n * 10 ^ usize dd:uintNat.of_uint d = of_lu (rev d)d:uintNat.of_uint d = of_lu (rev d)now rewrite of_uint_acc_spec. Qed.d:uintNat.of_uint_acc d 0 = of_lu (rev d)
First main bijection result
n:natNat.of_uint (Nat.to_uint n) = nn:natNat.of_uint (Nat.to_uint n) = napply of_to_lu. Qed.n:natof_lu (to_lu n) = n
The other direction
n:natn <> 0 -> to_lu (10 * n) = D0 (to_lu n)n:natn <> 0 -> to_lu (10 * n) = D0 (to_lu n)0 <> 0 -> to_lu (10 * 0) = D0 (to_lu 0)n:natIHn:n <> 0 -> to_lu (10 * n) = D0 (to_lu n)S n <> 0 -> to_lu (10 * S n) = D0 (to_lu (S n))0 <> 0 -> to_lu (10 * 0) = D0 (to_lu 0)now destruct 1.0 <> 0 -> 0%uint = 00%uintn:natIHn:n <> 0 -> to_lu (10 * n) = D0 (to_lu n)S n <> 0 -> to_lu (10 * S n) = D0 (to_lu (S n))n:natIHn:n <> 0 -> to_lu (10 * n) = D0 (to_lu n)to_lu (10 * S n) = D0 (to_lu (S n))n:natIHn:n <> 0 -> to_lu (10 * n) = D0 (to_lu n)H:n <> 0Little.succ (to_lu (n + S (n + S (n + S (n + S (n + S (n + S (n + S (n + ...))))))))) = D0 (Little.succ (to_lu n))n:natIHn:n <> 0 -> to_lu (10 * n) = D0 (to_lu n)H:n <> 0Little.succ (to_lu (S (S (S (S (S (S (S (S (S (n + (n + (...))))))))))))) = D0 (Little.succ (to_lu n))n:natIHn:n <> 0 -> to_lu (n + (n + (n + (n + (n + (n + (n + (n + (n + (n + 0)))))))))) = D0 (to_lu n)H:n <> 0Little.succ (Little.succ (Little.succ (Little.succ (Little.succ (Little.succ (Little.succ (Little.succ (Little.succ (Little.succ (to_lu (n + (n + (...))))))))))))) = D0 (Little.succ (to_lu n))now destruct (to_lu n). Qed.n:natIHn:n <> 0 -> to_lu (n + (n + (n + (n + (n + (n + (n + (n + (n + (n + 0)))))))))) = D0 (to_lu n)H:n <> 0Little.succ (Little.succ (Little.succ (Little.succ (Little.succ (Little.succ (Little.succ (Little.succ (Little.succ (Little.succ (D0 (to_lu n))))))))))) = D0 (Little.succ (to_lu n))d:uintof_lu d = 0 <-> nztail d = Nild:uintof_lu d = 0 <-> nztail d = Nild:uintIHd:of_lu d = 0 <-> nztail d = Nil0 + 10 * of_lu d = 0 <-> nztail (D0 d) = Nild:uintIHd:of_lu d = 0 <-> nztail d = Nil10 * of_lu d = 0 <-> nztail (D0 d) = Nild:uintIHd:of_lu d = 0 <-> nztail d = NilH:10 * of_lu d = 0nztail (D0 d) = Nild:uintIHd:of_lu d = 0 <-> nztail d = NilH:nztail (D0 d) = Nil10 * of_lu d = 0d:uintIHd:of_lu d = 0 <-> nztail d = NilH:10 * of_lu d = 0nztail (D0 d) = Nild:uintIHd:of_lu d = 0 <-> nztail d = NilH:of_lu d = 0nztail (D0 d) = Nild:uintIHd:of_lu d = 0 <-> nztail d = NilH:nztail d = Nilnztail (D0 d) = Nilnow rewrite H.d:uintIHd:of_lu d = 0 <-> nztail d = NilH:nztail d = Nilmatch nztail d with | Nil => Nil | D0 u => D0 (D0 u) | D1 u => D0 (D1 u) | D2 u => D0 (D2 u) | D3 u => D0 (D3 u) | D4 u => D0 (D4 u) | D5 u => D0 (D5 u) | D6 u => D0 (D6 u) | D7 u => D0 (D7 u) | D8 u => D0 (D8 u) | D9 u => D0 (D9 u) end = Nild:uintIHd:of_lu d = 0 <-> nztail d = NilH:nztail (D0 d) = Nil10 * of_lu d = 0d:uintIHd:of_lu d = 0 <-> nztail d = NilH:match nztail d with | Nil => Nil | D0 u => D0 (D0 u) | D1 u => D0 (D1 u) | D2 u => D0 (D2 u) | D3 u => D0 (D3 u) | D4 u => D0 (D4 u) | D5 u => D0 (D5 u) | D6 u => D0 (D6 u) | D7 u => D0 (D7 u) | D8 u => D0 (D8 u) | D9 u => D0 (D9 u) end = Nil10 * of_lu d = 0now destruct IHd as [_ ->]. Qed.d:uintIHd:of_lu d = 0 <-> Nil = NilH:Nil = Nil10 * of_lu d = 0d:uintto_lu (of_lu d) = lnorm d -> to_lu (10 * of_lu d) = lnorm (D0 d)d:uintto_lu (of_lu d) = lnorm d -> to_lu (10 * of_lu d) = lnorm (D0 d)d:uintIH:to_lu (of_lu d) = lnorm dto_lu (10 * of_lu d) = lnorm (D0 d)d:uintIH:to_lu (of_lu d) = lnorm dH:of_lu d = 0to_lu (10 * of_lu d) = lnorm (D0 d)d:uintIH:to_lu (of_lu d) = lnorm dH:of_lu d <> 0to_lu (10 * of_lu d) = lnorm (D0 d)d:uintIH:to_lu (of_lu d) = lnorm dH:of_lu d = 0to_lu (10 * of_lu d) = lnorm (D0 d)d:uintIH:to_lu (of_lu d) = lnorm dH:of_lu d = 0to_lu (10 * 0) = lnorm (D0 d)d:uintIH:to_lu (of_lu d) = lnorm dH:of_lu d = 00%uint = lnorm (D0 d)d:uintIH:to_lu (of_lu d) = lnorm dH:nztail d = Nil0%uint = lnorm (D0 d)d:uintIH:to_lu (of_lu d) = lnorm dH:nztail d = Nil0%uint = match nztail (D0 d) with | Nil => 0%uint | D0 u => D0 u | D1 u => D1 u | D2 u => D2 u | D3 u => D3 u | D4 u => D4 u | D5 u => D5 u | D6 u => D6 u | D7 u => D7 u | D8 u => D8 u | D9 u => D9 u endnow rewrite H.d:uintIH:to_lu (of_lu d) = lnorm dH:nztail d = Nil0%uint = match match nztail d with | Nil => Nil | D0 u => D0 (D0 u) | D1 u => D0 (D1 u) | D2 u => D0 (D2 u) | D3 u => D0 (D3 u) | D4 u => D0 (D4 u) | D5 u => D0 (D5 u) | D6 u => D0 (D6 u) | D7 u => D0 (D7 u) | D8 u => D0 (D8 u) | D9 u => D0 (D9 u) end with | Nil => 0%uint | D0 u => D0 u | D1 u => D1 u | D2 u => D2 u | D3 u => D3 u | D4 u => D4 u | D5 u => D5 u | D6 u => D6 u | D7 u => D7 u | D8 u => D8 u | D9 u => D9 u endd:uintIH:to_lu (of_lu d) = lnorm dH:of_lu d <> 0to_lu (10 * of_lu d) = lnorm (D0 d)d:uintIH:to_lu (of_lu d) = lnorm dH:of_lu d <> 0D0 (lnorm d) = lnorm (D0 d)d:uintIH:to_lu (of_lu d) = lnorm dH:nztail d <> NilD0 (lnorm d) = lnorm (D0 d)d:uintIH:to_lu (of_lu d) = lnorm dH:nztail d <> NilD0 match nztail d with | Nil => 0 | D0 u => D0 u | D1 u => D1 u | D2 u => D2 u | D3 u => D3 u | D4 u => D4 u | D5 u => D5 u | D6 u => D6 u | D7 u => D7 u | D8 u => D8 u | D9 u => D9 u end = match nztail (D0 d) with | Nil => 0%uint | D0 u => D0 u | D1 u => D1 u | D2 u => D2 u | D3 u => D3 u | D4 u => D4 u | D5 u => D5 u | D6 u => D6 u | D7 u => D7 u | D8 u => D8 u | D9 u => D9 u endnow destruct (nztail d). Qed.d:uintIH:to_lu (of_lu d) = lnorm dH:nztail d <> NilD0 match nztail d with | Nil => 0 | D0 u => D0 u | D1 u => D1 u | D2 u => D2 u | D3 u => D3 u | D4 u => D4 u | D5 u => D5 u | D6 u => D6 u | D7 u => D7 u | D8 u => D8 u | D9 u => D9 u end = match match nztail d with | Nil => Nil | D0 u => D0 (D0 u) | D1 u => D0 (D1 u) | D2 u => D0 (D2 u) | D3 u => D0 (D3 u) | D4 u => D0 (D4 u) | D5 u => D0 (D5 u) | D6 u => D0 (D6 u) | D7 u => D0 (D7 u) | D8 u => D0 (D8 u) | D9 u => D0 (D9 u) end with | Nil => 0%uint | D0 u => D0 u | D1 u => D1 u | D2 u => D2 u | D3 u => D3 u | D4 u => D4 u | D5 u => D5 u | D6 u => D6 u | D7 u => D7 u | D8 u => D8 u | D9 u => D9 u endd:uintto_lu (of_lu d) = lnorm dinduction d; [ reflexivity | .. ]; simpl_of_lu; rewrite ?Nat.add_succ_l, Nat.add_0_l, ?to_lu_succ, to_of_lu_tenfold by assumption; unfold lnorm; simpl; now destruct nztail. Qed.d:uintto_lu (of_lu d) = lnorm d
Second bijection result
d:uintNat.to_uint (Nat.of_uint d) = unorm dd:uintNat.to_uint (Nat.of_uint d) = unorm dapply rev_lnorm_rev. Qed.d:uintrev (lnorm (rev d)) = unorm d
Some consequences
n, n':natNat.to_uint n = Nat.to_uint n' -> n = n'n, n':natNat.to_uint n = Nat.to_uint n' -> n = n'now rewrite <- (of_to n), <- (of_to n'), EQ. Qed.n, n':natEQ:Nat.to_uint n = Nat.to_uint n'n = n'd:uintexists n : nat, Nat.to_uint n = unorm dd:uintexists n : nat, Nat.to_uint n = unorm dapply to_of. Qed.d:uintNat.to_uint (Nat.of_uint d) = unorm dd:uintNat.of_uint (unorm d) = Nat.of_uint dd:uintNat.of_uint (unorm d) = Nat.of_uint dnow induction d. Qed.d:uintNat.of_uint_acc (unorm d) 0 = Nat.of_uint_acc d 0d, d':uintNat.of_uint d = Nat.of_uint d' -> unorm d = unorm d'd, d':uintNat.of_uint d = Nat.of_uint d' -> unorm d = unorm d'd, d':uintH:Nat.of_uint d = Nat.of_uint d'unorm d = unorm d'now f_equal. Qed.d, d':uintH:Nat.of_uint d = Nat.of_uint d'Nat.to_uint (Nat.of_uint d) = Nat.to_uint (Nat.of_uint d')d, d':uintNat.of_uint d = Nat.of_uint d' <-> unorm d = unorm d'd, d':uintNat.of_uint d = Nat.of_uint d' <-> unorm d = unorm d'd, d':uintNat.of_uint d = Nat.of_uint d' -> unorm d = unorm d'd, d':uintunorm d = unorm d' -> Nat.of_uint d = Nat.of_uint d'd, d':uintunorm d = unorm d' -> Nat.of_uint d = Nat.of_uint d'd, d':uintE:unorm d = unorm d'Nat.of_uint d = Nat.of_uint d'apply of_uint_norm. Qed. End Unsigned.d, d':uintE:unorm d = unorm d'Nat.of_uint (unorm d') = Nat.of_uint d'
Conversion from/to signed decimal numbers
Module Signed.n:natNat.of_int (Nat.to_int n) = Some nn:natNat.of_int (Nat.to_int n) = Some nn:natSome (Nat.of_uint (unorm (Nat.to_uint n))) = Some nn:natNat.of_uint (unorm (Nat.to_uint n)) = napply Unsigned.of_to. Qed.n:natNat.of_uint (Nat.to_uint n) = nd:intn:natNat.of_int d = Some n -> Nat.to_int n = norm dd:intn:natNat.of_int d = Some n -> Nat.to_int n = norm dd:intn:natmatch norm d with | Pos u => Some (Nat.of_uint u) | Neg _ => None end = Some n -> Nat.to_int n = norm dd:intd0:uintHd:norm d = Pos d0Nat.to_int (Nat.of_uint d0) = Pos d0d:intd0:uintHd:norm d = Pos d0Pos (Nat.to_uint (Nat.of_uint d0)) = Pos d0d:intd0:uintHd:norm d = Pos d0Pos (unorm d0) = Pos d0d:intd0:uintHd:norm d = Pos d0unorm d0 = d0d, d0:uintPos (unorm d) = Pos d0 -> unorm d0 = d0d, d0:uintmatch nzhead d with | Nil => 0%int | D0 u => Neg (D0 u) | D1 u => Neg (D1 u) | D2 u => Neg (D2 u) | D3 u => Neg (D3 u) | D4 u => Neg (D4 u) | D5 u => Neg (D5 u) | D6 u => Neg (D6 u) | D7 u => Neg (D7 u) | D8 u => Neg (D8 u) | D9 u => Neg (D9 u) end = Pos d0 -> unorm d0 = d0d, d0:uintPos (unorm d) = Pos d0 -> unorm d0 = d0apply unorm_invol.d:uintunorm (unorm d) = unorm ddestruct (nzhead d); now intros [= <-]. Qed.d, d0:uintmatch nzhead d with | Nil => 0%int | D0 u => Neg (D0 u) | D1 u => Neg (D1 u) | D2 u => Neg (D2 u) | D3 u => Neg (D3 u) | D4 u => Neg (D4 u) | D5 u => Neg (D5 u) | D6 u => Neg (D6 u) | D7 u => Neg (D7 u) | D8 u => Neg (D8 u) | D9 u => Neg (D9 u) end = Pos d0 -> unorm d0 = d0n, n':natNat.to_int n = Nat.to_int n' -> n = n'n, n':natNat.to_int n = Nat.to_int n' -> n = n'n, n':natE:Nat.to_int n = Nat.to_int n'n = n'n, n':natE:Nat.to_int n = Nat.to_int n'Some n = Some n'n, n':natE:Nat.to_int n = Nat.to_int n'E':Some n = Some n'n = n'now rewrite <- (of_to n), <- (of_to n'), E.n, n':natE:Nat.to_int n = Nat.to_int n'Some n = Some n'now injection E'. Qed.n, n':natE:Nat.to_int n = Nat.to_int n'E':Some n = Some n'n = n'd:uintexists n : nat, Nat.to_int n = norm (Pos d)d:uintexists n : nat, Nat.to_int n = norm (Pos d)d:uintNat.to_int (Nat.of_uint d) = norm (Pos d)now rewrite Unsigned.to_of. Qed.d:uintPos (Nat.to_uint (Nat.of_uint d)) = norm (Pos d)d:intNat.of_int (norm d) = Nat.of_int dd:intNat.of_int (norm d) = Nat.of_int dnow rewrite norm_invol. Qed.d:intmatch norm (norm d) with | Pos u => Some (Nat.of_uint u) | Neg _ => None end = match norm d with | Pos u => Some (Nat.of_uint u) | Neg _ => None endd, d':uintNat.of_int (Pos d) = Nat.of_int (Pos d') -> unorm d = unorm d'd, d':uintNat.of_int (Pos d) = Nat.of_int (Pos d') -> unorm d = unorm d'd, d':uintmatch norm (Pos d) with | Pos u => Some (Nat.of_uint u) | Neg _ => None end = match norm (Pos d') with | Pos u => Some (Nat.of_uint u) | Neg _ => None end -> unorm d = unorm d'd, d':uintSome (Nat.of_uint (unorm d)) = Some (Nat.of_uint (unorm d')) -> unorm d = unorm d'd, d':uintH:Nat.of_uint (unorm d) = Nat.of_uint (unorm d')unorm d = unorm d'now rewrite <- Unsigned.of_uint_norm, H, Unsigned.of_uint_norm. Qed. End Signed.d, d':uintH:Nat.of_uint (unorm d) = Nat.of_uint (unorm d')Nat.of_uint d = Nat.of_uint d'