Library Coq.PArith.BinPosDef
Binary positive numbers, operations
Initial development by Pierre Crégut, CNET, Lannion, France
The type
positive and its constructors
xI and
xO and
xH
are now defined in
BinNums.v
Postfix notation for positive numbers, allowing to mimic
the position of bits in a big-endian representation.
For instance, we can write 1~1~0 instead of (xO (xI xH))
for the number 6 (which is 110 in binary notation).
Notation "p ~ 1" := (
xI p)
(
at level 7,
left associativity,
format "p '~' '1'") :
positive_scope.
Notation "p ~ 0" := (
xO p)
(
at level 7,
left associativity,
format "p '~' '0'") :
positive_scope.
Local Open Scope positive_scope.
LocalLocal
Module Pos.
Definition t :=
positive.
Operations over positive numbers
Successor
Fixpoint add x y :=
match x,
y with
|
p~1,
q~1 =>
(add_carry p q)~0
|
p~1,
q~0 =>
(add p q)~1
|
p~1, 1 =>
(succ p)~0
|
p~0,
q~1 =>
(add p q)~1
|
p~0,
q~0 =>
(add p q)~0
|
p~0, 1 =>
p~1
| 1,
q~1 =>
(succ q)~0
| 1,
q~0 =>
q~1
| 1, 1 => 1
~0
end
with add_carry x y :=
match x,
y with
|
p~1,
q~1 =>
(add_carry p q)~1
|
p~1,
q~0 =>
(add_carry p q)~0
|
p~1, 1 =>
(succ p)~1
|
p~0,
q~1 =>
(add_carry p q)~0
|
p~0,
q~0 =>
(add p q)~1
|
p~0, 1 =>
(succ p)~0
| 1,
q~1 =>
(succ q)~1
| 1,
q~0 =>
(succ q)~0
| 1, 1 => 1
~1
end.
Infix "+" :=
add :
positive_scope.
The predecessor of a positive number can be seen as a N
An auxiliary type for subtraction
Subtraction, result as a mask
Fixpoint sub_mask (
x y:
positive) {
struct y} :
mask :=
match x,
y with
|
p~1,
q~1 =>
double_mask (
sub_mask p q)
|
p~1,
q~0 =>
succ_double_mask (
sub_mask p q)
|
p~1, 1 =>
IsPos p~0
|
p~0,
q~1 =>
succ_double_mask (
sub_mask_carry p q)
|
p~0,
q~0 =>
double_mask (
sub_mask p q)
|
p~0, 1 =>
IsPos (
pred_double p)
| 1, 1 =>
IsNul
| 1,
_ =>
IsNeg
end
with sub_mask_carry (
x y:
positive) {
struct y} :
mask :=
match x,
y with
|
p~1,
q~1 =>
succ_double_mask (
sub_mask_carry p q)
|
p~1,
q~0 =>
double_mask (
sub_mask p q)
|
p~1, 1 =>
IsPos (
pred_double p)
|
p~0,
q~1 =>
double_mask (
sub_mask_carry p q)
|
p~0,
q~0 =>
succ_double_mask (
sub_mask_carry p q)
|
p~0, 1 =>
double_pred_mask p
| 1,
_ =>
IsNeg
end.
Subtraction, result as a positive, returning 1 if x<=y
Iteration over a positive number
Division by 2 rounded below but for 1
Definition div2 p :=
match p with
| 1 => 1
|
p~0 =>
p
|
p~1 =>
p
end.
Division by 2 rounded up
Number of digits in a positive number
Same, with positive output
Comparison on binary positive numbers
Fixpoint compare_cont (
x y:
positive) (
r:
comparison) {
struct y} :
comparison :=
match x,
y with
|
p~1,
q~1 =>
compare_cont p q r
|
p~1,
q~0 =>
compare_cont p q Gt
|
p~1, 1 =>
Gt
|
p~0,
q~1 =>
compare_cont p q Lt
|
p~0,
q~0 =>
compare_cont p q r
|
p~0, 1 =>
Gt
| 1,
q~1 =>
Lt
| 1,
q~0 =>
Lt
| 1, 1 =>
r
end.
Definition compare x y :=
compare_cont x y Eq.
Infix "?=" :=
compare (
at level 70,
no associativity) :
positive_scope.
Definition min p p´ :=
match p ?= p´ with
|
Lt |
Eq =>
p
|
Gt =>
p´
end.
Definition max p p´ :=
match p ?= p´ with
|
Lt |
Eq =>
p´
|
Gt =>
p
end.
Boolean equality and comparisons
Fixpoint eqb p q {
struct q} :=
match p,
q with
|
p~1,
q~1 =>
eqb p q
|
p~0,
q~0 =>
eqb p q
| 1, 1 =>
true
|
_,
_ =>
false
end.
Definition leb x y :=
match x ?= y with Gt =>
false |
_ =>
true end.
Definition ltb x y :=
match x ?= y with Lt =>
true |
_ =>
false end.
Infix "=?" :=
eqb (
at level 70,
no associativity) :
positive_scope.
Infix "<=?" :=
leb (
at level 70,
no associativity) :
positive_scope.
Infix "<?" :=
ltb (
at level 70,
no associativity) :
positive_scope.
A Square Root function for positive numbers
We procede by blocks of two digits : if p is written qbb'
then sqrt(p) will be sqrt(q)~0 or sqrt(q)~1.
For deciding easily in which case we are, we store the remainder
(as a mask, since it can be null).
Instead of copy-pasting the following code four times, we
factorize as an auxiliary function, with f and g being either
xO or xI depending of the initial digits.
NB: (sub_mask (g (f 1)) 4) is a hack, morally it's g (f 0).
Instead of the Euclid algorithm, we use here the Stein binary
algorithm, which is faster for this representation. This algorithm
is almost structural, but in the last cases we do some recursive
calls on subtraction, hence the need for a counter.
We'll show later that we need at most (log2(a.b)) loops
Generalized Gcd, also computing the division of a and b by the gcd
Fixpoint ggcdn (
n :
nat) (
a b :
positive) : (
positive*(positive*positive)) :=
match n with
|
O =>
(1
,(a,b))
|
S n =>
match a,
b with
| 1,
_ =>
(1
,(1
,b))
|
_, 1 =>
(1
,(a,1
))
|
a~0,
b~0 =>
let (
g,
p) :=
ggcdn n a b in
(g~0,p)
|
_,
b~0 =>
let ´
(g,(aa,bb)) :=
ggcdn n a b in
(g,(aa, bb~0))
|
a~0,
_ =>
let ´
(g,(aa,bb)) :=
ggcdn n a b in
(g,(aa~0, bb))
|
a´~1,
b´~1 =>
match a´ ?= b´ with
|
Eq =>
(a,(1
,1
))
|
Lt =>
let ´
(g,(ba,aa)) :=
ggcdn n (
b´-a´)
a in
(g,(aa, aa + ba~0))
|
Gt =>
let ´
(g,(ab,bb)) :=
ggcdn n (
a´-b´)
b in
(g,(bb + ab~0, bb))
end
end
end.
Definition ggcd (
a b:
positive) :=
ggcdn (
size_nat a + size_nat b)%
nat a b.
Local copies of the not-yet-available N.double and N.succ_double
Operation over bits.
Logical
or
Logical and
Logical diff
xor
Fixpoint lxor (
p q:
positive) :
N :=
match p,
q with
| 1, 1 =>
N0
| 1,
q~0 =>
Npos (
q~1)
| 1,
q~1 =>
Npos (
q~0)
|
p~0, 1 =>
Npos (
p~1)
|
p~0,
q~0 =>
Ndouble (
lxor p q)
|
p~0,
q~1 =>
Nsucc_double (
lxor p q)
|
p~1, 1 =>
Npos (
p~0)
|
p~1,
q~0 =>
Nsucc_double (
lxor p q)
|
p~1,
q~1 =>
Ndouble (
lxor p q)
end.
Shifts. NB: right shift of 1 stays at 1.
Checking whether a particular bit is set or not
Same, but with index in N
From binary positive numbers to Peano natural numbers
From Peano natural numbers to binary positive numbers
A version preserving positive numbers, and sending 0 to 1.