Library PrintPos
Require Import ZArith NArith List Zpower.
Inductive hex_digit : Set :=
| Hx0 | Hx1 | Hx2 | Hx3
| Hx4 | Hx5 | Hx6 | Hx7
| Hx8 | Hx9 | HxA | HxB
| HxC | HxD | HxE | HxF
.
Inductive hex_digit_partial : Set :=
| HDP0 | HDP1 (b: bool)
| HDP2 (b1 b0: bool)
| HDP3 (b2 b1 b0: bool)
.
Definition hex_partial_as_digit (hp: hex_digit_partial) : hex_digit :=
match hp with
| HDP0
| HDP1 false
| HDP2 false false
| HDP3 false false false ⇒ Hx0
| HDP1 true
| HDP2 false true
| HDP3 false false true ⇒ Hx1
| HDP2 true false
| HDP3 false true false ⇒ Hx2
| HDP2 true true
| HDP3 false true true ⇒ Hx3
| HDP3 true false false ⇒ Hx4
| HDP3 true false true ⇒ Hx5
| HDP3 true true false ⇒ Hx6
| HDP3 true true true ⇒ Hx7
end.
Definition set_next_bit (bh: hex_digit_partial)
: hex_digit + hex_digit_partial :=
match bh with
| HDP0 ⇒ inr _ (HDP1 true)
| HDP1 b ⇒ inr _ (HDP2 true b)
| HDP2 b1 b0 ⇒ inr _ (HDP3 true b1 b0)
| HDP3 b2 b1 b0 ⇒ inl _
(match b2, b1, b0 with
| false, false, false ⇒ Hx8
| false, false, true ⇒ Hx9
| false, true , false ⇒ HxA
| false, true , true ⇒ HxB
| true , false, false ⇒ HxC
| true , false, true ⇒ HxD
| true , true , false ⇒ HxE
| true , true , true ⇒ HxF
end)
end.
Definition reset_next_bit (bh: hex_digit_partial)
: hex_digit + hex_digit_partial :=
match bh with
| HDP0 ⇒ inr _ (HDP1 false)
| HDP1 b ⇒ inr _ (HDP2 false b)
| HDP2 b1 b0 ⇒ inr _ (HDP3 false b1 b0)
| HDP3 b2 b1 b0 ⇒ inl _
(match b2, b1, b0 with
| false, false, false ⇒ Hx0
| false, false, true ⇒ Hx1
| false, true , false ⇒ Hx2
| false, true , true ⇒ Hx3
| true , false, false ⇒ Hx4
| true , false, true ⇒ Hx5
| true , true , false ⇒ Hx6
| true , true , true ⇒ Hx7
end)
end.
Definition hex_num : Set := list hex_digit.
Fixpoint hex_of_pos' (p: positive) (curr: hex_digit_partial) (acc: hex_num)
{struct p} : hex_num :=
match p with
| xH ⇒ match set_next_bit curr with
| inl d ⇒ d
| inr hp ⇒ hex_partial_as_digit hp
end :: acc
| xO p' ⇒ match reset_next_bit curr with
| inl d ⇒ hex_of_pos' p' HDP0 (d::acc)
| inr hp ⇒ hex_of_pos' p' hp acc
end
| xI p' ⇒ match set_next_bit curr with
| inl d ⇒ hex_of_pos' p' HDP0 (d::acc)
| inr hp ⇒ hex_of_pos' p' hp acc
end
end.
Definition hex_of_pos (p: positive) : hex_num :=
hex_of_pos' p HDP0 nil.
Section PRINT.
Require Import Ascii String.
Local Open Scope char_scope.
Definition hex_digit_ascii (hx: hex_digit) : ascii :=
match hx with
| Hx0 ⇒ "0" | Hx1 ⇒ "1"
| Hx2 ⇒ "2" | Hx3 ⇒ "3"
| Hx4 ⇒ "4" | Hx5 ⇒ "5"
| Hx6 ⇒ "6" | Hx7 ⇒ "7"
| Hx8 ⇒ "8" | Hx9 ⇒ "9"
| HxA ⇒ "A" | HxB ⇒ "B"
| HxC ⇒ "C" | HxD ⇒ "D"
| HxE ⇒ "E" | HxF ⇒ "F"
end.
Fixpoint hex_num_string (hn: hex_num) {struct hn} : string :=
match hn with
| d :: hn' ⇒ String (hex_digit_ascii d) (hex_num_string hn')
| nil ⇒ EmptyString
end.
Definition print_pos (p: positive) : string :=
("0x" ++ hex_num_string (hex_of_pos p))%string.
Definition string_of_z (z: Z) : string :=
(match z with
| Z0 ⇒ "0"
| Zpos p ⇒ print_pos p
| Zneg p ⇒ "-" ++ print_pos p
end)%string.
End PRINT.