Library Coq.ZArith.BinIntDef
Definition double x :=
match x with
| 0 => 0
| Zpos p => Zpos p~0
| Zneg p => Zneg p~0
end.
Definition succ_double x :=
match x with
| 0 => 1
| Zpos p => Zpos p~1
| Zneg p => Zneg (Pos.pred_double p)
end.
Definition pred_double x :=
match x with
| 0 => -1
| Zneg p => Zneg p~1
| Zpos p => Zpos (Pos.pred_double p)
end.
Fixpoint pos_sub (x y:positive) {struct y} : Z :=
match x, y with
| p~1, q~1 => double (pos_sub p q)
| p~1, q~0 => succ_double (pos_sub p q)
| p~1, 1 => Zpos p~0
| p~0, q~1 => pred_double (pos_sub p q)
| p~0, q~0 => double (pos_sub p q)
| p~0, 1 => Zpos (Pos.pred_double p)
| 1, q~1 => Zneg q~0
| 1, q~0 => Zneg (Pos.pred_double q)
| 1, 1 => Z0
end%positive.
Definition add x y :=
match x, y with
| 0, y => y
| x, 0 => x
| Zpos x', Zpos y' => Zpos (x' + y')
| Zpos x', Zneg y' => pos_sub x' y'
| Zneg x', Zpos y' => pos_sub y' x'
| Zneg x', Zneg y' => Zneg (x' + y')
end.
Infix "+" := add : Z_scope.
Definition opp x :=
match x with
| 0 => 0
| Zpos x => Zneg x
| Zneg x => Zpos x
end.
Notation "- x" := (opp x) : Z_scope.
Definition mul x y :=
match x, y with
| 0, _ => 0
| _, 0 => 0
| Zpos x', Zpos y' => Zpos (x' * y')
| Zpos x', Zneg y' => Zneg (x' * y')
| Zneg x', Zpos y' => Zneg (x' * y')
| Zneg x', Zneg y' => Zpos (x' * y')
end.
Infix "*" := mul : Z_scope.
Definition pow_pos (z:Z) (n:positive) := Pos.iter n (mul z) 1.
Definition pow x y :=
match y with
| Zpos p => pow_pos x p
| 0 => 1
| Zneg _ => 0
end.
Infix "^" := pow : Z_scope.
Definition square x :=
match x with
| 0 => 0
| Zpos p => Zpos (Pos.square p)
| Zneg p => Zpos (Pos.square p)
end.
Definition compare x y :=
match x, y with
| 0, 0 => Eq
| 0, Zpos y' => Lt
| 0, Zneg y' => Gt
| Zpos x', 0 => Gt
| Zpos x', Zpos y' => (x' ?= y')%positive
| Zpos x', Zneg y' => Gt
| Zneg x', 0 => Lt
| Zneg x', Zpos y' => Lt
| Zneg x', Zneg y' => CompOpp ((x' ?= y')%positive)
end.
Infix "?=" := compare (at level 70, no associativity) : Z_scope.
Boolean equality and comparisons
Definition leb x y :=
match x ?= y with
| Gt => false
| _ => true
end.
Definition ltb x y :=
match x ?= y with
| Lt => true
| _ => false
end.
Nota: geb and gtb are provided for compatibility,
but leb and ltb should rather be used instead, since
more results we be available on them.
Definition geb x y :=
match x ?= y with
| Lt => false
| _ => true
end.
Definition gtb x y :=
match x ?= y with
| Gt => true
| _ => false
end.
Nota: this eqb is not convertible with the generated Z_beq,
since the underlying Pos.eqb differs from positive_beq
(cf BinIntDef).
Fixpoint eqb x y :=
match x, y with
| 0, 0 => true
| Zpos p, Zpos q => Pos.eqb p q
| Zneg p, Zneg q => Pos.eqb p q
| _, _ => false
end.
Infix "=?" := eqb (at level 70, no associativity) : Z_scope.
Infix "<=?" := leb (at level 70, no associativity) : Z_scope.
Infix "<?" := ltb (at level 70, no associativity) : Z_scope.
Infix ">=?" := geb (at level 70, no associativity) : Z_scope.
Infix ">?" := gtb (at level 70, no associativity) : Z_scope.
Definition max n m :=
match n ?= m with
| Eq | Gt => n
| Lt => m
end.
Definition min n m :=
match n ?= m with
| Eq | Lt => n
| Gt => m
end.
Definition abs_nat (z:Z) : nat :=
match z with
| 0 => 0%nat
| Zpos p => Pos.to_nat p
| Zneg p => Pos.to_nat p
end.
From Z to N via absolute value
From Z to nat by rounding negative numbers to 0
From Z to N by rounding negative numbers to 0
From nat to Z
From N to Z
Euclidean divisions for binary integers
Floor division
- we have sgn (a mod b) = sgn (b)
- div a b is the greatest integer smaller or equal to the exact fraction a/b.
- there is no easy sign rule.
Fixpoint pos_div_eucl (a:positive) (b:Z) : Z * Z :=
match a with
| xH => if 2 <=? b then (0, 1) else (1, 0)
| xO a' =>
let (q, r) := pos_div_eucl a' b in
let r' := 2 * r in
if r' <? b then (2 * q, r') else (2 * q + 1, r' - b)
| xI a' =>
let (q, r) := pos_div_eucl a' b in
let r' := 2 * r + 1 in
if r' <? b then (2 * q, r') else (2 * q + 1, r' - b)
end.
Then the general euclidean division
Definition div_eucl (a b:Z) : Z * Z :=
match a, b with
| 0, _ => (0, 0)
| _, 0 => (0, 0)
| Zpos a', Zpos _ => pos_div_eucl a' b
| Zneg a', Zpos _ =>
let (q, r) := pos_div_eucl a' b in
match r with
| 0 => (- q, 0)
| _ => (- (q + 1), b - r)
end
| Zneg a', Zneg b' =>
let (q, r) := pos_div_eucl a' (Zpos b') in (q, - r)
| Zpos a', Zneg b' =>
let (q, r) := pos_div_eucl a' (Zpos b') in
match r with
| 0 => (- q, 0)
| _ => (- (q + 1), b + r)
end
end.
Definition div (a b:Z) : Z := let (q, _) := div_eucl a b in q.
Definition modulo (a b:Z) : Z := let (_, r) := div_eucl a b in r.
Infix "/" := div : Z_scope.
Infix "mod" := modulo (at level 40, no associativity) : Z_scope.
Trunc Division
- we have sgn(a rem b) = sgn(a)
- sign rule for division: quot (-a) b = quot a (-b) = -(quot a b)
- and for modulo: a rem (-b) = a rem b and (-a) rem b = -(a rem b)
Definition quotrem (a b:Z) : Z * Z :=
match a, b with
| 0, _ => (0, 0)
| _, 0 => (0, a)
| Zpos a, Zpos b =>
let (q, r) := N.pos_div_eucl a (Npos b) in (of_N q, of_N r)
| Zneg a, Zpos b =>
let (q, r) := N.pos_div_eucl a (Npos b) in (-of_N q, - of_N r)
| Zpos a, Zneg b =>
let (q, r) := N.pos_div_eucl a (Npos b) in (-of_N q, of_N r)
| Zneg a, Zneg b =>
let (q, r) := N.pos_div_eucl a (Npos b) in (of_N q, - of_N r)
end.
Definition quot a b := fst (quotrem a b).
Definition rem a b := snd (quotrem a b).
Infix "÷" := quot (at level 40, left associativity) : Z_scope.
Definition even z :=
match z with
| 0 => true
| Zpos (xO _) => true
| Zneg (xO _) => true
| _ => false
end.
Definition odd z :=
match z with
| 0 => false
| Zpos (xO _) => false
| Zneg (xO _) => false
| _ => true
end.
Division by two
Definition div2 z :=
match z with
| 0 => 0
| Zpos 1 => 0
| Zpos p => Zpos (Pos.div2 p)
| Zneg p => Zneg (Pos.div2_up p)
end.
quot2 performs rounding toward zero, it is hence a particular
case of quot, and for all relative number n we have:
n = 2 * quot2 n + if odd n then sgn n else 0.
Definition quot2 (z:Z) :=
match z with
| 0 => 0
| Zpos 1 => 0
| Zpos p => Zpos (Pos.div2 p)
| Zneg 1 => 0
| Zneg p => Zneg (Pos.div2 p)
end.
Definition log2 z :=
match z with
| Zpos (p~1) => Zpos (Pos.size p)
| Zpos (p~0) => Zpos (Pos.size p)
| _ => 0
end.
Definition sqrtrem n :=
match n with
| 0 => (0, 0)
| Zpos p =>
match Pos.sqrtrem p with
| (s, IsPos r) => (Zpos s, Zpos r)
| (s, _) => (Zpos s, 0)
end
| Zneg _ => (0,0)
end.
Definition sqrt n :=
match n with
| Zpos p => Zpos (Pos.sqrt p)
| _ => 0
end.
Definition gcd a b :=
match a,b with
| 0, _ => abs b
| _, 0 => abs a
| Zpos a, Zpos b => Zpos (Pos.gcd a b)
| Zpos a, Zneg b => Zpos (Pos.gcd a b)
| Zneg a, Zpos b => Zpos (Pos.gcd a b)
| Zneg a, Zneg b => Zpos (Pos.gcd a b)
end.
A generalized gcd, also computing division of a and b by gcd.
Definition ggcd a b : Z*(Z*Z) :=
match a,b with
| 0, _ => (abs b,(0, sgn b))
| _, 0 => (abs a,(sgn a, 0))
| Zpos a, Zpos b =>
let '(g,(aa,bb)) := Pos.ggcd a b in (Zpos g, (Zpos aa, Zpos bb))
| Zpos a, Zneg b =>
let '(g,(aa,bb)) := Pos.ggcd a b in (Zpos g, (Zpos aa, Zneg bb))
| Zneg a, Zpos b =>
let '(g,(aa,bb)) := Pos.ggcd a b in (Zpos g, (Zneg aa, Zpos bb))
| Zneg a, Zneg b =>
let '(g,(aa,bb)) := Pos.ggcd a b in (Zpos g, (Zneg aa, Zneg bb))
end.
Bitwise functions
Definition testbit a n :=
match n with
| 0 => odd a
| Zpos p =>
match a with
| 0 => false
| Zpos a => Pos.testbit a (Npos p)
| Zneg a => negb (N.testbit (Pos.pred_N a) (Npos p))
end
| Zneg _ => false
end.
Shifts
Nota: a shift to the right by -n will be a shift to the left
by n, and vice-versa.
For fulfilling the two's complement convention, shifting to
the right a negative number should correspond to a division
by 2 with rounding toward bottom, hence the use of div2
instead of quot2.
Definition shiftl a n :=
match n with
| 0 => a
| Zpos p => Pos.iter p (mul 2) a
| Zneg p => Pos.iter p div2 a
end.
Definition shiftr a n := shiftl a (-n).
Bitwise operations lor land ldiff lxor
Definition lor a b :=
match a, b with
| 0, _ => b
| _, 0 => a
| Zpos a, Zpos b => Zpos (Pos.lor a b)
| Zneg a, Zpos b => Zneg (N.succ_pos (N.ldiff (Pos.pred_N a) (Npos b)))
| Zpos a, Zneg b => Zneg (N.succ_pos (N.ldiff (Pos.pred_N b) (Npos a)))
| Zneg a, Zneg b => Zneg (N.succ_pos (N.land (Pos.pred_N a) (Pos.pred_N b)))
end.
Definition land a b :=
match a, b with
| 0, _ => 0
| _, 0 => 0
| Zpos a, Zpos b => of_N (Pos.land a b)
| Zneg a, Zpos b => of_N (N.ldiff (Npos b) (Pos.pred_N a))
| Zpos a, Zneg b => of_N (N.ldiff (Npos a) (Pos.pred_N b))
| Zneg a, Zneg b => Zneg (N.succ_pos (N.lor (Pos.pred_N a) (Pos.pred_N b)))
end.
Definition ldiff a b :=
match a, b with
| 0, _ => 0
| _, 0 => a
| Zpos a, Zpos b => of_N (Pos.ldiff a b)
| Zneg a, Zpos b => Zneg (N.succ_pos (N.lor (Pos.pred_N a) (Npos b)))
| Zpos a, Zneg b => of_N (N.land (Npos a) (Pos.pred_N b))
| Zneg a, Zneg b => of_N (N.ldiff (Pos.pred_N b) (Pos.pred_N a))
end.
Definition lxor a b :=
match a, b with
| 0, _ => b
| _, 0 => a
| Zpos a, Zpos b => of_N (Pos.lxor a b)
| Zneg a, Zpos b => Zneg (N.succ_pos (N.lxor (Pos.pred_N a) (Npos b)))
| Zpos a, Zneg b => Zneg (N.succ_pos (N.lxor (Npos a) (Pos.pred_N b)))
| Zneg a, Zneg b => of_N (N.lxor (Pos.pred_N a) (Pos.pred_N b))
end.
End Z.