Module NumC
Require Import Ring.
Require Import ZArith.
Require Import QArith.
Require Import Qcanon.
Require Import Qround.
Require CoqAddOn.
Require List.
Require String.
Require Import OptionMonad.
Inductive trivialMulDiscr :=
IsZero |
IsUnit |
IsOppUnit |
Other.
Module Type BasicNumSig.
Parameter t:
Set.
Parameter z:
t.
Parameter u:
t.
Parameter add:
t ->
t ->
t.
Parameter mul:
t ->
t ->
t.
Parameter opp:
t ->
t.
Parameter sub:
t ->
t ->
t.
Parameter Ring:
ring_theory z u add mul sub opp eq.
Parameter ZNotU:
z <>
u.
Parameter Le:
t ->
t ->
Prop.
Parameter Lt:
t ->
t ->
Prop.
Parameter LtNotLe:
forall n1 n2 :
t,
Lt n1 n2 <-> ~
Le n2 n1.
Parameter LeNotLt:
forall n1 n2 :
t,
Le n1 n2 <-> ~
Lt n2 n1.
Parameter LtLe:
forall n1 n2:
t,
Lt n1 n2 ->
Le n1 n2.
Parameter eqDec:
forall n1 n2:
t, {
n1 =
n2} + {
n1 <>
n2}.
Parameter ltLeDec:
forall n1 n2:
t, {
Lt n1 n2} + {
Le n2 n1}.
Parameter dec:
forall n1 n2:
t, {
Lt n1 n2} + {
Lt n2 n1} + {
n1 =
n2}.
Parameter LeRefl:
forall n1:
t,
Le n1 n1.
Parameter LeLeEq:
forall n1 n2:
t,
Le n1 n2 /\
Le n2 n1 <->
n1 =
n2.
Parameter LeTrans:
forall n1 n2 n3:
t,
Le n1 n2 ->
Le n2 n3 ->
Le n1 n3.
Parameter LtTrans:
forall n1 n2 n3:
t,
Lt n1 n2 ->
Lt n2 n3 ->
Lt n1 n3.
Parameter LeLtTrans:
forall n1 n2 n3:
t,
Le n1 n2 ->
Lt n2 n3 ->
Lt n1 n3.
Parameter LtLeTrans:
forall n1 n2 n3:
t,
Lt n1 n2 ->
Le n2 n3 ->
Lt n1 n3.
Parameter isZero:
forall n:
t, {
n =
z} + {
n <>
z}.
Parameter mulDiscr:
t ->
trivialMulDiscr.
Parameter mulDiscr_correct:
forall n,
match (
mulDiscr n)
with
|
IsZero =>
n=
z
|
IsUnit =>
n=
u
|
IsOppUnit =>
n=
opp u
|
_ =>
True
end.
Parameter AddLeLe:
forall n1 n2 n3 n4:
t,
Le n1 n2 ->
Le n3 n4 ->
Le (
add n1 n3) (
add n2 n4).
Parameter AddLtLt:
forall n1 n2 n3 n4:
t,
Lt n1 n2 ->
Lt n3 n4 ->
Lt (
add n1 n3) (
add n2 n4).
Parameter AddLeLt:
forall n1 n2 n3 n4:
t,
Le n1 n2 ->
Lt n3 n4 ->
Lt (
add n1 n3) (
add n2 n4).
Parameter AddLtLe:
forall n1 n2 n3 n4:
t,
Lt n1 n2 ->
Le n3 n4 ->
Lt (
add n1 n3) (
add n2 n4).
Parameter MulZL:
forall n:
t,
mul z n =
z.
Parameter MulLe1:
forall n1 n2 n3:
t,
Le z n1 ->
Le n2 n3 ->
Le (
mul n1 n2) (
mul n1 n3).
Parameter MulLe2:
forall n1 n2 n3:
t,
Lt z n1 ->
Le (
mul n1 n2) (
mul n1 n3) ->
Le n2 n3.
Parameter MulLt:
forall n1 n2 n3:
t,
Lt z n1 -> (
Lt n2 n3 <->
Lt (
mul n1 n2) (
mul n1 n3)).
Parameter OppZ:
opp z =
z.
Parameter OppOpp:
forall n:
t,
opp (
opp n) =
n.
Parameter OppLt:
forall n1 n2:
t,
Lt n1 n2 <->
Lt (
opp n2) (
opp n1).
Parameter OppLe:
forall n1 n2:
t,
Le n1 n2 <->
Le (
opp n2) (
opp n1).
Parameter MulUR:
forall n1:
t,
mul n1 u =
n1.
Parameter MulAssoc:
forall n1 n2 n3:
t,
mul n1 (
mul n2 n3) =
mul (
mul n1 n2)
n3.
Parameter AddOppDistr:
forall n1 n2:
t,
add (
opp n1) (
opp n2) =
opp (
add n1 n2).
Parameter MulAddDistr:
forall n1 n2 n3:
t,
mul (
add n1 n2)
n3 =
add (
mul n1 n3) (
mul n2 n3).
Parameter MulOppDistrR:
forall n1 n2:
t,
mul n1 (
opp n2) =
opp (
mul n1 n2).
Parameter MulOppDistrL:
forall n1 n2:
t,
mul (
opp n1)
n2 =
opp (
mul n1 n2).
Parameter MulComm:
forall n1 n2:
t,
mul n1 n2 =
mul n2 n1.
Pretty-print in a human-readable way
Parameter pr:
t ->
String.string.
Pretty-print the inner structure of t
Parameter prRaw:
t ->
String.string.
Hint Rewrite <-
OppLt OppLe LeNotLt LtNotLe:
num.
Hint Resolve AddLeLe AddLeLt AddLtLt AddLtLe LeRefl:
num.
End BasicNumSig.
Inductive cmpT:
Set
:=
EqT |
LeT |
LtT.
Inductive cmpG:
Set
:=
Eq |
Le |
Lt |
Neq.
Definition cmpT2G (
c:
cmpT):
cmpG :=
match c with
|
EqT =>
Eq
|
LeT =>
Le
|
LtT =>
Lt
end.
Global Coercion cmpT2G:
cmpT >->
cmpG.
Definition cmpG2T (
cmp:
cmpG):
option cmpT :=
match cmp with
|
Eq =>
Some EqT
|
Le =>
Some LeT
|
Lt =>
Some LtT
|
Neq =>
None
end.
Module CmpTheory(
N:
BasicNumSig).
Add Ring NRing:
N.Ring.
Definition cmpDenote (
cmp:
cmpG):
N.t ->
N.t ->
Prop
:=
match cmp with
|
Eq =>
eq
|
Le =>
N.Le
|
Lt =>
N.Lt
|
Neq =>
fun x y =>
x <>
y
end.
Lemma cmp_add_preserve {
cmp n1 n2 n3}:
cmpDenote cmp n1 n2 ->
cmpDenote cmp (
N.add n1 n3) (
N.add n2 n3).
Proof.
destruct cmp;
simpl;
intros;
subst;
auto with num.
neq *)
intros X.
destruct H.
cutrewrite (
n1 =
N.add (
N.add n1 n3) (
N.opp n3));
try ring.
rewrite X;
ring.
Qed.
Local Hint Resolve cmp_add_preserve:
num.
Lemma cmp_zero_left {
cmp n1 n2}:
cmpDenote cmp n1 n2 ->
cmpDenote cmp N.z (
N.add n2 (
N.opp n1)).
Proof.
intros H;
cutrewrite (
N.z=
N.add n1 (
N.opp n1));
auto with num.
ring.
Qed.
Local Hint Resolve cmp_zero_left:
num.
Lemma cmp_transfo {
cmp n1 n2 n3 n4}:
cmpDenote cmp n1 n2 ->
n4 = (
N.add (
N.add n2 (
N.opp n1))
n3)->
cmpDenote cmp n3 n4.
Proof.
intros H H0;
subst.
cut (
n3=
N.add N.z n3).
intros X;
rewrite X at 1;
clear X.
auto with num.
ring.
Qed.
Ltac cmp_simplify :=
eapply cmp_transfo; [
eauto |
try ring ].
Lemma cmpG2T_correct cmp:
WHEN c <-
cmpG2T cmp THEN
forall v1 v2,
cmpDenote c v1 v2 <->
cmpDenote cmp v1 v2.
Proof.
destruct cmp; simpl; intuition.
Qed.
Lemma cmpDenote_dec (
cmp:
cmpG) (
n1 n2:
N.t): {
cmpDenote cmp n1 n2} + {~
cmpDenote cmp n1 n2}.
refine (
match cmp return {
cmpDenote cmp n1 n2} + {~
cmpDenote cmp n1 n2}
with
|
Eq =>
N.eqDec n1 n2
|
Le =>
match N.ltLeDec n2 n1 with
|
left pf =>
right (
proj1 (
N.LtNotLe n2 n1)
pf)
|
right pf =>
left pf
end
|
Lt =>
match N.ltLeDec n1 n2 with
|
left pf =>
left pf
|
right pf =>
right (
proj1 (
N.LeNotLt n2 n1)
pf)
end
|
Neq =>
match N.eqDec n1 n2 with
|
left pf =>
right (
fun H =>
H pf)
|
right pf =>
left pf
end
end).
Qed.
End CmpTheory.
Module Type NumSig := BasicNumSig <+ CmpTheory.
Module QBasicNum <: BasicNumSig.
Add Ring QcRing: Qcrt.
Definition t: Set := Qc.
Definition z: t := 0.
Definition u: t := 1.
Lemma ZNotU: z <> u.
discriminate.
Qed.
Definition Le: t -> t -> Prop := Qcle.
Definition Lt: t -> t -> Prop := Qclt.
Definition add: t -> t -> t := Qcplus.
Definition sub: t -> t -> t := Qcminus.
Definition mul: t -> t -> t := Qcmult.
Definition div: t -> t -> t := Qcdiv.
Definition opp: t -> t := Qcopp.
Definition inv: t -> t := Qcinv.
Definition eqDec: forall n1 n2: t, {n1 = n2} + {n1 <> n2}
:= Qc_eq_dec.
Definition ltLeDec: forall n1 n2: t, {Lt n1 n2} + {Le n2 n1}
:= Qclt_le_dec.
Definition dec: forall n1 n2: t, {Lt n1 n2} + {Lt n2 n1} + {n1 = n2}
:= Qc_dec.
Lemma zero_unique (n:t): (Qnum (this n))=0%Z -> n=z.
Proof.
intros; destruct n. qc. simpl in * |- *.
destruct this. simpl in * |- *. subst. vm_compute. auto.
Qed.
Program Definition isZero (n: t): {n = z} + {n <> z}
:= match (Qnum (this n)) with
| Z0 => left _
| _ => right _
end.
Obligation 1.
apply zero_unique. auto.
Qed.
Obligation 2.
intros H0. subst; apply H. vm_compute. auto.
Qed.
Lemma one_unique (n:t): Qnum (this n)=1%Z -> Qden (this n)=1%positive -> n=u.
Proof.
intros. destruct n. qc. simpl in * |- *.
destruct this. simpl in * |- *. subst. vm_compute. auto.
Qed.
Lemma opp_one_unique (n:t): Qnum (this n)=(-1)%Z -> Qden (this n)=1%positive -> n=(opp u).
Proof.
intros. destruct n. qc. simpl in * |- *.
destruct this. simpl in * |- *. subst. vm_compute. auto.
Qed.
Definition mulDiscr (n: t)
:= match (Qden (this n)) with
| 1%positive =>
match (Qnum (this n)) with
| 0%Z => IsZero
| 1%Z => IsUnit
| (-1)%Z => IsOppUnit
| _ => Other
end
| _ => Other
end.
Lemma mulDiscr_correct n:
match (mulDiscr n) with
| IsZero => n=z
| IsUnit => n=u
| IsOppUnit => n=opp u
| _ => True
end.
Proof.
Extraction Inline add sub mul div opp inv eqDec ltLeDec dec isZero mulDiscr.
Lemma LeRefl: forall n: t, Le n n.
Proof Qcle_refl.
Lemma LeLeEq: forall n1 n2: t, Le n1 n2 /\ Le n2 n1 <-> n1 = n2.
intros n1 n2.
split;
intro h.
- apply Qcle_antisym;
[exact (proj1 h)|exact (proj2 h)].
- subst n2.
split;
apply LeRefl.
Qed.
Lemma LtLe: forall n1 n2: t, Lt n1 n2 -> Le n1 n2.
Proof Qclt_le_weak.
Lemma LtNotLe: forall n1 n2: t, Lt n1 n2 <-> not (Le n2 n1).
intros n1 n2.
split;
intro h.
- apply Qclt_not_le.
assumption.
- apply Qcnot_le_lt.
assumption.
Qed.
Lemma LeNotLt: forall n1 n2: t, Le n1 n2 <-> not (Lt n2 n1).
intros n1 n2.
split;
intro h.
- apply Qcle_not_lt.
assumption.
- apply Qcnot_lt_le.
assumption.
Qed.
Lemma LeTrans: forall n1 n2 n3: t, Le n1 n2 -> Le n2 n3 -> Le n1 n3.
Proof Qcle_trans.
Lemma LtTrans: forall n1 n2 n3: t, Lt n1 n2 -> Lt n2 n3 -> Lt n1 n3.
Proof Qclt_trans.
Lemma LeLtTrans: forall n1 n2 n3: t, Le n1 n2 -> Lt n2 n3 -> Lt n1 n3.
Proof Qcle_lt_trans.
Lemma LtLeTrans: forall n1 n2 n3: t, Lt n1 n2 -> Le n2 n3 -> Lt n1 n3.
Proof Qclt_le_trans.
Lemma SplitEq: forall n1 n2: t,
Le n1 n2 -> Le (opp n1) (opp n2) -> n1 = n2.
unfold opp; intros n1 n2 Hle HleN.
apply Qcle_antisym;
[ | apply Qcopp_le_compat in HleN;
rewrite (Qcopp_involutive n2), (Qcopp_involutive n1) in HleN ];
assumption.
Qed.
Lemma MulAddDistrL: forall n1 n2 n3: t,
mul (add n1 n2) n3 = add (mul n1 n3) (mul n2 n3).
exact Qcmult_plus_distr_l.
Qed.
Lemma AddAssoc: forall n1 n2 n3: t,
add n1 (add n2 n3) = add (add n1 n2) n3.
Proof Qcplus_assoc.
Lemma AddComm: forall n1 n2: t, add n1 n2 = add n2 n1.
Proof Qcplus_comm.
Lemma AddZL: forall n: t, add z n = n.
Proof Qcplus_0_l.
Lemma AddZR: forall n: t, add n z = n.
Proof Qcplus_0_r.
Lemma AddOpp: forall n: t, add n (opp n) = z.
Proof Qcplus_opp_r.
Lemma AddOppDistr: forall n1 n2: t, add (opp n1) (opp n2) = opp (add n1 n2).
unfold t, add, opp.
intros.
ring.
Qed.
Lemma MulUL: forall n: t, mul u n = n.
Proof Qcmult_1_l.
Lemma MulUR: forall n1: t, mul n1 u = n1.
Proof Qcmult_1_r.
Lemma MulZL: forall n: t, mul z n = z.
intro; compute;
apply Qc_is_canon; reflexivity.
Qed.
Lemma MulAssoc: forall n1 n2 n3: t,
mul n1 (mul n2 n3) = mul (mul n1 n2) n3.
Proof Qcmult_assoc.
Lemma MulComm: forall n1 n2: t, mul n1 n2 = mul n2 n1.
Proof Qcmult_comm.
Lemma MulAddDistr: forall n1 n2 n3: t, mul (add n1 n2) n3 = add (mul n1 n3) (mul n2 n3).
Proof Qcmult_plus_distr_l.
Lemma MulOppDistrR: forall n1 n2: t, mul n1 (opp n2) = opp (mul n1 n2).
unfold t, mul, opp.
intros.
ring.
Qed.
Lemma MulOppDistrL: forall n1 n2: t, mul (opp n1) n2 = opp (mul n1 n2).
unfold t, mul, opp.
intros.
ring.
Qed.
Lemma SubAdd: forall n1 n2: t, sub n1 n2 = add n1 (opp n2).
intros; unfold sub, add, opp, Qcminus; trivial.
Qed.
Lemma AddLeLe: forall n1 n2 n3 n4: t,
Le n1 n2 -> Le n3 n4 -> Le (add n1 n3) (add n2 n4).
Proof Qcplus_le_compat.
Lemma AddLtLt: forall n1 n2 n3 n4: t,
Lt n1 n2 -> Lt n3 n4 -> Lt (add n1 n3) (add n2 n4).
Proof CoqAddOn.Qc.Qcplus_lt_compat.
Lemma AddEqLt: forall n1 n2 n3 n4: t,
n1 = n2 -> Lt n3 n4 -> Lt (add n1 n3) (add n2 n4).
Proof CoqAddOn.Qc.Qcplus_eqlt_compat.
Lemma AddLeLt: forall n1 n2 n3 n4: t,
Le n1 n2 -> Lt n3 n4 -> Lt (add n1 n3) (add n2 n4).
intros n1 n2 n3 n4 h; unfold Le in h;
apply Qcle_lt_or_eq in h; destruct h as [h | h];
[ exact (AddLtLt _ _ _ _ h) | exact (AddEqLt _ _ _ _ (Qc_is_canon _ _ h))].
Qed.
Lemma AddLtLe: forall n1 n2 n3 n4: t,
Lt n1 n2 -> Le n3 n4 -> Lt (add n1 n3) (add n2 n4).
intros.
rewrite (AddComm n1 n3).
rewrite (AddComm n2 n4).
apply AddLeLt;
assumption.
Qed.
Hint Resolve AddLeLe AddLeLt AddLtLt AddLtLe SplitEq LeRefl: num.
Lemma MulLe1: forall n1 n2 n3: t,
Le z n1 -> Le n2 n3 -> Le (mul n1 n2) (mul n1 n3).
intros n1 n2 n3 h1 h2.
rewrite (MulComm n1 n2), (MulComm n1 n3).
apply Qcmult_le_compat_r;
assumption.
Qed.
Lemma MulLe2: forall n1 n2 n3: t,
Lt z n1 -> Le (mul n1 n2) (mul n1 n3) -> Le n2 n3.
intros n1 n2 n3 h1 h2.
rewrite (MulComm n1 n2), (MulComm n1 n3) in h2.
apply Qcmult_lt_0_le_reg_r with (z := n1);
assumption.
Qed.
Lemma MulLt: forall n1 n2 n3: t,
Lt z n1 -> (Lt n2 n3 <-> Lt (mul n1 n2) (mul n1 n3)).
intros n1 n2 n3 h1.
rewrite (MulComm n1 n2), (MulComm n1 n3).
split;
intro h2.
- unfold Lt, mul, Qcmult.
apply (proj1 (CoqAddOn.Qc.QcQLt _ _)).
apply Qmult_lt_r;
assumption.
- unfold Lt, mul, Qcmult in h2.
apply (proj2 (CoqAddOn.Qc.QcQLt _ _)) in h2.
apply Qmult_lt_r in h2;
assumption.
Qed.
Lemma OppZ: opp z = z.
reflexivity.
Qed.
Lemma OppOpp: forall n: t, opp (opp n) = n.
Proof Qcopp_involutive.
Lemma OppLe: forall n1 n2: t, Le n1 n2 <-> Le (opp n2) (opp n1).
intros n1 n2.
split; [exact (Qcopp_le_compat n1 n2) |].
intro h.
apply (AddLeLe n1 n1 (opp n2) (opp n1)) in h; auto with num.
eapply (AddLeLe n2 n2) in h; auto with num.
unfold add in h.
rewrite (Qcplus_comm n1 (opp n2)) in h.
rewrite (Qcplus_assoc n2 (opp n2) n1) in h.
repeat rewrite Qcplus_opp_r in h.
rewrite Qcplus_0_l ,Qcplus_0_r in h.
assumption.
Qed.
Lemma OppLt: forall n1 n2: t, Lt n1 n2 <-> Lt (opp n2) (opp n1).
Proof CoqAddOn.Qc.Qcopp_lt_compat.
Definition Ring := mk_rt z u add mul sub opp eq AddZL AddComm AddAssoc
MulUL MulComm MulAssoc MulAddDistrL SubAdd AddOpp.
Import List String.
Local Open Scope string_scope.
Definition pr: t -> string
:= fun q =>
let nstr := CoqAddOn.zPr (Qnum (this q)) in
let dstr := CoqAddOn.posPr (Qden (this q)) in
CoqAddOn.sprintf "(%s/%s)" (cons nstr (cons dstr nil)).
Definition prRaw: t -> string
:= fun q =>
let nstr := CoqAddOn.zPrRaw (Qnum (this q)) in
let dstr := CoqAddOn.posPrRaw (Qden (this q)) in
CoqAddOn.sprintf "{num = %s; den = %s}" (cons nstr (cons dstr nil)).
Lemma LtLeAbsurd: forall n1 n2: t, Lt n1 n2 -> Le n2 n1 -> False.
intros n1 n2; case (LtNotLe n1 n2); intuition.
Qed.
Hint Resolve LtLeAbsurd LeTrans LtLe LtLeTrans LeLtTrans: num.
Hint Rewrite SubAdd: num.
Hint Rewrite <- OppLt OppLe LeNotLt LtNotLe: num.
End QBasicNum.
Module QNum <: NumSig := QBasicNum <+ CmpTheory.
Import ZArith_base.
Module ZBasicNum <: BasicNumSig.
Local Open Scope Z_scope.
Definition t: Set := Z.
Definition z: t := 0.
Definition u: t := 1.
Lemma ZNotU: z <> u.
discriminate.
Qed.
Definition Le: t -> t -> Prop
:= fun n1 n2 => n1 <= n2.
Definition Lt: t -> t -> Prop
:= fun n1 n2 => n1 < n2.
Lemma LtNotLe: forall n1 n2 : t, Lt n1 n2 <-> ~ Le n2 n1.
intros n1 n2.
split;
intro h.
- apply Zlt_not_le.
assumption.
- apply Znot_ge_lt.
intro hcontr.
apply h, Z.ge_le.
assumption.
Qed.
Lemma LeNotLt: forall n1 n2 : t, Le n1 n2 <-> ~ Lt n2 n1.
intros n1 n2.
split;
intro h.
- apply Zle_not_lt.
assumption.
- apply Znot_gt_le.
intro hcontr.
apply h, Z.gt_lt.
assumption.
Qed.
Lemma LtLe: forall n1 n2: t, Lt n1 n2 -> Le n1 n2.
Proof Zlt_le_weak.
Definition eqDec: forall n1 n2: t, {n1 = n2} + {n1 <> n2}
:= Z.eq_dec.
Definition ltLeDec: forall n1 n2: t, {Lt n1 n2} + {Le n2 n1}
:= ZArith_dec.Z_lt_le_dec.
Definition dec: forall n1 n2: t, {Lt n1 n2} + {Lt n2 n1} + {n1 = n2}
:= ZArith_dec.Z_dec'.
Lemma LeRefl: forall n1: t, Le n1 n1.
Proof Z.le_refl.
Lemma LeLeEq: forall n1 n2: t, Le n1 n2 /\ Le n2 n1 <-> n1 = n2.
intros n1 n2.
split;
intro h.
- apply Z.le_antisymm;
[exact (proj1 h)|exact (proj2 h)].
- subst n2.
split;
apply LeRefl.
Qed.
Lemma LeTrans: forall n1 n2 n3: t, Le n1 n2 -> Le n2 n3 -> Le n1 n3.
Proof Z.le_trans.
Lemma LtTrans: forall n1 n2 n3: t, Lt n1 n2 -> Lt n2 n3 -> Lt n1 n3.
Proof Z.lt_trans.
Lemma LeLtTrans: forall n1 n2 n3: t, Le n1 n2 -> Lt n2 n3 -> Lt n1 n3.
Proof Z.le_lt_trans.
Lemma LtLeTrans: forall n1 n2 n3: t, Lt n1 n2 -> Le n2 n3 -> Lt n1 n3.
Proof Z.lt_le_trans.
Definition add: t -> t -> t
:= fun n1 n2 => n1 + n2.
Lemma AddLeLe: forall n1 n2 n3 n4: t,
Le n1 n2 -> Le n3 n4 -> Le (add n1 n3) (add n2 n4).
Proof Z.add_le_mono.
Lemma AddLtLt: forall n1 n2 n3 n4: t,
Lt n1 n2 -> Lt n3 n4 -> Lt (add n1 n3) (add n2 n4).
Proof Z.add_lt_mono.
Lemma AddLeLt: forall n1 n2 n3 n4: t,
Le n1 n2 -> Lt n3 n4 -> Lt (add n1 n3) (add n2 n4).
Proof Z.add_le_lt_mono.
Lemma AddLtLe: forall n1 n2 n3 n4: t,
Lt n1 n2 -> Le n3 n4 -> Lt (add n1 n3) (add n2 n4).
Proof Z.add_lt_le_mono.
Definition mul: t -> t -> t
:= fun n1 n2 => n1 * n2.
Lemma MulZL: forall n: t, mul z n = z.
Proof Z.mul_0_l.
Lemma MulLe1: forall n1 n2 n3: t,
(Le z n1) -> Le n2 n3 -> Le (mul n1 n2) (mul n1 n3).
intros n1 n2 n3 h1 h2.
apply Zmult_le_compat_l;
assumption.
Qed.
Lemma MulLe2: forall n1 n2 n3: t,
Lt z n1 -> Le (mul n1 n2) (mul n1 n3) -> Le n2 n3.
intros n1 n2 n3 h1 h2.
apply Zmult_le_reg_r with (p := n1).
- apply Z.lt_gt.
assumption.
- unfold mul in h2.
rewrite (Z.mul_comm n1 n2), (Z.mul_comm n1 n3) in h2.
assumption.
Qed.
Lemma MulLt: forall n1 n2 n3: t,
Lt z n1 -> (Lt n2 n3 <-> Lt (mul n1 n2) (mul n1 n3)).
intros n1 n2 n3 h1.
split;
intro h2.
- apply Zmult_lt_compat_l;
assumption.
- apply Zmult_lt_reg_r with (p := n1);
unfold mul in h2;
[idtac|rewrite (Z.mul_comm n1 n2), (Z.mul_comm n1 n3) in h2];
assumption.
Qed.
Definition opp: t -> t
:= fun n1 => - n1.
Lemma OppZ: opp z = z.
reflexivity.
Qed.
Lemma OppOpp: forall n: t, opp (opp n) = n.
Proof Z.opp_involutive.
Lemma OppLt: forall n1 n2: t, Lt n1 n2 <-> Lt (opp n2) (opp n1).
intros n1 n2.
unfold Lt, Z.lt.
rewrite Z.compare_opp.
reflexivity.
Qed.
Lemma OppLe: forall n1 n2: t, Le n1 n2 <-> Le (opp n2) (opp n1).
intros n1 n2.
unfold Le, Z.le.
rewrite Z.compare_opp.
reflexivity.
Qed.
Lemma AddOpp: forall n: t, add n (opp n) = z.
Proof Zplus_opp_r.
Lemma MulUR: forall n1: t, mul n1 u = n1.
Proof Z.mul_1_r.
Lemma MulAssoc: forall n1 n2 n3: t, mul n1 (mul n2 n3) = mul (mul n1 n2) n3.
Proof Z.mul_assoc.
Lemma MulAddDistr: forall n1 n2 n3: t, mul (add n1 n2) n3 = add (mul n1 n3) (mul n2 n3).
Proof Z.mul_add_distr_r.
Lemma AddOppDistr: forall n1 n2: t, add (opp n1) (opp n2) = opp (add n1 n2).
intros n1 n2.
rewrite Z.opp_add_distr.
reflexivity.
Qed.
Lemma MulOppDistrR: forall n1 n2: t, mul n1 (opp n2) = opp (mul n1 n2).
Proof Z.mul_opp_r.
Lemma MulOppDistrL: forall n1 n2: t, mul (opp n1) n2 = opp (mul n1 n2).
Proof Z.mul_opp_l.
Definition pr: t -> String.string
:= fun z => CoqAddOn.zPr z.
Definition prRaw: t -> String.string
:= fun z => CoqAddOn.zPrRaw z.
Definition sub: t -> t -> t := Zminus.
Lemma SubAdd: forall n1 n2: t, sub n1 n2 = add n1 (opp n2).
intros; unfold sub, add, opp, Zminus; trivial.
Qed.
Definition Ring := mk_rt z u add mul sub opp eq Zplus_0_l Zplus_comm Zplus_assoc
Zmult_1_l Zmult_comm MulAssoc Zmult_plus_distr_l SubAdd AddOpp.
Hint Rewrite SubAdd: num.
Program Definition isZero (n: t): {n = z} + {n <> z}
:= match n with
| Z0 => left _
| _ => right _
end.
Definition mulDiscr (n: t)
:= match n with
| 0%Z => IsZero
| 1%Z => IsUnit
| (-1)%Z => IsOppUnit
| _ => Other
end.
Lemma mulDiscr_correct n:
match (mulDiscr n) with
| IsZero => n=z
| IsUnit => n=u
| IsOppUnit => n=opp u
| _ => True
end.
Proof.
unfold mulDiscr;
destruct n;
simpl;
auto;
destruct p;
simpl;
auto.
Qed.
Extraction Inline add sub mul opp eqDec ltLeDec dec isZero mulDiscr.
Hint Resolve AddLeLe AddLeLt AddLtLt AddLtLe LeRefl: num.
Definition MulComm := Z.mul_comm.
Ltac simplify := unfold z, u, add, sub, mul, opp, Le, Lt in * |- *; omega || auto with zarith.
End ZBasicNum.
Module ZNum <: NumSig := ZBasicNum <+ CmpTheory.
Module ZtoQ.
Lemma PosGcdOne: forall p: positive, Pos.gcd p 1%positive = 1%positive.
intro p.
unfold Pos.gcd.
generalize (Pos.size_nat p + Pos.size_nat 1)%nat.
intro n.
unfold Pos.gcdn.
destruct n;
[idtac|destruct p];
reflexivity.
Qed.
Lemma ZGcdOne: forall z: Z, Z.gcd z 1%Z = 1%Z.
intro z.
unfold Z.gcd.
destruct z;
try rewrite PosGcdOne;
reflexivity.
Qed.
Lemma ZGgcdOne: forall z: Z, snd (Z.ggcd z 1%Z) = (z, 1%Z).
intro z.
assert (pf1 := Z.ggcd_gcd z 1%Z).
assert (pf2 := Z.ggcd_correct_divisors z 1%Z).
rewrite (surjective_pairing (Z.ggcd z 1%Z)) in pf2.
rewrite (surjective_pairing (snd (Z.ggcd z 1%Z))) in pf2.
rewrite pf1, ZGcdOne in pf2.
do 2 rewrite Z.mul_1_l in pf2.
rewrite (surjective_pairing (snd (Z.ggcd z 1%Z))).
rewrite <- (proj1 pf2), <- (proj2 pf2).
reflexivity.
Qed.
Lemma QredOne: forall z: Z, Qred (z # 1%positive) = z # 1%positive.
intro z.
unfold Qred.
rewrite ZGgcdOne.
reflexivity.
Qed.
Definition ofZ: ZNum.t -> QNum.t
:= fun z => Qcmake (QArith_base.inject_Z z) (QredOne _).
Extraction Inline ofZ.
Lemma ofZ_zero: ofZ ZNum.z = QNum.z.
Proof.
Lemma ofZ_one: ofZ ZNum.u = QNum.u.
Proof.
Hint Rewrite ofZ_zero ofZ_one: num.
Lemma EqCommutes: forall z1 z2: ZNum.t, z1 = z2 <-> (ofZ z1) = (ofZ z2).
intros z1 z2.
split;
intro h;
[rewrite h|inversion h];
reflexivity.
Qed.
Ltac solveOrder
:= fun a b =>
split;
unfold a, b;
simpl;
intro h;
[do 2 rewrite Z.mul_1_r|do 2 rewrite Z.mul_1_r in h];
assumption.
Lemma LeCommutes: forall z1 z2: ZNum.t,
ZNum.Le z1 z2 <-> QNum.Le (ofZ z1) (ofZ z2).
intros z1 z2.
unfold ZNum.Le, QNum.Le, ofZ.
solveOrder Qcle Qle.
Qed.
Lemma LtCommutes: forall z1 z2: ZNum.t,
ZNum.Lt z1 z2 <-> QNum.Lt (ofZ z1) (ofZ z2).
intros z1 z2.
unfold ZNum.Lt, QNum.Lt, ofZ.
solveOrder Qclt Qlt.
Qed.
Lemma AddCommutes: forall z1 z2: ZNum.t,
ofZ (ZNum.add z1 z2) = QNum.add (ofZ z1) (ofZ z2).
intros z1 z2.
apply Qc_is_canon.
simpl.
rewrite ZGgcdOne.
do 2 rewrite Z.mul_1_r.
simpl.
reflexivity.
Qed.
Lemma MulCommutes: forall z1 z2: ZNum.t,
ofZ (ZNum.mul z1 z2) = QNum.mul (ofZ z1) (ofZ z2).
intros z1 z2.
apply Qc_is_canon.
simpl.
rewrite ZGgcdOne.
reflexivity.
Qed.
Lemma OppCommutes: forall z: ZNum.t,
ofZ (ZNum.opp z) = QNum.opp (ofZ z).
intros z.
apply Qc_is_canon.
simpl.
rewrite ZGgcdOne.
reflexivity.
Qed.
Hint Rewrite EqCommutes LeCommutes LtCommutes LtCommutes AddCommutes MulCommutes OppCommutes: num.
Lemma isInZ_test q: Qden(this(q))=1%positive -> q=ofZ(Qnum(this(q))).
Proof.
intros H; qc. simpl in * |- *.
generalize H; clear H canon.
case this. simpl; intros; subst; simpl. reflexivity.
Qed.
Local Hint Resolve isInZ_test.
Program Definition isInZ (q: QNum.t): option (q=ofZ(Qnum(this(q)))) :=
match Qden(this(q)) with
| 1%positive => Some _
| _ => None
end.
Definition floor: QNum.t -> ZNum.t
:= fun n => Qfloor n.
Lemma FloorZ: forall z: ZNum.t, floor (ofZ z) = z.
apply Qfloor_Z.
Qed.
Lemma FloorLeZ: forall n1 n2: QNum.t, QNum.Le n1 n2 -> ZNum.Le (floor n1) (floor n2).
intros n1 n2 h.
apply Qfloor_resp_le.
assumption.
Qed.
Definition ceil: QNum.t -> ZNum.t
:= fun n => Qceiling n.
Lemma CeilZ: forall z: ZNum.t, ceil (ofZ z) = z.
apply Qceiling_Z.
Qed.
Lemma CeilLeZ: forall n1 n2: QNum.t, QNum.Le n1 n2 -> ZNum.Le (ceil n1) (ceil n2).
intros n1 n2 h.
apply Qceiling_resp_le.
assumption.
Qed.
Lemma FloorQLt: forall (q1 q2 : QNum.t),
QNum.Lt q1 q2 -> QNum.Lt (ofZ (floor q1)) q2.
intros q1 q2 h.
apply (QNum.LeLtTrans _ q1 _).
apply Qfloor_le.
assumption.
Qed.
Lemma CeilQLt: forall (q1 q2: QNum.t),
QNum.Lt q1 q2 -> QNum.Lt q1 (ofZ (ceil q2)).
intros q1 q2 h.
apply (QNum.LtLeTrans _ q2 _).
assumption.
apply Qle_ceiling.
Qed.
Lemma CeilQLe: forall (q1 q2: QNum.t),
QNum.Le q1 q2 -> QNum.Le q1 (ofZ (ceil q2)).
intros q1 q2 h.
apply (QNum.LeTrans _ q2 _).
assumption.
apply Qle_ceiling.
Qed.
Lemma Ceil_exact q: q=ofZ(Qnum(this(q))) -> (ceil q)=Qnum(this(q)).
Proof.
intros H;
rewrite H at 1.
rewrite CeilZ;
auto.
Qed.
Lemma Floor_exact q: q=ofZ(Qnum(this(q))) -> (floor q)=Qnum(this(q)).
Proof.
intros H;
rewrite H at 1.
rewrite FloorZ;
auto.
Qed.
End ZtoQ.