├── .github └── workflows │ └── docker-action.yml ├── .gitignore ├── CeCILL-B ├── Make ├── Make.test-suite ├── Makefile ├── README.md ├── _CoqProject ├── coq-mathcomp-zify.opam ├── examples ├── boolean.v ├── divmod.v ├── test_algebra.v ├── test_ssreflect.v └── zagier.v ├── meta.yml └── theories ├── ssrZ.v ├── zify.v ├── zify_algebra.v └── zify_ssreflect.v /.github/workflows/docker-action.yml: -------------------------------------------------------------------------------- 1 | # This file was generated from `meta.yml`, please do not edit manually. 2 | # Follow the instructions on https://github.com/coq-community/templates to regenerate. 3 | name: Docker CI 4 | 5 | on: 6 | push: 7 | branches: 8 | - master 9 | pull_request: 10 | branches: 11 | - '**' 12 | 13 | jobs: 14 | build: 15 | # the OS must be GNU/Linux to be able to use the docker-coq-action 16 | runs-on: ubuntu-latest 17 | strategy: 18 | matrix: 19 | image: 20 | - 'mathcomp/mathcomp:2.0.0-coq-8.16' 21 | - 'mathcomp/mathcomp:2.0.0-coq-8.17' 22 | - 'mathcomp/mathcomp:2.0.0-coq-8.18' 23 | - 'mathcomp/mathcomp:2.1.0-coq-8.16' 24 | - 'mathcomp/mathcomp:2.1.0-coq-8.17' 25 | - 'mathcomp/mathcomp:2.1.0-coq-8.18' 26 | - 'mathcomp/mathcomp:2.2.0-coq-8.16' 27 | - 'mathcomp/mathcomp:2.2.0-coq-8.17' 28 | - 'mathcomp/mathcomp:2.2.0-coq-8.18' 29 | - 'mathcomp/mathcomp:2.2.0-coq-8.19' 30 | - 'mathcomp/mathcomp:2.2.0-coq-8.20' 31 | - 'mathcomp/mathcomp:2.3.0-coq-8.18' 32 | - 'mathcomp/mathcomp:2.3.0-coq-8.19' 33 | - 'mathcomp/mathcomp:2.3.0-coq-8.20' 34 | - 'mathcomp/mathcomp:2.4.0-coq-8.19' 35 | - 'mathcomp/mathcomp:2.4.0-coq-8.20' 36 | - 'mathcomp/mathcomp:2.4.0-rocq-prover-9.0' 37 | - 'mathcomp/mathcomp:2.4.0-rocq-prover-dev' 38 | - 'mathcomp/mathcomp-dev:coq-8.20' 39 | - 'mathcomp/mathcomp-dev:rocq-prover-9.0' 40 | - 'mathcomp/mathcomp-dev:rocq-prover-dev' 41 | fail-fast: false 42 | steps: 43 | - uses: actions/checkout@v4 44 | - uses: coq-community/docker-coq-action@v1 45 | with: 46 | opam_file: 'coq-mathcomp-zify.opam' 47 | custom_image: ${{ matrix.image }} 48 | export: 'OPAMWITHTEST' 49 | env: 50 | OPAMWITHTEST: true 51 | 52 | # See also: 53 | # https://github.com/coq-community/docker-coq-action#readme 54 | # https://github.com/erikmd/docker-coq-github-action-demo 55 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.d 2 | *.vo 3 | *.vio 4 | *.vos 5 | *.vok 6 | *.cm* 7 | *~ 8 | *.glob 9 | *.aux 10 | *.a 11 | *.o 12 | Make*.coq 13 | Make*.coq.bak 14 | Make*.coq.conf 15 | *# 16 | .lia.cache 17 | .nia.cache 18 | -------------------------------------------------------------------------------- /CeCILL-B: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/math-comp/mczify/d4ec06f83fdadaac59734557803094a3cd63f3d0/CeCILL-B -------------------------------------------------------------------------------- /Make: -------------------------------------------------------------------------------- 1 | theories/ssrZ.v 2 | theories/zify_ssreflect.v 3 | theories/zify_algebra.v 4 | theories/zify.v 5 | 6 | -R theories mathcomp.zify 7 | -arg -w -arg -notation-overridden 8 | -------------------------------------------------------------------------------- /Make.test-suite: -------------------------------------------------------------------------------- 1 | examples/boolean.v 2 | examples/divmod.v 3 | examples/zagier.v 4 | examples/test_ssreflect.v 5 | examples/test_algebra.v 6 | 7 | -R theories mathcomp.zify 8 | -I . 9 | -arg -w -arg -notation-overridden 10 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # KNOWNTARGETS will not be passed along to CoqMakefile 2 | KNOWNTARGETS := Makefile.coq Makefile.test-suite.coq test-suite \ 3 | clean cleanall distclean 4 | # KNOWNFILES will not get implicit targets from the final rule, and so 5 | # depending on them won't invoke the submake 6 | # Warning: These files get declared as PHONY, so any targets depending 7 | # on them always get rebuilt 8 | KNOWNFILES := Makefile Make Make.test-suite 9 | 10 | .DEFAULT_GOAL := invoke-coqmakefile 11 | 12 | COQMAKEFILE = $(COQBIN)coq_makefile 13 | COQMAKE = $(MAKE) --no-print-directory -f Makefile.coq 14 | COQMAKE_TESTSUITE = $(MAKE) --no-print-directory -f Makefile.test-suite.coq 15 | 16 | Makefile.coq: Makefile Make 17 | $(COQMAKEFILE) -f Make -o Makefile.coq 18 | 19 | Makefile.test-suite.coq: Makefile Make.test-suite 20 | $(COQMAKEFILE) -f Make.test-suite -o Makefile.test-suite.coq 21 | 22 | invoke-coqmakefile: Makefile.coq 23 | $(COQMAKE) $(filter-out $(KNOWNTARGETS),$(MAKECMDGOALS)) 24 | 25 | test-suite: Makefile.test-suite.coq invoke-coqmakefile 26 | $(COQMAKE_TESTSUITE) 27 | 28 | clean:: 29 | @if [ -f Makefile.coq ]; then $(COQMAKE) clean; fi 30 | @if [ -f Makefile.test-suite.coq ]; then $(COQMAKE_TESTSUITE) clean; fi 31 | 32 | cleanall:: 33 | @if [ -f Makefile.coq ]; then $(COQMAKE) cleanall; fi 34 | @if [ -f Makefile.test-suite.coq ]; then $(COQMAKE_TESTSUITE) cleanall; fi 35 | 36 | distclean:: cleanall 37 | rm -f Makefile.coq Makefile.coq.conf 38 | rm -f Makefile.test-suite.coq Makefile.test-suite.coq.conf 39 | 40 | .PHONY: invoke-coqmakefile $(KNOWNFILES) 41 | 42 | #################################################################### 43 | ## Your targets here ## 44 | #################################################################### 45 | 46 | # This should be the last rule, to handle any targets not declared above 47 | %: invoke-coqmakefile 48 | @true 49 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 5 | # Mczify 6 | 7 | [![Docker CI][docker-action-shield]][docker-action-link] 8 | 9 | [docker-action-shield]: https://github.com/math-comp/mczify/actions/workflows/docker-action.yml/badge.svg?branch=master 10 | [docker-action-link]: https://github.com/math-comp/mczify/actions/workflows/docker-action.yml 11 | 12 | 13 | 14 | 15 | This small library enables the use of the Micromega arithmetic solvers of Coq 16 | for goals stated with the definitions of the Mathematical Components library 17 | by extending the zify tactic. 18 | 19 | ## Meta 20 | 21 | - Author(s): 22 | - Kazuhiko Sakaguchi (initial) 23 | - License: [CeCILL-B Free Software License Agreement](CeCILL-B) 24 | - Compatible Coq versions: 8.16 or later 25 | - Additional dependencies: 26 | - [MathComp](https://math-comp.github.io) ssreflect 2.0 or later 27 | - [MathComp](https://math-comp.github.io) algebra 28 | - Coq namespace: `mathcomp.zify` 29 | - Related publication(s): none 30 | 31 | ## Building and installation instructions 32 | 33 | The easiest way to install the latest released version of Mczify 34 | is via [OPAM](https://opam.ocaml.org/doc/Install.html): 35 | 36 | ```shell 37 | opam repo add coq-released https://coq.inria.fr/opam/released 38 | opam install coq-mathcomp-zify 39 | ``` 40 | 41 | To instead build and install manually, do: 42 | 43 | ``` shell 44 | git clone https://github.com/math-comp/mczify.git 45 | cd mczify 46 | make # or make -j 47 | make install 48 | ``` 49 | 50 | 51 | ## File contents 52 | 53 | - `zify_ssreflect.v`: Z-ification instances for the `coq-mathcomp-ssreflect` 54 | library 55 | - `zify_algebra.v`: Z-ification instances for the `coq-mathcomp-algebra` 56 | library 57 | - `zify.v`: re-exports all the Z-ification instances 58 | - `ssrZ.v`: provides a minimal facility for reasoning about `Z` and relating 59 | `Z` and `int` 60 | -------------------------------------------------------------------------------- /_CoqProject: -------------------------------------------------------------------------------- 1 | -R theories mathcomp.zify 2 | -arg -w -arg -notation-overridden 3 | -------------------------------------------------------------------------------- /coq-mathcomp-zify.opam: -------------------------------------------------------------------------------- 1 | # This file was generated from `meta.yml`, please do not edit manually. 2 | # Follow the instructions on https://github.com/coq-community/templates to regenerate. 3 | 4 | opam-version: "2.0" 5 | maintainer: "kazuhiko.sakaguchi@inria.fr" 6 | version: "dev" 7 | 8 | homepage: "https://github.com/math-comp/mczify" 9 | dev-repo: "git+https://github.com/math-comp/mczify.git" 10 | bug-reports: "https://github.com/math-comp/mczify/issues" 11 | license: "CECILL-B" 12 | 13 | synopsis: "Micromega tactics for Mathematical Components" 14 | description: """ 15 | This small library enables the use of the Micromega arithmetic solvers of Coq 16 | for goals stated with the definitions of the Mathematical Components library 17 | by extending the zify tactic.""" 18 | 19 | build: [make "-j%{jobs}%"] 20 | run-test: [make "-j%{jobs}%" "test-suite"] 21 | install: [make "install"] 22 | depends: [ 23 | "coq" {>= "8.16"} 24 | "coq-mathcomp-ssreflect" {>= "2.0"} 25 | "coq-mathcomp-algebra" 26 | ] 27 | 28 | tags: [ 29 | "logpath:mathcomp.zify" 30 | ] 31 | authors: [ 32 | "Kazuhiko Sakaguchi" 33 | ] 34 | -------------------------------------------------------------------------------- /examples/boolean.v: -------------------------------------------------------------------------------- 1 | From mathcomp Require Import all_ssreflect zify. 2 | 3 | Set Implicit Arguments. 4 | Unset Strict Implicit. 5 | Unset Printing Implicit Defensive. 6 | 7 | Lemma odd_add (n m : nat) : odd (m + n) = odd m (+) odd n. 8 | Proof. lia. Qed. 9 | -------------------------------------------------------------------------------- /examples/divmod.v: -------------------------------------------------------------------------------- 1 | From mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq path. 2 | From mathcomp Require Import div choice fintype tuple finfun bigop finset prime. 3 | From mathcomp Require Import binomial ssralg countalg ssrnum ssrint rat intdiv. 4 | From mathcomp Require Import zify. 5 | 6 | Set Implicit Arguments. 7 | Unset Strict Implicit. 8 | Unset Printing Implicit Defensive. 9 | 10 | Lemma dvdz_lcm_6_4 (m : int) : (6 %| m -> 4 %| m -> 12 %| m)%Z. 11 | Proof. lia. Qed. 12 | 13 | Lemma dvdz_lcm_6_4' (m : int) : (6 %| m)%Z && (4 %| m)%Z = (12 %| m)%Z. 14 | Proof. lia. Qed. 15 | 16 | Lemma divzMA_ge0 (m n p : int) : 17 | (0 <= n)%R -> (m %/ (n * p))%Z = ((m %/ n) %/ p)%Z. 18 | Proof. nia. Qed. 19 | -------------------------------------------------------------------------------- /examples/test_algebra.v: -------------------------------------------------------------------------------- 1 | From Coq Require Import BinInt Zify. 2 | From mathcomp Require Import all_ssreflect all_algebra zify ssrZ. 3 | 4 | Set Implicit Arguments. 5 | Unset Strict Implicit. 6 | Unset Printing Implicit Defensive. 7 | 8 | Local Delimit Scope Z_scope with Z. 9 | 10 | Fact test_zero_nat : Z.of_nat 0%R = 0%Z. 11 | Proof. zify_op; reflexivity. Qed. 12 | 13 | Fact test_add_nat n m : Z.of_nat (n + m)%R = (Z.of_nat n + Z.of_nat m)%Z. 14 | Proof. zify_op; reflexivity. Qed. 15 | 16 | Fact test_one_nat : Z.of_nat 1%R = 1%Z. 17 | Proof. zify_op; reflexivity. Qed. 18 | 19 | Fact test_mul_nat n m : Z.of_nat (n * m)%R = (Z.of_nat n * Z.of_nat m)%Z. 20 | Proof. zify_op; reflexivity. Qed. 21 | 22 | Fact test_natmul_nat n m : Z.of_nat (n *+ m)%R = (Z.of_nat n * Z.of_nat m)%Z. 23 | Proof. zify_op; reflexivity. Qed. 24 | 25 | Fact test_exp_nat n m : Z.of_nat (n ^+ m)%R = (Z.of_nat n ^ Z.of_nat m)%Z. 26 | Proof. zify_op; reflexivity. Qed. 27 | 28 | Fact test_zero_N : Z.of_N 0%R = 0%Z. 29 | Proof. zify_op; reflexivity. Qed. 30 | 31 | Fact test_add_N n m : Z.of_N (n + m)%R = (Z.of_N n + Z.of_N m)%Z. 32 | Proof. zify_op; reflexivity. Qed. 33 | 34 | Fact test_one_N : Z.of_N 1%R = 1%Z. 35 | Proof. zify_op; reflexivity. Qed. 36 | 37 | Fact test_mul_N n m : Z.of_N (n * m)%R = (Z.of_N n * Z.of_N m)%Z. 38 | Proof. zify_op; reflexivity. Qed. 39 | 40 | Fact test_natmul_N n m : Z.of_N (n *+ m)%R = (Z.of_N n * Z.of_nat m)%Z. 41 | Proof. zify_op; reflexivity. Qed. 42 | 43 | Fact test_exp_N n m : Z.of_N (n ^+ m)%R = (Z.of_N n ^ Z.of_nat m)%Z. 44 | Proof. zify_op; reflexivity. Qed. 45 | 46 | Fact test_unit_int m : 47 | m \is a GRing.unit = (Z_of_int m =? 1)%Z || (Z_of_int m =? - 1)%Z. 48 | Proof. zify_pre_hook; zify_op; reflexivity. Qed. 49 | -------------------------------------------------------------------------------- /examples/test_ssreflect.v: -------------------------------------------------------------------------------- 1 | From Coq Require Import BinInt Zify. 2 | From mathcomp Require Import all_ssreflect zify ssrZ. 3 | 4 | Set Implicit Arguments. 5 | Unset Strict Implicit. 6 | Unset Printing Implicit Defensive. 7 | 8 | (* FIXME: dual instances are not exported *) 9 | Import Order.Theory. 10 | 11 | Local Delimit Scope Z_scope with Z. 12 | 13 | Implicit Types (b : bool) (n m : nat). 14 | 15 | (******************************************************************************) 16 | (* ssrbool *) 17 | (******************************************************************************) 18 | 19 | Fact test_andb b1 b2 : b1 (+) b2 = Bool.eqb b1 (~~ b2). 20 | Proof. zify_op; reflexivity. Qed. 21 | 22 | Fact test_eqb b1 b2 : eqb b1 b2 = Bool.eqb b1 b2. 23 | Proof. zify_op; reflexivity. Qed. 24 | 25 | Fact test_eq_op_bool b1 b2 : (b1 == b2) = Bool.eqb b1 b2. 26 | Proof. zify_op; reflexivity. Qed. 27 | 28 | Fact test_le_bool b1 b2 : (b1 <= b2)%O = implb b1 b2. 29 | Proof. zify_op; reflexivity. Qed. 30 | 31 | Fact test_ge_bool b1 b2 : (b1 >= b2)%O = implb b2 b1. 32 | Proof. zify_op; reflexivity. Qed. 33 | 34 | Fact test_dual_le_bool (b1 b2 : bool^d) : (b1 <=^d b2)%O = implb b2 b1. 35 | Proof. zify_op; reflexivity. Qed. 36 | 37 | Fact test_dual_ge_bool (b1 b2 : bool^d) : (b1 >=^d b2)%O = implb b1 b2. 38 | Proof. zify_op; reflexivity. Qed. 39 | 40 | Fact test_lt_bool b1 b2 : (b1 < b2)%O = ~~ b1 && b2. 41 | Proof. zify_op; reflexivity. Qed. 42 | 43 | Fact test_gt_bool b1 b2 : (b1 > b2)%O = ~~ b2 && b1. 44 | Proof. zify_op; reflexivity. Qed. 45 | 46 | Fact test_dual_lt_bool (b1 b2 : bool^d) : (b1 <^d b2)%O = b1 && ~~ b2. 47 | Proof. zify_op; reflexivity. Qed. 48 | 49 | Fact test_dual_gt_bool (b1 b2 : bool^d) : (b1 >^d b2)%O = b2 && ~~ b1. 50 | Proof. zify_op; reflexivity. Qed. 51 | 52 | (* FIXME: ge, gt *) 53 | 54 | Fact test_min_bool b1 b2 : Order.min b1 b2 = b1 && b2. 55 | Proof. zify_op; reflexivity. Qed. 56 | 57 | Fact test_max_bool b1 b2 : Order.max b1 b2 = b1 || b2. 58 | Proof. zify_op; reflexivity. Qed. 59 | 60 | Fact test_dual_min_bool (b1 b2 : bool^d) : Order.dual_min b1 b2 = b1 || b2. 61 | Proof. zify_op; reflexivity. Qed. 62 | 63 | Fact test_dual_max_bool (b1 b2 : bool^d) : Order.dual_max b1 b2 = b1 && b2. 64 | Proof. zify_op; reflexivity. Qed. 65 | 66 | (* FIXME: meet and join below are broken but the tests pass because they are *) 67 | (* convertible anyway. *) 68 | Fact test_meet_bool b1 b2 : (b1 `&` b2)%O = b1 && b2. 69 | Proof. zify_op; reflexivity. Qed. 70 | 71 | Fact test_join_bool b1 b2 : (b1 `|` b2)%O = b1 || b2. 72 | Proof. zify_op; reflexivity. Qed. 73 | 74 | Fact test_dual_meet_bool (b1 b2 : bool^d) : (b1 `&^d` b2)%O = b1 || b2. 75 | Proof. zify_op; reflexivity. Qed. 76 | 77 | Fact test_dual_join_bool (b1 b2 : bool^d) : (b1 `|^d` b2)%O = b1 && b2. 78 | Proof. zify_op; reflexivity. Qed. 79 | 80 | Fact test_bottom_bool : \bot%O = false :> bool. 81 | Proof. zify_op; reflexivity. Qed. 82 | 83 | Fact test_top_bool : \top%O = true :> bool. 84 | Proof. zify_op; reflexivity. Qed. 85 | 86 | (* FIXME: Notations 0^d and 1^d are broken. *) 87 | Fact test_dual_bottom_bool : \bot%O = true :> bool^d. 88 | Proof. zify_op; reflexivity. Qed. 89 | 90 | Fact test_dual_top_bool : \top%O = false :> bool^d. 91 | Proof. zify_op; reflexivity. Qed. 92 | 93 | Fact test_sub_bool b1 b2 : (b1 `\` b2)%O = b1 && ~~ b2. 94 | Proof. zify_op; reflexivity. Qed. 95 | 96 | Fact test_compl_bool b : (~` b)%O = ~~ b. 97 | Proof. zify_op; reflexivity. Qed. 98 | 99 | (******************************************************************************) 100 | (* ssrnat *) 101 | (******************************************************************************) 102 | 103 | Fact test_eqn n m : eqn n m = Z.eqb (Z.of_nat n) (Z.of_nat m). 104 | Proof. zify_op; reflexivity. Qed. 105 | 106 | Fact test_eq_op_nat n m : (n == m) = Z.eqb (Z.of_nat n) (Z.of_nat m). 107 | Proof. zify_op; reflexivity. Qed. 108 | 109 | Fact test_addn n m : Z.of_nat (n + m) = (Z.of_nat n + Z.of_nat m)%Z. 110 | Proof. zify_op; reflexivity. Qed. 111 | 112 | Fact test_addn_trec n m : 113 | Z.of_nat (NatTrec.add n m) = (Z.of_nat n + Z.of_nat m)%Z. 114 | Proof. zify_op; reflexivity. Qed. 115 | 116 | Fact test_subn n m : 117 | Z.of_nat (n - m) = Z.max 0 (Z.of_nat n - Z.of_nat m). 118 | Proof. zify_op; reflexivity. Qed. 119 | 120 | Fact test_muln n m : Z.of_nat (n * m) = (Z.of_nat n * Z.of_nat m)%Z. 121 | Proof. zify_op; reflexivity. Qed. 122 | 123 | Fact test_muln_trec n m : 124 | Z.of_nat (NatTrec.mul n m) = (Z.of_nat n * Z.of_nat m)%Z. 125 | Proof. zify_op; reflexivity. Qed. 126 | 127 | Fact test_leq n m : (n <= m) = (Z.of_nat n <=? Z.of_nat m)%Z. 128 | Proof. zify_op; reflexivity. Qed. 129 | 130 | (* FIXME: geq, ltn, gtn *) 131 | 132 | Fact test_minn n m : Z.of_nat (minn n m) = Z.min (Z.of_nat n) (Z.of_nat m). 133 | Proof. zify_op; reflexivity. Qed. 134 | 135 | Fact test_maxn n m : Z.of_nat (maxn n m) = Z.max (Z.of_nat n) (Z.of_nat m). 136 | Proof. zify_op; reflexivity. Qed. 137 | 138 | Fact test_nat_of_bool b : Z.of_nat (nat_of_bool b) = Z.b2z b. 139 | Proof. zify_op; reflexivity. Qed. 140 | 141 | Fact test_double n : Z.of_nat n.*2 = (2 * Z.of_nat n)%Z. 142 | Proof. zify_op; reflexivity. Qed. 143 | 144 | Fact test_double_trec n : Z.of_nat (NatTrec.double n) = (2 * Z.of_nat n)%Z. 145 | Proof. zify_op; reflexivity. Qed. 146 | 147 | Fact test_expn n m : Z.of_nat (n ^ m) = (Z.of_nat n ^ Z.of_nat m)%Z. 148 | Proof. zify_op; reflexivity. Qed. 149 | 150 | Fact test_expn_trec n m : 151 | Z.of_nat (NatTrec.exp n m) = (Z.of_nat n ^ Z.of_nat m)%Z. 152 | Proof. zify_op; reflexivity. Qed. 153 | 154 | Fact test_eq_op_N (n m : N) : (n == m) = (Z.of_N n =? Z.of_N m)%Z. 155 | Proof. zify_op; reflexivity. Qed. 156 | 157 | Fact test_nat_of_pos p : Z.of_nat (nat_of_pos p) = Z.pos p. 158 | Proof. zify_op; reflexivity. Qed. 159 | 160 | Fact test_nat_of_bin (n : N) : Z.of_nat (nat_of_bin n) = Z.of_N n. 161 | Proof. zify_op; reflexivity. Qed. 162 | 163 | Fact test_pos_of_nat n m : 164 | Z.pos (pos_of_nat n m) = Z.max 1 (Z.of_nat n * 2 - Z.of_nat m + 1). 165 | Proof. zify_op; reflexivity. Qed. 166 | 167 | Fact test_bin_of_nat n : Z.of_N (bin_of_nat n) = Z.of_nat n. 168 | Proof. zify_op; reflexivity. Qed. 169 | 170 | Fact test_le_nat n m : (n <= m)%O = (Z.of_nat n <=? Z.of_nat m)%Z. 171 | Proof. zify_op; reflexivity. Qed. 172 | 173 | Fact test_ge_nat n m : (n >= m)%O = (Z.of_nat m <=? Z.of_nat n)%Z. 174 | Proof. zify_op; reflexivity. Qed. 175 | 176 | Fact test_dual_le_nat (n m : nat^d) : 177 | (n <=^d m)%O = (Z.of_nat n >=? Z.of_nat m)%Z. 178 | Proof. zify_op; reflexivity. Qed. 179 | 180 | Fact test_dual_ge_nat (n m : nat^d) : 181 | (n >=^d m)%O = (Z.of_nat m >=? Z.of_nat n)%Z. 182 | Proof. zify_op; reflexivity. Qed. 183 | 184 | Fact test_lt_nat n m : (n < m)%O = (Z.of_nat n m)%O = (Z.of_nat m ? Z.of_nat m)%Z. 192 | Proof. zify_op; reflexivity. Qed. 193 | 194 | Fact test_dual_gt_nat (n m : nat^d) : 195 | (n >^d m)%O = (Z.of_nat m >? Z.of_nat n)%Z. 196 | Proof. zify_op; reflexivity. Qed. 197 | 198 | (* FIXME: ge, gt *) 199 | 200 | Fact test_min_nat n m : 201 | Z.of_nat (Order.min n m) = Z.min (Z.of_nat n) (Z.of_nat m). 202 | Proof. zify_op; reflexivity. Qed. 203 | 204 | Fact test_max_nat n m : 205 | Z.of_nat (Order.max n m) = Z.max (Z.of_nat n) (Z.of_nat m). 206 | Proof. zify_op; reflexivity. Qed. 207 | 208 | Fact test_dual_min_nat (n m : nat^d) : 209 | Z.of_nat (Order.dual_min n m) = Z.max (Z.of_nat n) (Z.of_nat m). 210 | Proof. zify_op; reflexivity. Qed. 211 | 212 | Fact test_dual_max_nat (n m : nat^d) : 213 | Z.of_nat (Order.dual_max n m) = Z.min (Z.of_nat n) (Z.of_nat m). 214 | Proof. zify_op; reflexivity. Qed. 215 | 216 | Fact test_meet_nat n m : Z.of_nat (n `&` m)%O = Z.min (Z.of_nat n) (Z.of_nat m). 217 | Proof. zify_op; reflexivity. Qed. 218 | 219 | Fact test_join_nat n m : Z.of_nat (n `|` m)%O = Z.max (Z.of_nat n) (Z.of_nat m). 220 | Proof. zify_op; reflexivity. Qed. 221 | 222 | Fact test_dual_meet_nat (n m : nat^d) : 223 | Z.of_nat (n `&^d` m)%O = Z.max (Z.of_nat n) (Z.of_nat m). 224 | Proof. zify_op; reflexivity. Qed. 225 | 226 | Fact test_dual_join_nat (n m : nat^d) : 227 | Z.of_nat (n `|^d` m)%O = Z.min (Z.of_nat n) (Z.of_nat m). 228 | Proof. zify_op; reflexivity. Qed. 229 | 230 | Fact test_bottom_nat : Z.of_nat \bot%O = 0%Z. 231 | Proof. zify_op; reflexivity. Qed. 232 | 233 | (******************************************************************************) 234 | (* div (divn, modn, dvdn, gcdn, lcmn, and coprime) *) 235 | (******************************************************************************) 236 | 237 | Notation divZ := zify_ssreflect.SsreflectZifyInstances.divZ. 238 | Notation modZ := zify_ssreflect.SsreflectZifyInstances.modZ. 239 | 240 | Fact test_divn n m : Z.of_nat (divn n m) = divZ (Z.of_nat n) (Z.of_nat m). 241 | Proof. zify_op; reflexivity. Qed. 242 | 243 | Fact test_modn n m : Z.of_nat (modn n m) = modZ (Z.of_nat n) (Z.of_nat m). 244 | Proof. zify_op; reflexivity. Qed. 245 | 246 | Fact test_dvdn n m : dvdn n m = (modZ (Z.of_nat m) (Z.of_nat n) =? 0)%Z. 247 | Proof. zify_op; reflexivity. Qed. 248 | 249 | Fact test_odd n : odd n = (modZ (Z.of_nat n) 2 =? 1)%Z. 250 | Proof. zify_op; reflexivity. Qed. 251 | 252 | Fact test_odd_trec n : NatTrec.odd n = (modZ (Z.of_nat n) 2 =? 1)%Z. 253 | Proof. zify_op; reflexivity. Qed. 254 | 255 | Fact test_half n : Z.of_nat (half n) = divZ (Z.of_nat n) 2. 256 | Proof. zify_op; reflexivity. Qed. 257 | 258 | Fact test_uphalf n : Z.of_nat (uphalf n) = divZ (Z.of_nat n + 1) 2. 259 | Proof. zify_op; reflexivity. Qed. 260 | 261 | Fact test_gcdn n m : Z.of_nat (gcdn n m) = Z.gcd (Z.of_nat n) (Z.of_nat m). 262 | Proof. zify_op; reflexivity. Qed. 263 | 264 | Fact test_lcmn n m : Z.of_nat (lcmn n m) = Z.lcm (Z.of_nat n) (Z.of_nat m). 265 | Proof. zify_op; reflexivity. Qed. 266 | 267 | Fact test_coprime n m : coprime n m = (Z.gcd (Z.of_nat n) (Z.of_nat m) =? 1)%Z. 268 | Proof. zify_op; reflexivity. Qed. 269 | 270 | (******************************************************************************) 271 | (* natdvd in order.v *) 272 | (******************************************************************************) 273 | 274 | Fact test_le_natdvd (n m : natdvd) : 275 | (n <= m)%O = (modZ (Z.of_nat m) (Z.of_nat n) =? 0)%Z. 276 | Proof. zify_op; reflexivity. Qed. 277 | 278 | Fact test_lt_natdvd (n m : natdvd) : 279 | (n < m)%O = 280 | ~~ (Z.of_nat m =? Z.of_nat n)%Z && (modZ (Z.of_nat m) (Z.of_nat n) =? 0)%Z. 281 | Proof. zify_op; reflexivity. Qed. 282 | 283 | Fact test_dual_le_natdvd (n m : natdvd^d) : 284 | (m <= n)%O = (modZ (Z.of_nat m) (Z.of_nat n) =? 0)%Z. 285 | Proof. zify_op; reflexivity. Qed. 286 | 287 | Fact test_dual_lt_natdvd (n m : natdvd^d) : 288 | (m < n)%O = 289 | ~~ (Z.of_nat m =? Z.of_nat n)%Z && (modZ (Z.of_nat m) (Z.of_nat n) =? 0)%Z. 290 | Proof. zify_op; reflexivity. Qed. 291 | 292 | (* FIXME: ge, gt *) 293 | 294 | Fact test_meet_natdvd (n m : natdvd) : 295 | Z.of_nat (n `&` m)%O = Z.gcd (Z.of_nat n) (Z.of_nat m). 296 | Proof. zify_op; reflexivity. Qed. 297 | 298 | Fact test_join_natdvd (n m : natdvd) : 299 | Z.of_nat (n `|` m)%O = Z.lcm (Z.of_nat n) (Z.of_nat m). 300 | Proof. zify_op; reflexivity. Qed. 301 | 302 | Fact test_dual_meet_natdvd (n m : natdvd^d) : 303 | Z.of_nat (n `&` m)%O = Z.lcm (Z.of_nat n) (Z.of_nat m). 304 | Proof. zify_op; reflexivity. Qed. 305 | 306 | Fact test_dual_join_natdvd (n m : natdvd^d) : 307 | Z.of_nat (n `|` m)%O = Z.gcd (Z.of_nat n) (Z.of_nat m). 308 | Proof. zify_op; reflexivity. Qed. 309 | 310 | Fact test_bottom_natdvd : Z.of_nat (\bot%O : natdvd) = 1%Z. 311 | Proof. zify_op; reflexivity. Qed. 312 | 313 | Fact test_top_natdvd : Z.of_nat (\top%O : natdvd) = 0%Z. 314 | Proof. zify_op; reflexivity. Qed. 315 | 316 | Fact test_dual_bottom_natdvd : Z.of_nat (\bot^d%O : natdvd^d) = 0%Z. 317 | Proof. zify_op; reflexivity. Qed. 318 | 319 | Fact test_dual_top_natdvd : Z.of_nat (\top^d%O : natdvd^d) = 1%Z. 320 | Proof. zify_op; reflexivity. Qed. 321 | -------------------------------------------------------------------------------- /examples/zagier.v: -------------------------------------------------------------------------------- 1 | From mathcomp Require Import all_ssreflect zify. 2 | 3 | Set Implicit Arguments. 4 | Unset Strict Implicit. 5 | Unset Printing Implicit Defensive. 6 | 7 | Lemma zagierK x y z : 0 < x -> 0 < z -> 8 | let zagier t := 9 | let: (x, y, z) := t in 10 | if x < y - z then (x + z.*2, z, y - z - x) 11 | else if x < y.*2 then (y.*2 - x, y, x + z - y) 12 | else (x - y.*2, x + z - y, y) in 13 | zagier (zagier (x, y, z)) = (x, y, z). 14 | Proof. 15 | move=> xP zP /=. 16 | repeat case: leqP => *; congr (_,_,_); lia. 17 | Qed. 18 | -------------------------------------------------------------------------------- /meta.yml: -------------------------------------------------------------------------------- 1 | --- 2 | fullname: Mczify 3 | shortname: mczify 4 | opam_name: coq-mathcomp-zify 5 | organization: math-comp 6 | action: true 7 | 8 | synopsis: >- 9 | Micromega tactics for Mathematical Components 10 | 11 | description: |- 12 | This small library enables the use of the Micromega arithmetic solvers of Coq 13 | for goals stated with the definitions of the Mathematical Components library 14 | by extending the zify tactic. 15 | 16 | authors: 17 | - name: Kazuhiko Sakaguchi 18 | initial: true 19 | 20 | opam-file-maintainer: kazuhiko.sakaguchi@inria.fr 21 | 22 | license: 23 | fullname: CeCILL-B Free Software License Agreement 24 | identifier: CECILL-B 25 | file: CeCILL-B 26 | 27 | supported_coq_versions: 28 | text: 8.16 or later 29 | opam: '{>= "8.16"}' 30 | 31 | tested_coq_nix_versions: 32 | 33 | tested_coq_opam_versions: 34 | - version: '2.0.0-coq-8.16' 35 | repo: 'mathcomp/mathcomp' 36 | - version: '2.0.0-coq-8.17' 37 | repo: 'mathcomp/mathcomp' 38 | - version: '2.0.0-coq-8.18' 39 | repo: 'mathcomp/mathcomp' 40 | - version: '2.1.0-coq-8.16' 41 | repo: 'mathcomp/mathcomp' 42 | - version: '2.1.0-coq-8.17' 43 | repo: 'mathcomp/mathcomp' 44 | - version: '2.1.0-coq-8.18' 45 | repo: 'mathcomp/mathcomp' 46 | - version: '2.2.0-coq-8.16' 47 | repo: 'mathcomp/mathcomp' 48 | - version: '2.2.0-coq-8.17' 49 | repo: 'mathcomp/mathcomp' 50 | - version: '2.2.0-coq-8.18' 51 | repo: 'mathcomp/mathcomp' 52 | - version: '2.2.0-coq-8.19' 53 | repo: 'mathcomp/mathcomp' 54 | - version: '2.2.0-coq-8.20' 55 | repo: 'mathcomp/mathcomp' 56 | - version: '2.3.0-coq-8.18' 57 | repo: 'mathcomp/mathcomp' 58 | - version: '2.3.0-coq-8.19' 59 | repo: 'mathcomp/mathcomp' 60 | - version: '2.3.0-coq-8.20' 61 | repo: 'mathcomp/mathcomp' 62 | - version: '2.4.0-coq-8.19' 63 | repo: 'mathcomp/mathcomp' 64 | - version: '2.4.0-coq-8.20' 65 | repo: 'mathcomp/mathcomp' 66 | - version: '2.4.0-rocq-prover-9.0' 67 | repo: 'mathcomp/mathcomp' 68 | - version: '2.4.0-rocq-prover-dev' 69 | repo: 'mathcomp/mathcomp' 70 | - version: 'coq-8.20' 71 | repo: 'mathcomp/mathcomp-dev' 72 | - version: 'rocq-prover-9.0' 73 | repo: 'mathcomp/mathcomp-dev' 74 | - version: 'rocq-prover-dev' 75 | repo: 'mathcomp/mathcomp-dev' 76 | 77 | dependencies: 78 | - opam: 79 | name: coq-mathcomp-ssreflect 80 | version: '{>= "2.0"}' 81 | description: |- 82 | [MathComp](https://math-comp.github.io) ssreflect 2.0 or later 83 | - opam: 84 | name: coq-mathcomp-algebra 85 | description: |- 86 | [MathComp](https://math-comp.github.io) algebra 87 | 88 | test_target: test-suite 89 | namespace: mathcomp.zify 90 | 91 | action_appendix: |2- 92 | export: 'OPAMWITHTEST' 93 | env: 94 | OPAMWITHTEST: true 95 | 96 | documentation: |- 97 | ## File contents 98 | 99 | - `zify_ssreflect.v`: Z-ification instances for the `coq-mathcomp-ssreflect` 100 | library 101 | - `zify_algebra.v`: Z-ification instances for the `coq-mathcomp-algebra` 102 | library 103 | - `zify.v`: re-exports all the Z-ification instances 104 | - `ssrZ.v`: provides a minimal facility for reasoning about `Z` and relating 105 | `Z` and `int` 106 | 107 | --- 108 | -------------------------------------------------------------------------------- /theories/ssrZ.v: -------------------------------------------------------------------------------- 1 | From Coq Require Import ZArith. 2 | 3 | From HB Require Import structures. 4 | From mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq path. 5 | From mathcomp Require Import div choice fintype tuple finfun bigop finset prime. 6 | From mathcomp Require Import order binomial ssralg countalg ssrnum ssrint. 7 | From mathcomp Require Import zify_ssreflect. 8 | 9 | Set Implicit Arguments. 10 | Unset Strict Implicit. 11 | Unset Printing Implicit Defensive. 12 | 13 | Import Order.Theory GRing.Theory Num.Theory. 14 | 15 | Definition int_of_Z (n : Z) : int := 16 | match n with 17 | | Z0 => Posz 0 18 | | Zpos p => Posz (Pos.to_nat p) 19 | | Zneg p => Negz (Pos.to_nat p).-1 20 | end. 21 | 22 | Definition Z_of_int (n : int) : Z := 23 | match n with 24 | | Posz n => Z.of_nat n 25 | | Negz n' => Z.opp (Z.of_nat (n' + 1)) 26 | end. 27 | 28 | Lemma int_of_ZK : cancel int_of_Z Z_of_int. 29 | Proof. by case=> //= p; lia. Qed. 30 | 31 | Lemma Z_of_intK : cancel Z_of_int int_of_Z. 32 | Proof. 33 | case=> [[|n]|n] //=. 34 | congr Posz; lia. 35 | rewrite addnC /=; congr Negz; lia. 36 | Qed. 37 | 38 | Module Instances. 39 | 40 | (* Instances taken from math-comp/math-comp#1031, authored by Pierre Roux *) 41 | (* TODO: remove them when we drop support for MathComp 2.0 *) 42 | #[export] 43 | HB.instance Definition _ := GRing.isNmodule.Build nat addnA addnC add0n. 44 | 45 | #[export] 46 | HB.instance Definition _ := GRing.Nmodule_isComSemiRing.Build nat 47 | mulnA mulnC mul1n mulnDl mul0n erefl. 48 | 49 | #[export] 50 | HB.instance Definition _ (V : nmodType) (x : V) := 51 | GRing.isSemiAdditive.Build nat V (GRing.natmul x) (mulr0n x, mulrnDr x). 52 | 53 | #[export] 54 | HB.instance Definition _ (R : semiRingType) := 55 | GRing.isMultiplicative.Build nat R (GRing.natmul 1) (natrM R, mulr1n 1). 56 | 57 | Fact Posz_is_semi_additive : semi_additive Posz. 58 | Proof. by []. Qed. 59 | 60 | #[export] 61 | HB.instance Definition _ := GRing.isSemiAdditive.Build nat int Posz 62 | Posz_is_semi_additive. 63 | 64 | Fact Posz_is_multiplicative : multiplicative Posz. 65 | Proof. by []. Qed. 66 | 67 | #[export] 68 | HB.instance Definition _ := GRing.isMultiplicative.Build nat int Posz 69 | Posz_is_multiplicative. 70 | (* end *) 71 | 72 | #[export] 73 | HB.instance Definition _ := Countable.copy N (can_type nat_of_binK). 74 | 75 | #[export] 76 | HB.instance Definition _ := GRing.isNmodule.Build N 77 | Nplus_assoc Nplus_comm Nplus_0_l. 78 | 79 | #[export] 80 | HB.instance Definition _ := GRing.Nmodule_isComSemiRing.Build N 81 | Nmult_assoc Nmult_comm Nmult_1_l Nmult_plus_distr_r N.mul_0_l isT. 82 | 83 | Fact bin_of_nat_is_semi_additive : semi_additive bin_of_nat. 84 | Proof. by split=> //= m n; rewrite /GRing.add /=; lia. Qed. 85 | 86 | #[export] 87 | HB.instance Definition _ := GRing.isSemiAdditive.Build nat N bin_of_nat 88 | bin_of_nat_is_semi_additive. 89 | 90 | Fact nat_of_bin_is_semi_additive : semi_additive nat_of_bin. 91 | Proof. by split=> //= m n; rewrite /GRing.add /=; lia. Qed. 92 | 93 | #[export] 94 | HB.instance Definition _ := GRing.isSemiAdditive.Build N nat nat_of_bin 95 | nat_of_bin_is_semi_additive. 96 | 97 | Fact bin_of_nat_is_multiplicative : multiplicative bin_of_nat. 98 | Proof. by split=> // m n; rewrite /GRing.mul /=; lia. Qed. 99 | 100 | #[export] 101 | HB.instance Definition _ := GRing.isMultiplicative.Build nat N bin_of_nat 102 | bin_of_nat_is_multiplicative. 103 | 104 | Fact nat_of_bin_is_multiplicative : multiplicative nat_of_bin. 105 | Proof. by split=> // m n; rewrite /GRing.mul /=; lia. Qed. 106 | 107 | #[export] 108 | HB.instance Definition _ := GRing.isMultiplicative.Build N nat nat_of_bin 109 | nat_of_bin_is_multiplicative. 110 | 111 | Fact N_of_nat_is_semi_additive : semi_additive N.of_nat. 112 | Proof. by split=> //= m n; rewrite /GRing.add /=; lia. Qed. 113 | 114 | #[export] 115 | HB.instance Definition _ := GRing.isSemiAdditive.Build nat N N.of_nat 116 | N_of_nat_is_semi_additive. 117 | 118 | Fact N_to_nat_is_semi_additive : semi_additive N.to_nat. 119 | Proof. by split=> //= m n; rewrite /GRing.add /=; lia. Qed. 120 | 121 | #[export] 122 | HB.instance Definition _ := GRing.isSemiAdditive.Build N nat N.to_nat 123 | N_to_nat_is_semi_additive. 124 | 125 | Fact N_of_nat_is_multiplicative : multiplicative N.of_nat. 126 | Proof. by split=> // m n; rewrite /GRing.mul /=; lia. Qed. 127 | 128 | #[export] 129 | HB.instance Definition _ := GRing.isMultiplicative.Build nat N N.of_nat 130 | N_of_nat_is_multiplicative. 131 | 132 | Fact N_to_nat_is_multiplicative : multiplicative N.to_nat. 133 | Proof. by split=> // m n; rewrite /GRing.mul /=; lia. Qed. 134 | 135 | #[export] 136 | HB.instance Definition _ := GRing.isMultiplicative.Build N nat N.to_nat 137 | N_to_nat_is_multiplicative. 138 | 139 | Implicit Types (m n : Z). 140 | 141 | Fact eqZP : Equality.axiom Z.eqb. 142 | Proof. by move=> x y; apply: (iffP idP); lia. Qed. 143 | 144 | #[export] 145 | HB.instance Definition _ := hasDecEq.Build Z eqZP. 146 | 147 | #[export] 148 | HB.instance Definition _ := Countable.copy Z (can_type int_of_ZK). 149 | 150 | #[export] 151 | HB.instance Definition _ := GRing.isZmodule.Build Z 152 | Zplus_assoc Zplus_comm Zplus_0_l Zplus_opp_l. 153 | 154 | #[export] 155 | HB.instance Definition _ := GRing.Zmodule_isComRing.Build Z 156 | Zmult_assoc Zmult_comm Zmult_1_l Zmult_plus_distr_l isT. 157 | 158 | Definition unitZ := [qualify a n : Z | (n == Z.pos xH) || (n == Z.neg xH)]. 159 | Definition invZ n := n. 160 | 161 | Fact mulVZ : {in unitZ, left_inverse 1%R invZ *%R}. 162 | Proof. by move=> n /pred2P[] ->. Qed. 163 | 164 | Fact unitZPl m n : (n * m = 1)%R -> m \is a unitZ. 165 | Proof. case: m n => [|[m|m|]|[m|m|]] [|n|n] //= []; lia. Qed. 166 | 167 | Fact invZ_out : {in [predC unitZ], invZ =1 id}. 168 | Proof. exact. Qed. 169 | 170 | #[export] 171 | HB.instance Definition _ := GRing.ComRing_hasMulInverse.Build Z 172 | mulVZ unitZPl invZ_out. 173 | 174 | Fact idomain_axiomZ m n : (m * n = 0)%R -> (m == 0%R) || (n == 0%R). 175 | Proof. by case: m n => [|m|m] []. Qed. 176 | 177 | #[export] 178 | HB.instance Definition _ := GRing.ComUnitRing_isIntegral.Build Z idomain_axiomZ. 179 | 180 | Fact leZ_add m n : Z.leb 0 m -> Z.leb 0 n -> Z.leb 0 (m + n). Proof. lia. Qed. 181 | Fact leZ_mul m n : Z.leb 0 m -> Z.leb 0 n -> Z.leb 0 (m * n). Proof. lia. Qed. 182 | Fact leZ_anti m : Z.leb 0 m -> Z.leb m 0 -> m = Z0. Proof. lia. Qed. 183 | 184 | Fact subZ_ge0 m n : Z.leb 0 (n - m)%R = Z.leb m n. 185 | Proof. by rewrite /GRing.add /GRing.opp /=; lia. Qed. 186 | 187 | Fact leZ_total m n : Z.leb m n || Z.leb n m. Proof. lia. Qed. 188 | 189 | Fact normZN m : Z.abs (- m) = Z.abs m. Proof. lia. Qed. 190 | 191 | Fact geZ0_norm m : Z.leb 0 m -> Z.abs m = m. Proof. lia. Qed. 192 | 193 | Fact ltZ_def m n : (Z.ltb m n) = (n != m) && (Z.leb m n). 194 | Proof. by rewrite eqE /=; lia. Qed. 195 | 196 | #[export] 197 | HB.instance Definition _ := Num.IntegralDomain_isLeReal.Build Z 198 | leZ_add leZ_mul leZ_anti subZ_ge0 (leZ_total 0) normZN geZ0_norm ltZ_def. 199 | 200 | Fact Z_of_intE (n : int) : Z_of_int n = (n%:~R)%R. 201 | Proof. 202 | have Hnat (m : nat) : Z.of_nat m = (m%:R)%R. 203 | by elim: m => // m; rewrite Nat2Z.inj_succ -Z.add_1_l mulrS => ->. 204 | case: n => n; rewrite /intmul /=; first exact: Hnat. 205 | by congr Z.opp; rewrite Nat2Z.inj_add /= mulrSr Hnat. 206 | Qed. 207 | 208 | Fact Z_of_int_is_additive : additive Z_of_int. 209 | Proof. by move=> m n; rewrite !Z_of_intE raddfB. Qed. 210 | 211 | #[export] 212 | HB.instance Definition _ := GRing.isAdditive.Build int Z Z_of_int 213 | Z_of_int_is_additive. 214 | 215 | Fact int_of_Z_is_additive : additive int_of_Z. 216 | Proof. exact: can2_additive Z_of_intK int_of_ZK. Qed. 217 | 218 | #[export] 219 | HB.instance Definition _ := GRing.isAdditive.Build Z int int_of_Z 220 | int_of_Z_is_additive. 221 | 222 | Fact Z_of_int_is_multiplicative : multiplicative Z_of_int. 223 | Proof. by split => // m n; rewrite !Z_of_intE rmorphM. Qed. 224 | 225 | #[export] 226 | HB.instance Definition _ := GRing.isMultiplicative.Build int Z Z_of_int 227 | Z_of_int_is_multiplicative. 228 | 229 | Fact int_of_Z_is_multiplicative : multiplicative int_of_Z. 230 | Proof. exact: can2_rmorphism Z_of_intK int_of_ZK. Qed. 231 | 232 | #[export] 233 | HB.instance Definition _ := GRing.isMultiplicative.Build Z int int_of_Z 234 | int_of_Z_is_multiplicative. 235 | 236 | Fact Z_of_nat_is_semi_additive : semi_additive Z.of_nat. 237 | Proof. by split=> //= m n; rewrite /GRing.add /=; lia. Qed. 238 | 239 | #[export] 240 | HB.instance Definition _ := GRing.isSemiAdditive.Build nat Z Z.of_nat 241 | Z_of_nat_is_semi_additive. 242 | 243 | Fact Z_of_nat_is_multiplicative : multiplicative Z.of_nat. 244 | Proof. by split => // m n; rewrite /GRing.mul /=; lia. Qed. 245 | 246 | #[export] 247 | HB.instance Definition _ := GRing.isMultiplicative.Build nat Z Z.of_nat 248 | Z_of_nat_is_multiplicative. 249 | 250 | Fact Z_of_N_is_semi_additive : semi_additive Z.of_N. 251 | Proof. by split=> //= m n; rewrite /GRing.add /=; lia. Qed. 252 | 253 | #[export] 254 | HB.instance Definition _ := GRing.isSemiAdditive.Build N Z Z.of_N 255 | Z_of_N_is_semi_additive. 256 | 257 | Fact Z_of_N_is_multiplicative : multiplicative Z.of_N. 258 | Proof. by split => // m n; rewrite /GRing.mul /=; lia. Qed. 259 | 260 | #[export] 261 | HB.instance Definition _ := GRing.isMultiplicative.Build N Z Z.of_N 262 | Z_of_N_is_multiplicative. 263 | 264 | Module Exports. HB.reexport. End Exports. 265 | 266 | End Instances. 267 | 268 | Export Instances.Exports. 269 | -------------------------------------------------------------------------------- /theories/zify.v: -------------------------------------------------------------------------------- 1 | From Coq Require Export Lia. 2 | From mathcomp Require Import zify_ssreflect zify_algebra. 3 | Export SsreflectZifyInstances.Exports. 4 | Export AlgebraZifyInstances.Exports. 5 | -------------------------------------------------------------------------------- /theories/zify_algebra.v: -------------------------------------------------------------------------------- 1 | From Coq Require Import ZArith ZifyClasses ZifyBool. 2 | From Coq Require Export Lia. 3 | 4 | From mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq path. 5 | From mathcomp Require Import div choice fintype tuple finfun bigop finset prime. 6 | From mathcomp Require Import order binomial ssralg countalg ssrnum ssrint rat. 7 | From mathcomp Require Import intdiv. 8 | From mathcomp Require Import zify_ssreflect ssrZ. 9 | 10 | Set Implicit Arguments. 11 | Unset Strict Implicit. 12 | Unset Printing Implicit Defensive. 13 | 14 | Module AlgebraZifyInstances. 15 | 16 | Local Delimit Scope Z_scope with Z. 17 | 18 | Import Order.Theory GRing.Theory Num.Theory SsreflectZifyInstances. 19 | 20 | (* TODO: remove natn below when we drop support for MathComp 2.0 *) 21 | Local Lemma natn n : n%:R%R = n :> nat. 22 | Proof. by elim: n => // n; rewrite mulrS => ->. Qed. 23 | 24 | (******************************************************************************) 25 | (* nat *) 26 | (******************************************************************************) 27 | 28 | #[global] 29 | Instance Op_nat_0 : CstOp (0%R : nat) := ZifyInst.Op_O. 30 | Add Zify CstOp Op_nat_0. 31 | 32 | #[global] 33 | Instance Op_nat_add : BinOp (+%R : nat -> nat -> nat) := Op_addn. 34 | Add Zify BinOp Op_nat_add. 35 | 36 | #[global] 37 | Instance Op_nat_1 : CstOp (1%R : nat) := { TCst := 1%Z; TCstInj := erefl }. 38 | Add Zify CstOp Op_nat_1. 39 | 40 | #[global] 41 | Instance Op_nat_mul : BinOp ( *%R : nat -> nat -> nat) := Op_muln. 42 | Add Zify BinOp Op_nat_mul. 43 | 44 | Fact Op_nat_natmul_subproof (n m : nat) : 45 | Z.of_nat (n *+ m)%R = (Z.of_nat n * Z.of_nat m)%Z. 46 | Proof. by rewrite raddfMn -mulr_natr -[m in RHS]natn rmorph_nat. Qed. 47 | 48 | #[global] 49 | Instance Op_nat_natmul : BinOp (@GRing.natmul _ : nat -> nat -> nat) := 50 | { TBOp := Z.mul; TBOpInj := Op_nat_natmul_subproof }. 51 | Add Zify BinOp Op_nat_natmul. 52 | 53 | Fact Op_nat_exp_subproof (n : nat) (m : nat) : 54 | Z_of_nat (n ^+ m)%R = (Z_of_int n ^ Z.of_nat m)%Z. 55 | Proof. rewrite -Zpower_nat_Z; elim: m => //= m <-; rewrite exprS; lia. Qed. 56 | 57 | #[global] 58 | Instance Op_nat_exp : BinOp (@GRing.exp _ : nat -> nat -> nat) := 59 | { TBOp := Z.pow; TBOpInj := Op_nat_exp_subproof }. 60 | Add Zify BinOp Op_nat_exp. 61 | 62 | (******************************************************************************) 63 | (* N *) 64 | (******************************************************************************) 65 | 66 | #[global] 67 | Instance Op_N_0 : CstOp (0%R : N) := ZifyInst.Op_N_N0. 68 | Add Zify CstOp Op_N_0. 69 | 70 | #[global] 71 | Instance Op_N_add : BinOp (+%R : N -> N -> N) := ZifyInst.Op_N_add. 72 | Add Zify BinOp Op_N_add. 73 | 74 | #[global] 75 | Instance Op_N_1 : CstOp (1%R : N) := { TCst := 1%Z; TCstInj := erefl }. 76 | Add Zify CstOp Op_N_1. 77 | 78 | #[global] 79 | Instance Op_N_mul : BinOp ( *%R : N -> N -> N) := ZifyInst.Op_N_mul. 80 | Add Zify BinOp Op_N_mul. 81 | 82 | Fact Op_N_natmul_subproof (n : N) (m : nat) : 83 | Z.of_N (n *+ m)%R = (Z.of_N n * Z.of_nat m)%Z. 84 | Proof. by rewrite raddfMn -mulr_natr -[m in RHS]natn rmorph_nat. Qed. 85 | 86 | #[global] 87 | Instance Op_N_natmul : BinOp (@GRing.natmul _ : N -> nat -> N) := 88 | { TBOp := Z.mul; TBOpInj := Op_N_natmul_subproof }. 89 | Add Zify BinOp Op_N_natmul. 90 | 91 | Fact Op_N_exp_subproof (n : N) (m : nat) : 92 | Z_of_N (n ^+ m)%R = (Z_of_N n ^ Z.of_nat m)%Z. 93 | Proof. rewrite -Zpower_nat_Z; elim: m => //= m <-; rewrite exprS; lia. Qed. 94 | 95 | #[global] 96 | Instance Op_N_exp : BinOp (@GRing.exp _ : N -> nat -> N) := 97 | { TBOp := Z.pow; TBOpInj := Op_N_exp_subproof }. 98 | Add Zify BinOp Op_N_exp. 99 | 100 | (******************************************************************************) 101 | (* ssrint *) 102 | (******************************************************************************) 103 | 104 | #[global] 105 | Instance Inj_int_Z : InjTyp int Z := 106 | { inj := Z_of_int; pred _ := True; cstr _ := I }. 107 | Add Zify InjTyp Inj_int_Z. 108 | 109 | #[global] 110 | Instance Op_Z_of_int : UnOp Z_of_int := { TUOp := id; TUOpInj _ := erefl }. 111 | Add Zify UnOp Op_Z_of_int. 112 | 113 | #[global] 114 | Instance Op_int_of_Z : UnOp int_of_Z := { TUOp := id; TUOpInj := int_of_ZK }. 115 | Add Zify UnOp Op_int_of_Z. 116 | 117 | #[global] 118 | Instance Op_Posz : UnOp Posz := { TUOp := id; TUOpInj _ := erefl }. 119 | Add Zify UnOp Op_Posz. 120 | 121 | #[global] 122 | Instance Op_Negz : UnOp Negz := 123 | { TUOp x := (- (x + 1))%Z; TUOpInj := ltac:(simpl; lia) }. 124 | Add Zify UnOp Op_Negz. 125 | 126 | #[global] 127 | Instance Op_int_eq : BinRel (@eq int) := 128 | { TR := @eq Z; TRInj := ltac:(by split=> [->|/(can_inj Z_of_intK)]) }. 129 | Add Zify BinRel Op_int_eq. 130 | 131 | #[global] 132 | Instance Op_int_eq_op : BinOp (@eq_op int : int -> int -> bool) := 133 | { TBOp := Z.eqb; 134 | TBOpInj := ltac:(move=> [] ? [] ?; do 2 rewrite eqE /=; lia) }. 135 | Add Zify BinOp Op_int_eq_op. 136 | 137 | #[global] 138 | Instance Op_int_0 : CstOp (0%R : int) := { TCst := 0%Z; TCstInj := erefl }. 139 | Add Zify CstOp Op_int_0. 140 | 141 | #[global] 142 | Instance Op_addz : BinOp intZmod.addz := { TBOp := Z.add; TBOpInj := raddfD _ }. 143 | Add Zify BinOp Op_addz. 144 | 145 | #[global] 146 | Instance Op_int_add : BinOp +%R := Op_addz. 147 | Add Zify BinOp Op_int_add. 148 | 149 | #[global] 150 | Instance Op_oppz : UnOp intZmod.oppz := { TUOp := Z.opp; TUOpInj := raddfN _ }. 151 | Add Zify UnOp Op_oppz. 152 | 153 | #[global] 154 | Instance Op_int_opp : UnOp (@GRing.opp _) := Op_oppz. 155 | Add Zify UnOp Op_int_opp. 156 | 157 | #[global] 158 | Instance Op_int_1 : CstOp (1%R : int) := { TCst := 1%Z; TCstInj := erefl }. 159 | Add Zify CstOp Op_int_1. 160 | 161 | #[global] 162 | Instance Op_mulz : BinOp intRing.mulz := 163 | { TBOp := Z.mul; TBOpInj := rmorphM _ }. 164 | Add Zify BinOp Op_mulz. 165 | 166 | #[global] 167 | Instance Op_int_mulr : BinOp *%R := Op_mulz. 168 | Add Zify BinOp Op_int_mulr. 169 | 170 | #[global] 171 | Instance Op_int_natmul : BinOp (@GRing.natmul _ : int -> nat -> int) := 172 | { TBOp := Z.mul; TBOpInj _ _ := ltac:(rewrite /= pmulrn mulrzz; lia) }. 173 | Add Zify BinOp Op_int_natmul. 174 | 175 | #[global] 176 | Instance Op_int_intmul : BinOp ( *~%R%R : int -> int -> int) := 177 | { TBOp := Z.mul; TBOpInj _ _ := ltac:(rewrite /= mulrzz; lia) }. 178 | Add Zify BinOp Op_int_intmul. 179 | 180 | #[global] 181 | Instance Op_int_scale : BinOp (@GRing.scale _ int^o) := 182 | Op_mulz. 183 | Add Zify BinOp Op_int_scale. 184 | 185 | Fact Op_int_exp_subproof n m : Z_of_int (n ^+ m) = (Z_of_int n ^ Z.of_nat m)%Z. 186 | Proof. rewrite -Zpower_nat_Z; elim: m => //= m <-; rewrite exprS; lia. Qed. 187 | 188 | #[global] 189 | Instance Op_int_exp : BinOp (@GRing.exp _ : int -> nat -> int) := 190 | { TBOp := Z.pow; TBOpInj := Op_int_exp_subproof }. 191 | Add Zify BinOp Op_int_exp. 192 | 193 | #[global] 194 | Instance Op_unitz : UnOp (has_quality 1 intUnitRing.unitz : int -> bool) := 195 | { TUOp x := (x =? 1)%Z || (x =? - 1)%Z; TUOpInj := ltac:(simpl; lia) }. 196 | Add Zify UnOp Op_unitz. 197 | 198 | #[global] 199 | Instance Op_int_unit : UnOp (has_quality 1 GRing.unit) := Op_unitz. 200 | Add Zify UnOp Op_int_unit. 201 | 202 | #[global] 203 | Instance Op_invz : UnOp intUnitRing.invz := 204 | { TUOp := id; TUOpInj _ := erefl }. 205 | Add Zify UnOp Op_invz. 206 | 207 | #[global] 208 | Instance Op_int_inv : UnOp GRing.inv := Op_invz. 209 | Add Zify UnOp Op_int_inv. 210 | 211 | #[global] 212 | Instance Op_absz : UnOp absz := 213 | { TUOp := Z.abs; TUOpInj := ltac:(case=> ? /=; lia) }. 214 | Add Zify UnOp Op_absz. 215 | 216 | #[global] 217 | Instance Op_int_normr : UnOp (Num.norm : int -> int) := 218 | { TUOp := Z.abs; TUOpInj := ltac:(rewrite /Num.norm /=; lia) }. 219 | Add Zify UnOp Op_int_normr. 220 | 221 | #[global] 222 | Instance Op_lez : BinOp intOrdered.lez := 223 | { TBOp := Z.leb; TBOpInj := ltac:(case=> ? [] ? /=; lia) }. 224 | Add Zify BinOp Op_lez. 225 | 226 | #[global] 227 | Instance Op_ltz : BinOp intOrdered.ltz := 228 | { TBOp := Z.ltb; TBOpInj := ltac:(case=> ? [] ? /=; lia) }. 229 | Add Zify BinOp Op_ltz. 230 | 231 | #[global] 232 | Instance Op_int_sgr : UnOp (Num.sg : int -> int) := 233 | { TUOp := Z.sgn; TUOpInj := ltac:(case=> [[]|] //=; lia) }. 234 | Add Zify UnOp Op_int_sgr. 235 | 236 | #[global] 237 | Instance Op_int_sgz : UnOp (@sgz _) := Op_int_sgr. 238 | Add Zify UnOp Op_int_sgz. 239 | 240 | #[global] 241 | Instance Op_int_le : BinOp <=%O := Op_lez. 242 | Add Zify BinOp Op_int_le. 243 | 244 | #[global] 245 | Instance Op_int_le' : BinOp (>=^d%O : rel int^d) := Op_lez. 246 | Add Zify BinOp Op_int_le'. 247 | 248 | #[global] 249 | Instance Op_int_ge : BinOp (>=%O : int -> int -> bool) := 250 | { TBOp := Z.geb; TBOpInj := ltac:(simpl; lia) }. 251 | Add Zify BinOp Op_int_ge. 252 | 253 | #[global] 254 | Instance Op_int_ge' : BinOp (<=^d%O : rel int^d) := Op_int_ge. 255 | Add Zify BinOp Op_int_ge'. 256 | 257 | #[global] 258 | Instance Op_int_lt : BinOp <%O := Op_ltz. 259 | Add Zify BinOp Op_int_lt. 260 | 261 | #[global] 262 | Instance Op_int_lt' : BinOp (>^d%O : rel int^d) := Op_ltz. 263 | Add Zify BinOp Op_int_lt'. 264 | 265 | #[global] 266 | Instance Op_int_gt : BinOp (>%O : int -> int -> bool) := 267 | { TBOp := Z.gtb; TBOpInj := ltac:(simpl; lia) }. 268 | Add Zify BinOp Op_int_gt. 269 | 270 | #[global] 271 | Instance Op_int_gt' : BinOp (<^d%O : rel int^d) := Op_int_gt. 272 | Add Zify BinOp Op_int_gt'. 273 | 274 | #[global] 275 | Instance Op_int_min : BinOp (Order.min : int -> int -> int) := 276 | { TBOp := Z.min; TBOpInj _ _ := ltac:(case: leP => /=; lia) }. 277 | Add Zify BinOp Op_int_min. 278 | 279 | #[global] 280 | Instance Op_int_min' : BinOp ((Order.max : int^d -> _) : int -> int -> int) := 281 | { TBOp := Z.min; TBOpInj _ _ := ltac:(case: leP => /=; lia) }. 282 | Add Zify BinOp Op_int_min'. 283 | 284 | #[global] 285 | Instance Op_int_max : BinOp (Order.max : int -> int -> int) := 286 | { TBOp := Z.max; TBOpInj _ _ := ltac:(case: leP => /=; lia) }. 287 | Add Zify BinOp Op_int_max. 288 | 289 | #[global] 290 | Instance Op_int_max' : BinOp ((Order.min : int^d -> _) : int -> int -> int) := 291 | { TBOp := Z.max; TBOpInj _ _ := ltac:(case: leP => /=; lia) }. 292 | Add Zify BinOp Op_int_max'. 293 | 294 | #[global] 295 | Instance Op_int_meet : BinOp (Order.meet : int -> int -> int) := 296 | { TBOp := Z.min; TBOpInj _ _ := ltac:(case: leP => /=; lia) }. 297 | Add Zify BinOp Op_int_meet. 298 | 299 | #[global] 300 | Instance Op_int_meet' : BinOp (Order.join : int^d -> _) := Op_int_min. 301 | Add Zify BinOp Op_int_meet'. 302 | 303 | #[global] 304 | Instance Op_int_join : BinOp (Order.join : int -> int -> int) := 305 | { TBOp := Z.max; TBOpInj _ _ := ltac:(case: leP => /=; lia) }. 306 | Add Zify BinOp Op_int_join. 307 | 308 | #[global] 309 | Instance Op_int_join' : BinOp (Order.meet : int^d -> _) := Op_int_max. 310 | Add Zify BinOp Op_int_join'. 311 | 312 | (******************************************************************************) 313 | (* ssrZ *) 314 | (******************************************************************************) 315 | 316 | #[global] 317 | Instance Op_Z_eq_op : BinOp (eq_op : Z -> Z -> bool) := Op_Zeqb. 318 | Add Zify BinOp Op_Z_eq_op. 319 | 320 | #[global] 321 | Instance Op_Z_0 : CstOp (0%R : Z) := { TCst := 0%Z; TCstInj := erefl }. 322 | Add Zify CstOp Op_Z_0. 323 | 324 | #[global] 325 | Instance Op_Z_add : BinOp (+%R : Z -> Z -> Z) := 326 | { TBOp := Z.add; TBOpInj _ _ := erefl }. 327 | Add Zify BinOp Op_Z_add. 328 | 329 | #[global] 330 | Instance Op_Z_opp : UnOp (@GRing.opp _ : Z -> Z) := 331 | { TUOp := Z.opp; TUOpInj _ := erefl }. 332 | Add Zify UnOp Op_Z_opp. 333 | 334 | #[global] 335 | Instance Op_Z_1 : CstOp (1%R : Z) := { TCst := 1%Z; TCstInj := erefl }. 336 | Add Zify CstOp Op_Z_1. 337 | 338 | #[global] 339 | Instance Op_Z_mulr : BinOp ( *%R : Z -> Z -> Z) := 340 | { TBOp := Z.mul; TBOpInj _ _ := erefl }. 341 | Add Zify BinOp Op_Z_mulr. 342 | 343 | Fact Op_Z_natmul_subproof (n : Z) (m : nat) : (n *+ m)%R = (n * Z.of_nat m)%Z. 344 | Proof. 345 | elim: m => [|m]; rewrite (mulr0n, mulrS); first by lia. 346 | by move=> ->; lia. 347 | Qed. 348 | 349 | #[global] 350 | Instance Op_Z_natmul : BinOp (@GRing.natmul _ : Z -> nat -> Z) := 351 | { TBOp := Z.mul; TBOpInj := Op_Z_natmul_subproof }. 352 | Add Zify BinOp Op_Z_natmul. 353 | 354 | #[global] 355 | Instance Op_Z_intmul : BinOp ( *~%R%R : Z -> int -> Z) := 356 | { TBOp := Z.mul; TBOpInj := ltac:(move=> n [] m; rewrite /intmul /=; lia) }. 357 | Add Zify BinOp Op_Z_intmul. 358 | 359 | #[global] 360 | Instance Op_Z_scale : BinOp (@GRing.scale _ Z^o) := 361 | Op_Z_mulr. 362 | Add Zify BinOp Op_Z_scale. 363 | 364 | Fact Op_Z_exp_subproof n m : (n ^+ m)%R = (n ^ Z.of_nat m)%Z. 365 | Proof. by rewrite -Zpower_nat_Z; elim: m => //= m <-; rewrite exprS. Qed. 366 | 367 | #[global] 368 | Instance Op_Z_exp : BinOp (@GRing.exp _ : Z -> nat -> Z) := 369 | { TBOp := Z.pow; TBOpInj := Op_Z_exp_subproof }. 370 | Add Zify BinOp Op_Z_exp. 371 | 372 | #[global] 373 | Instance Op_unitZ : UnOp (has_quality 1 Instances.unitZ : Z -> bool) := 374 | { TUOp x := (x =? 1)%Z || (x =? - 1)%Z; TUOpInj _ := erefl }. 375 | Add Zify UnOp Op_unitZ. 376 | 377 | #[global] 378 | Instance Op_Z_unit : UnOp (has_quality 1 GRing.unit : Z -> bool) := Op_unitZ. 379 | Add Zify UnOp Op_Z_unit. 380 | 381 | #[global] 382 | Instance Op_invZ : UnOp Instances.invZ := { TUOp := id; TUOpInj _ := erefl }. 383 | Add Zify UnOp Op_invZ. 384 | 385 | #[global] 386 | Instance Op_Z_inv : UnOp (GRing.inv : Z -> Z) := 387 | { TUOp := id; TUOpInj _ := erefl }. 388 | Add Zify UnOp Op_Z_inv. 389 | 390 | #[global] 391 | Instance Op_Z_normr : UnOp (Num.norm : Z -> Z) := 392 | { TUOp := Z.abs; TUOpInj _ := erefl }. 393 | Add Zify UnOp Op_Z_normr. 394 | 395 | #[global] 396 | Instance Op_Z_sgr : UnOp (Num.sg : Z -> Z) := 397 | { TUOp := Z.sgn; TUOpInj := ltac:(case=> //=; lia) }. 398 | Add Zify UnOp Op_Z_sgr. 399 | 400 | #[global] 401 | Instance Op_Z_le : BinOp (<=%O : Z -> Z -> bool) := 402 | { TBOp := Z.leb; TBOpInj _ _ := erefl }. 403 | Add Zify BinOp Op_Z_le. 404 | 405 | #[global] 406 | Instance Op_Z_le' : BinOp (>=^d%O : rel Z^d) := Op_Z_le. 407 | Add Zify BinOp Op_Z_le'. 408 | 409 | #[global] 410 | Instance Op_Z_ge : BinOp (>=%O : Z -> Z -> bool) := 411 | { TBOp := Z.geb; TBOpInj := ltac:(simpl; lia) }. 412 | Add Zify BinOp Op_Z_ge. 413 | 414 | #[global] 415 | Instance Op_Z_ge' : BinOp (<=^d%O : rel Z^d) := Op_Z_ge. 416 | Add Zify BinOp Op_Z_ge'. 417 | 418 | #[global] 419 | Instance Op_Z_lt : BinOp (<%O : Z -> Z -> bool) := 420 | { TBOp := Z.ltb; TBOpInj _ _ := erefl }. 421 | Add Zify BinOp Op_Z_lt. 422 | 423 | #[global] 424 | Instance Op_Z_lt' : BinOp (>^d%O : rel Z^d) := Op_Z_lt. 425 | Add Zify BinOp Op_Z_lt'. 426 | 427 | #[global] 428 | Instance Op_Z_gt : BinOp (>%O : Z -> Z -> bool) := 429 | { TBOp := Z.gtb; TBOpInj := ltac:(simpl; lia) }. 430 | Add Zify BinOp Op_Z_gt. 431 | 432 | #[global] 433 | Instance Op_Z_gt' : BinOp (<^d%O : rel Z^d) := Op_Z_gt. 434 | Add Zify BinOp Op_Z_gt'. 435 | 436 | #[global] 437 | Instance Op_Z_min : BinOp (Order.min : Z -> Z -> Z) := 438 | { TBOp := Z.min; TBOpInj _ _ := ltac:(case: leP => /=; lia) }. 439 | Add Zify BinOp Op_Z_min. 440 | 441 | #[global] 442 | Instance Op_Z_min' : BinOp ((Order.max : Z^d -> _) : Z -> Z -> Z) := 443 | { TBOp := Z.min; TBOpInj _ _ := ltac:(case: leP => /=; lia) }. 444 | Add Zify BinOp Op_Z_min'. 445 | 446 | #[global] 447 | Instance Op_Z_max : BinOp (Order.max : Z -> Z -> Z) := 448 | { TBOp := Z.max; TBOpInj _ _ := ltac:(case: leP => /=; lia) }. 449 | Add Zify BinOp Op_Z_max. 450 | 451 | #[global] 452 | Instance Op_Z_max' : BinOp ((Order.min : Z^d -> _) : Z -> Z -> Z) := 453 | { TBOp := Z.max; TBOpInj _ _ := ltac:(case: leP => /=; lia) }. 454 | Add Zify BinOp Op_Z_max'. 455 | 456 | #[global] 457 | Instance Op_Z_meet : BinOp (Order.meet : Z -> Z -> Z) := 458 | { TBOp := Z.min; TBOpInj _ _ := ltac:(case: leP => /=; lia) }. 459 | Add Zify BinOp Op_Z_meet. 460 | 461 | #[global] 462 | Instance Op_Z_meet' : BinOp (Order.join : Z^d -> _) := Op_Z_min. 463 | Add Zify BinOp Op_Z_meet'. 464 | 465 | #[global] 466 | Instance Op_Z_join : BinOp (Order.join : Z -> Z -> Z) := 467 | { TBOp := Z.max; TBOpInj _ _ := ltac:(case: leP => /=; lia) }. 468 | Add Zify BinOp Op_Z_join. 469 | 470 | #[global] 471 | Instance Op_Z_join' : BinOp (Order.meet : Z^d -> _) := Op_Z_max. 472 | Add Zify BinOp Op_Z_join'. 473 | 474 | (******************************************************************************) 475 | (* intdiv *) 476 | (******************************************************************************) 477 | 478 | Fact Op_divz_subproof n m : 479 | Z_of_int (divz n m) = divZ (Z_of_int n) (Z_of_int m). 480 | Proof. case: n => [[|n]|n]; rewrite /divz /divZ /= ?addn1 /=; nia. Qed. 481 | 482 | #[global] 483 | Instance Op_divz : BinOp (divz : int -> int -> int) := 484 | { TBOp := divZ; TBOpInj := Op_divz_subproof }. 485 | Add Zify BinOp Op_divz. 486 | 487 | #[global] 488 | Instance Op_modz : BinOp modz := 489 | { TBOp := modZ; TBOpInj := ltac:(rewrite /= /modz; lia) }. 490 | Add Zify BinOp Op_modz. 491 | 492 | #[global] 493 | Instance Op_dvdz : BinOp dvdz := 494 | { TBOp n m := (modZ m n =? 0)%Z; 495 | TBOpInj _ _ := ltac:(apply/dvdz_mod0P/idP; lia) }. 496 | Add Zify BinOp Op_dvdz. 497 | 498 | Fact Op_gcdz_subproof n m : 499 | Z_of_int (gcdz n m) = Z.gcd (Z_of_int n) (Z_of_int m). 500 | Proof. rewrite /gcdz -Z.gcd_abs_l -Z.gcd_abs_r; lia. Qed. 501 | 502 | #[global] 503 | Instance Op_gcdz : BinOp gcdz := { TBOp := Z.gcd; TBOpInj := Op_gcdz_subproof }. 504 | Add Zify BinOp Op_gcdz. 505 | 506 | #[global] 507 | Instance Op_coprimez : BinOp coprimez := 508 | { TBOp x y := (Z.gcd x y =? 1)%Z; 509 | TBOpInj := ltac:(rewrite /= /coprimez; lia) }. 510 | Add Zify BinOp Op_coprimez. 511 | 512 | Module Exports. 513 | Add Zify CstOp Op_nat_0. 514 | Add Zify BinOp Op_nat_add. 515 | Add Zify CstOp Op_nat_1. 516 | Add Zify BinOp Op_nat_mul. 517 | Add Zify BinOp Op_nat_natmul. 518 | Add Zify BinOp Op_nat_exp. 519 | Add Zify CstOp Op_N_0. 520 | Add Zify BinOp Op_N_add. 521 | Add Zify CstOp Op_N_1. 522 | Add Zify BinOp Op_N_mul. 523 | Add Zify BinOp Op_N_natmul. 524 | Add Zify BinOp Op_N_exp. 525 | Add Zify InjTyp Inj_int_Z. 526 | Add Zify UnOp Op_Z_of_int. 527 | Add Zify UnOp Op_Posz. 528 | Add Zify UnOp Op_Negz. 529 | Add Zify BinRel Op_int_eq. 530 | Add Zify BinOp Op_int_eq_op. 531 | Add Zify CstOp Op_int_0. 532 | Add Zify BinOp Op_addz. 533 | Add Zify BinOp Op_int_add. 534 | Add Zify UnOp Op_oppz. 535 | Add Zify UnOp Op_int_opp. 536 | Add Zify CstOp Op_int_1. 537 | Add Zify BinOp Op_mulz. 538 | Add Zify BinOp Op_int_mulr. 539 | Add Zify BinOp Op_int_natmul. 540 | Add Zify BinOp Op_int_intmul. 541 | Add Zify BinOp Op_int_scale. 542 | Add Zify BinOp Op_int_exp. 543 | Add Zify UnOp Op_unitz. 544 | Add Zify UnOp Op_int_unit. 545 | Add Zify UnOp Op_invz. 546 | Add Zify UnOp Op_int_inv. 547 | Add Zify UnOp Op_absz. 548 | Add Zify UnOp Op_int_normr. 549 | Add Zify BinOp Op_lez. 550 | Add Zify BinOp Op_ltz. 551 | Add Zify UnOp Op_int_sgr. 552 | Add Zify UnOp Op_int_sgz. 553 | Add Zify BinOp Op_int_le. 554 | Add Zify BinOp Op_int_le'. 555 | Add Zify BinOp Op_int_ge. 556 | Add Zify BinOp Op_int_ge'. 557 | Add Zify BinOp Op_int_lt. 558 | Add Zify BinOp Op_int_lt'. 559 | Add Zify BinOp Op_int_gt. 560 | Add Zify BinOp Op_int_gt'. 561 | Add Zify BinOp Op_int_min. 562 | Add Zify BinOp Op_int_min'. 563 | Add Zify BinOp Op_int_max. 564 | Add Zify BinOp Op_int_max'. 565 | Add Zify BinOp Op_int_meet. 566 | Add Zify BinOp Op_int_meet'. 567 | Add Zify BinOp Op_int_join. 568 | Add Zify BinOp Op_int_join'. 569 | Add Zify BinOp Op_Z_eq_op. 570 | Add Zify CstOp Op_Z_0. 571 | Add Zify BinOp Op_Z_add. 572 | Add Zify UnOp Op_Z_opp. 573 | Add Zify CstOp Op_Z_1. 574 | Add Zify BinOp Op_Z_mulr. 575 | Add Zify BinOp Op_Z_natmul. 576 | Add Zify BinOp Op_Z_intmul. 577 | Add Zify BinOp Op_Z_scale. 578 | Add Zify BinOp Op_Z_exp. 579 | Add Zify UnOp Op_unitZ. 580 | Add Zify UnOp Op_Z_unit. 581 | Add Zify UnOp Op_invZ. 582 | Add Zify UnOp Op_Z_inv. 583 | Add Zify UnOp Op_Z_normr. 584 | Add Zify UnOp Op_Z_sgr. 585 | Add Zify BinOp Op_Z_le. 586 | Add Zify BinOp Op_Z_le'. 587 | Add Zify BinOp Op_Z_ge. 588 | Add Zify BinOp Op_Z_ge'. 589 | Add Zify BinOp Op_Z_lt. 590 | Add Zify BinOp Op_Z_lt'. 591 | Add Zify BinOp Op_Z_gt. 592 | Add Zify BinOp Op_Z_gt'. 593 | Add Zify BinOp Op_Z_min. 594 | Add Zify BinOp Op_Z_min'. 595 | Add Zify BinOp Op_Z_max. 596 | Add Zify BinOp Op_Z_max'. 597 | Add Zify BinOp Op_Z_meet. 598 | Add Zify BinOp Op_Z_meet'. 599 | Add Zify BinOp Op_Z_join. 600 | Add Zify BinOp Op_Z_join'. 601 | Add Zify BinOp Op_divz. 602 | Add Zify BinOp Op_modz. 603 | Add Zify BinOp Op_dvdz. 604 | Add Zify BinOp Op_gcdz. 605 | Add Zify BinOp Op_coprimez. 606 | End Exports. 607 | 608 | End AlgebraZifyInstances. 609 | Export SsreflectZifyInstances.Exports. 610 | Export AlgebraZifyInstances.Exports. 611 | -------------------------------------------------------------------------------- /theories/zify_ssreflect.v: -------------------------------------------------------------------------------- 1 | From Coq Require Import ZArith ZifyClasses ZifyInst ZifyBool. 2 | From Coq Require Export Lia. 3 | From Coq Require Znumtheory. 4 | 5 | From mathcomp Require Import ssreflect ssrfun ssrbool eqtype ssrnat seq path. 6 | From mathcomp Require Import div choice fintype tuple finfun bigop finset prime. 7 | From mathcomp Require Import order binomial. 8 | 9 | Set Implicit Arguments. 10 | Unset Strict Implicit. 11 | Unset Printing Implicit Defensive. 12 | 13 | Ltac Zify.zify_pre_hook ::= unfold is_true in *; do ?rewrite -> unfold_in in *. 14 | 15 | Module SsreflectZifyInstances. 16 | 17 | Import Order.Theory. 18 | 19 | #[global] 20 | Instance Op_bool_inj : UnOp (inj : bool -> bool) := 21 | { TUOp := id; TUOpInj _ := erefl }. 22 | Add Zify UnOp Op_bool_inj. 23 | 24 | #[global] 25 | Instance Op_nat_inj : UnOp (inj : nat -> Z) := Op_Z_of_nat. 26 | Add Zify UnOp Op_nat_inj. 27 | 28 | (******************************************************************************) 29 | (* ssrbool *) 30 | (******************************************************************************) 31 | 32 | #[global] 33 | Instance Op_addb : BinOp addb := 34 | { TBOp x y := Bool.eqb x (~~ y); TBOpInj := ltac:(by case=> [][]) }. 35 | Add Zify BinOp Op_addb. 36 | 37 | #[global] 38 | Instance Op_eqb : BinOp eqb := 39 | { TBOp := Bool.eqb; TBOpInj := ltac:(by case=> [][]) }. 40 | Add Zify BinOp Op_eqb. 41 | 42 | #[global] 43 | Instance Op_eq_op_bool : BinOp (eq_op : rel bool) := Op_eqb. 44 | Add Zify BinOp Op_eq_op_bool. 45 | 46 | #[global] 47 | Instance Op_bool_le : BinOp (<=%O : bool -> bool -> bool) := 48 | { TBOp := implb; TBOpInj := ltac:(by case=> [][]) }. 49 | Add Zify BinOp Op_bool_le. 50 | 51 | #[global] 52 | Instance Op_bool_le' : BinOp (>=^d%O : rel bool^d) := Op_bool_le. 53 | Add Zify BinOp Op_bool_le'. 54 | 55 | #[global] 56 | Instance Op_bool_ge : BinOp (>=%O : bool -> bool -> bool) := 57 | { TBOp x y := implb y x; TBOpInj := ltac:(by case=> [][]) }. 58 | Add Zify BinOp Op_bool_ge. 59 | 60 | #[global] 61 | Instance Op_bool_ge' : BinOp (<=^d%O : rel bool^d) := Op_bool_ge. 62 | Add Zify BinOp Op_bool_ge'. 63 | 64 | #[global] 65 | Instance Op_bool_lt : BinOp (<%O : bool -> bool -> bool) := 66 | { TBOp x y := ~~ x && y; TBOpInj := ltac:(by case=> [][]) }. 67 | Add Zify BinOp Op_bool_lt. 68 | 69 | #[global] 70 | Instance Op_bool_lt' : BinOp (>^d%O : rel bool^d) := Op_bool_lt. 71 | Add Zify BinOp Op_bool_lt'. 72 | 73 | #[global] 74 | Instance Op_bool_gt : BinOp (>%O : bool -> bool -> bool) := 75 | { TBOp x y := x && ~~ y; TBOpInj := ltac:(by case=> [][]) }. 76 | Add Zify BinOp Op_bool_gt. 77 | 78 | #[global] 79 | Instance Op_bool_gt' : BinOp (<^d%O : rel bool^d) := Op_bool_gt. 80 | Add Zify BinOp Op_bool_gt'. 81 | 82 | #[global] 83 | Instance Op_bool_min : BinOp (Order.min : bool -> bool -> bool) := 84 | { TBOp := andb; TBOpInj := ltac:(by case=> [][]) }. 85 | Add Zify BinOp Op_bool_min. 86 | 87 | #[global] 88 | Instance Op_bool_min' : 89 | BinOp ((Order.max : bool^d -> _) : bool -> bool -> bool) := 90 | { TBOp := andb; TBOpInj := ltac:(by case=> [][]) }. 91 | Add Zify BinOp Op_bool_min'. 92 | 93 | #[global] 94 | Instance Op_bool_max : BinOp (Order.max : bool -> bool -> bool) := 95 | { TBOp := orb; TBOpInj := ltac:(by case=> [][]) }. 96 | Add Zify BinOp Op_bool_max. 97 | 98 | #[global] 99 | Instance Op_bool_max' : 100 | BinOp ((Order.min : bool^d -> _) : bool -> bool -> bool) := 101 | { TBOp := orb; TBOpInj := ltac:(by case=> [][]) }. 102 | Add Zify BinOp Op_bool_max'. 103 | 104 | #[global] 105 | Instance Op_bool_meet : BinOp (Order.meet : bool -> bool -> bool) := Op_andb. 106 | Add Zify BinOp Op_bool_meet. 107 | 108 | #[global] 109 | Instance Op_bool_meet' : BinOp (Order.join : bool^d -> _) := Op_andb. 110 | Add Zify BinOp Op_bool_meet'. 111 | 112 | #[global] 113 | Instance Op_bool_join : BinOp (Order.join : bool -> bool -> bool) := Op_orb. 114 | Add Zify BinOp Op_bool_join. 115 | 116 | #[global] 117 | Instance Op_bool_join' : BinOp (Order.meet : bool^d -> _) := Op_orb. 118 | Add Zify BinOp Op_bool_join'. 119 | 120 | #[global] 121 | Instance Op_bool_bottom : CstOp (\bot : bool)%O := Op_false. 122 | Add Zify CstOp Op_bool_bottom. 123 | 124 | #[global] 125 | Instance Op_bool_bottom' : CstOp (\top : bool^d)%O := Op_false. 126 | Add Zify CstOp Op_bool_bottom'. 127 | 128 | #[global] 129 | Instance Op_bool_top : CstOp (\top : bool)%O := Op_true. 130 | Add Zify CstOp Op_bool_top. 131 | 132 | #[global] 133 | Instance Op_bool_top' : CstOp (\bot : bool^d)%O := Op_true. 134 | Add Zify CstOp Op_bool_top'. 135 | 136 | #[global] 137 | Instance Op_bool_sub : BinOp (Order.diff : bool -> bool -> bool) := 138 | { TBOp x y := x && ~~ y; TBOpInj := ltac:(by case=> [][]) }. 139 | Add Zify BinOp Op_bool_sub. 140 | 141 | #[global] 142 | Instance Op_bool_compl : UnOp (Order.compl : bool -> bool) := Op_negb. 143 | Add Zify UnOp Op_bool_compl. 144 | 145 | (******************************************************************************) 146 | (* ssrnat *) 147 | (******************************************************************************) 148 | 149 | #[global] 150 | Instance Op_eqn : BinOp eqn := Op_nat_eqb. 151 | Add Zify BinOp Op_eqn. 152 | 153 | #[global] 154 | Instance Op_eq_op_nat : BinOp (eq_op : rel nat) := Op_eqn. 155 | Add Zify BinOp Op_eq_op_nat. 156 | 157 | #[global] 158 | Instance Op_addn_rec : BinOp addn_rec := Op_plus. 159 | Add Zify BinOp Op_addn_rec. 160 | 161 | #[global] 162 | Instance Op_addn : BinOp addn := Op_plus. 163 | Add Zify BinOp Op_addn. 164 | 165 | #[global] 166 | Instance Op_addn_trec : BinOp NatTrec.add := 167 | { TBOp := Z.add; TBOpInj n m := ltac:(rewrite NatTrec.addE; lia) }. 168 | Add Zify BinOp Op_addn_trec. 169 | 170 | #[global] 171 | Instance Op_subn_rec : BinOp subn_rec := Op_sub. 172 | Add Zify BinOp Op_subn_rec. 173 | 174 | #[global] 175 | Instance Op_subn : BinOp subn := Op_sub. 176 | Add Zify BinOp Op_subn. 177 | 178 | #[global] 179 | Instance Op_muln_rec : BinOp muln_rec := Op_mul. 180 | Add Zify BinOp Op_muln_rec. 181 | 182 | #[global] 183 | Instance Op_muln : BinOp muln := Op_mul. 184 | Add Zify BinOp Op_muln. 185 | 186 | #[global] 187 | Instance Op_muln_trec : BinOp NatTrec.mul := 188 | { TBOp := Z.mul; TBOpInj n m := ltac:(rewrite NatTrec.mulE; lia) }. 189 | Add Zify BinOp Op_muln_trec. 190 | 191 | #[global] 192 | Instance Op_leq : BinOp leq := 193 | { TBOp := Z.leb; TBOpInj := ltac:(rewrite /leq; lia) }. 194 | Add Zify BinOp Op_leq. 195 | 196 | #[global] 197 | Instance Op_geq : BinOp (geq : nat -> nat -> bool) := 198 | { TBOp := Z.geb; TBOpInj := ltac:(simpl; lia) }. 199 | Add Zify BinOp Op_geq. 200 | 201 | #[global] 202 | Instance Op_ltn : BinOp (ltn : nat -> nat -> bool) := 203 | { TBOp := Z.ltb; TBOpInj := ltac:(simpl; lia) }. 204 | Add Zify BinOp Op_ltn. 205 | 206 | #[global] 207 | Instance Op_gtn : BinOp (gtn : nat -> nat -> bool) := 208 | { TBOp := Z.gtb; TBOpInj := ltac:(simpl; lia) }. 209 | Add Zify BinOp Op_gtn. 210 | 211 | #[global] 212 | Instance Op_minn : BinOp minn := 213 | { TBOp := Z.min; TBOpInj _ _ := ltac:(case: leqP; lia) }. 214 | Add Zify BinOp Op_minn. 215 | 216 | #[global] 217 | Instance Op_maxn : BinOp maxn := 218 | { TBOp := Z.max; TBOpInj _ _ := ltac:(case: leqP; lia) }. 219 | Add Zify BinOp Op_maxn. 220 | 221 | #[global] 222 | Instance Op_nat_of_bool : UnOp nat_of_bool := 223 | { TUOp := Z.b2z; TUOpInj := ltac:(by case) }. 224 | Add Zify UnOp Op_nat_of_bool. 225 | 226 | #[global] 227 | Instance Op_double : UnOp double := 228 | { TUOp := Z.mul 2; TUOpInj _ := ltac:(rewrite -muln2; lia) }. 229 | Add Zify UnOp Op_double. 230 | 231 | #[global] 232 | Instance Op_double_trec : UnOp NatTrec.double := 233 | { TUOp := Z.mul 2; TUOpInj _ := ltac:(rewrite NatTrec.doubleE; lia) }. 234 | Add Zify UnOp Op_double_trec. 235 | 236 | Fact Op_expn_subproof n m : Z.of_nat (n ^ m) = (Z.of_nat n ^ Z.of_nat m)%Z. 237 | Proof. rewrite -Zpower_nat_Z; elim: m => //= m <-; rewrite expnS; lia. Qed. 238 | 239 | #[global] 240 | Instance Op_expn_rec : BinOp expn_rec := 241 | { TBOp := Z.pow; TBOpInj := Op_expn_subproof }. 242 | Add Zify BinOp Op_expn_rec. 243 | 244 | #[global] 245 | Instance Op_expn : BinOp expn := Op_expn_rec. 246 | Add Zify BinOp Op_expn. 247 | 248 | #[global] 249 | Instance Op_expn_trec : BinOp NatTrec.exp := 250 | { TBOp := Z.pow; TBOpInj n m := ltac:(rewrite NatTrec.expE; lia) }. 251 | Add Zify BinOp Op_expn_trec. 252 | 253 | #[global] 254 | Instance Op_eq_op_N : BinOp (eq_op : N -> N -> bool) := 255 | { TBOp := Z.eqb; TBOpInj := ltac:(by case => [|n] []) }. 256 | Add Zify BinOp Op_eq_op_N. 257 | 258 | Fact nat_of_posE : nat_of_pos =1 Pos.to_nat. 259 | Proof. 260 | move=> p; rewrite /Pos.to_nat -[LHS]muln1. 261 | elim: p 1 => /= [p IHp | p IHp |] n; rewrite -?IHp; lia. 262 | Qed. 263 | 264 | #[global] 265 | Instance Op_nat_of_pos : UnOp nat_of_pos := 266 | { TUOp := id; TUOpInj n := ltac:(rewrite /= nat_of_posE; lia) }. 267 | Add Zify UnOp Op_nat_of_pos. 268 | 269 | #[global] 270 | Instance Op_nat_of_bin : UnOp nat_of_bin := 271 | { TUOp := id; TUOpInj := ltac:(case => //=; lia) }. 272 | Add Zify UnOp Op_nat_of_bin. 273 | 274 | Fact pos_of_natE n m : pos_of_nat n m = Pos.of_succ_nat (n * 2 - m). 275 | Proof. elim: n m => // n IHn [|[|m]] /=; rewrite IHn; lia. Qed. 276 | 277 | #[global] 278 | Instance Op_pos_of_nat : BinOp pos_of_nat := 279 | { TBOp n m := Z.max 1 (n * 2 - m + 1); 280 | TBOpInj n m := ltac:(rewrite /= pos_of_natE; lia) }. 281 | Add Zify BinOp Op_pos_of_nat. 282 | 283 | #[global] 284 | Instance Op_bin_of_nat : UnOp bin_of_nat := 285 | { TUOp := id; TUOpInj n := ltac:(rewrite /= -[n in RHS]bin_of_natK; lia) }. 286 | Add Zify UnOp Op_bin_of_nat. 287 | 288 | #[global] 289 | Instance Op_nat_le : BinOp (<=%O : rel nat) := Op_leq. 290 | Add Zify BinOp Op_nat_le. 291 | 292 | #[global] 293 | Instance Op_nat_le' : BinOp (>=^d%O : rel nat^d) := Op_leq. 294 | Add Zify BinOp Op_nat_le'. 295 | 296 | #[global] 297 | Instance Op_nat_ge : BinOp (>=%O : rel nat) := Op_geq. 298 | Add Zify BinOp Op_nat_ge. 299 | 300 | #[global] 301 | Instance Op_nat_ge' : BinOp (<=^d%O : rel nat^d) := Op_geq. 302 | Add Zify BinOp Op_nat_ge'. 303 | 304 | #[global] 305 | Instance Op_nat_lt : BinOp (<%O : rel nat) := Op_ltn. 306 | Add Zify BinOp Op_nat_lt. 307 | 308 | #[global] 309 | Instance Op_nat_lt' : BinOp (>^d%O : rel nat^d) := Op_ltn. 310 | Add Zify BinOp Op_nat_lt'. 311 | 312 | #[global] 313 | Instance Op_nat_gt : BinOp (>%O : rel nat) := Op_gtn. 314 | Add Zify BinOp Op_nat_gt. 315 | 316 | #[global] 317 | Instance Op_nat_gt' : BinOp (<^d%O : rel nat^d) := Op_gtn. 318 | Add Zify BinOp Op_nat_gt'. 319 | 320 | #[global] 321 | Instance Op_nat_min : BinOp (Order.min : nat -> _) := Op_minn. 322 | Add Zify BinOp Op_nat_min. 323 | 324 | #[global] 325 | Instance Op_nat_min' : BinOp ((Order.max : nat^d -> _) : nat -> nat -> nat) := 326 | { TBOp := Z.min; TBOpInj _ _ := ltac:(case: leP; lia) }. 327 | Add Zify BinOp Op_nat_min'. 328 | 329 | #[global] 330 | Instance Op_nat_max : BinOp (Order.max : nat -> _) := Op_maxn. 331 | Add Zify BinOp Op_nat_max. 332 | 333 | #[global] 334 | Instance Op_nat_max' : BinOp ((Order.min : nat^d -> _) : nat -> nat -> nat) := 335 | { TBOp := Z.max; TBOpInj _ _ := ltac:(case: leP; lia) }. 336 | Add Zify BinOp Op_nat_max'. 337 | 338 | #[global] 339 | Instance Op_nat_meet : BinOp (Order.meet : nat -> _) := Op_minn. 340 | Add Zify BinOp Op_nat_meet. 341 | 342 | #[global] 343 | Instance Op_nat_meet' : BinOp (Order.join : nat^d -> _) := Op_minn. 344 | Add Zify BinOp Op_nat_meet'. 345 | 346 | #[global] 347 | Instance Op_nat_join : BinOp (Order.join : nat -> _) := Op_maxn. 348 | Add Zify BinOp Op_nat_join. 349 | 350 | #[global] 351 | Instance Op_nat_join' : BinOp (Order.meet : nat^d -> _) := Op_maxn. 352 | Add Zify BinOp Op_nat_join'. 353 | 354 | #[global] 355 | Instance Op_nat_bottom : CstOp (\bot : nat)%O := Op_O. 356 | Add Zify CstOp Op_nat_bottom. 357 | 358 | (******************************************************************************) 359 | (* division / modulo: Since `divz` and `modz` of MathComp (defined in *) 360 | (* `intdiv.v`) are incompatible with the division and modulo functions for *) 361 | (* `Z` in the Coq standard library, here we have to define ones for `Z` which *) 362 | (* behave the same as `divz` and `modz`. *) 363 | (******************************************************************************) 364 | 365 | Definition divZ (m d : Z) : Z := 366 | Z.sgn d * 367 | match m with 368 | | Z0 => 0 369 | | Z.pos p => Z.of_nat (Pos.to_nat p %/ Z.abs_nat d)%N 370 | | Z.neg p => - Z.succ (Z.of_nat ((Pos.to_nat p).-1 %/ Z.abs_nat d)%N) 371 | end%Z. 372 | 373 | Definition modZ (m d : Z) : Z := (m - divZ m d * d)%Z. 374 | 375 | #[global] 376 | Instance Op_divZ : BinOp divZ := { TBOp := divZ; TBOpInj _ _ := erefl }. 377 | Add Zify BinOp Op_divZ. 378 | 379 | #[global] 380 | Instance Op_modZ : BinOp modZ := { TBOp := modZ; TBOpInj _ _ := erefl }. 381 | Add Zify BinOp Op_modZ. 382 | 383 | (* Reimplementation of Z.div_mod_to_equations (PreOmega.v) for divZ and modZ: *) 384 | 385 | Fact divZ_eq m d : m = (divZ m d * d + modZ m d)%Z. 386 | Proof. rewrite /modZ; lia. Qed. 387 | 388 | Fact modZ_ge0 m d : d <> 0%Z -> (0 <= modZ m d)%Z. 389 | Proof. 390 | by move: d m => [] // d [] // m _; rewrite /modZ /divZ [Z.abs_nat _]/=; 391 | move: (leq_trunc_div (Pos.to_nat m) (Pos.to_nat d)); 392 | move: (@ltn_ceil (Pos.to_nat m).-1 (Pos.to_nat d)); lia. 393 | Qed. 394 | 395 | Fact ltz_pmodZ m d : (0 < d)%Z -> (modZ m d < d)%Z. 396 | Proof. 397 | by move: d m => [] // d [] // m _; rewrite /modZ /divZ [Z.abs_nat _]/=; 398 | move: (leq_trunc_div (Pos.to_nat m).-1 (Pos.to_nat d)); 399 | move: (@ltn_ceil (Pos.to_nat m) (Pos.to_nat d)); lia. 400 | Qed. 401 | 402 | Fact ltz_nmodZ m d : (d < 0)%Z -> (modZ m d < - d)%Z. 403 | Proof. 404 | move: d m => [] // d [] // m _; rewrite /modZ /divZ [Z.abs_nat _]/=; 405 | move: (leq_trunc_div (Pos.to_nat m).-1 (Pos.to_nat d)); 406 | move: (@ltn_ceil (Pos.to_nat m) (Pos.to_nat d)); lia. 407 | Qed. 408 | 409 | Fact divZ0 m d : d = 0%Z -> divZ m d = 0%Z. 410 | Proof. by move=> ->. Qed. 411 | 412 | Ltac divZ_modZ_to_equations := 413 | let divZ_modZ_to_equations' m d := 414 | pose proof (@divZ_eq m d); 415 | pose proof (@modZ_ge0 m d); 416 | pose proof (@ltz_pmodZ m d); 417 | pose proof (@ltz_nmodZ m d); 418 | pose proof (@divZ0 m d); 419 | let q := fresh "q" in 420 | let r := fresh "r" in 421 | set (q := divZ m d) in *; 422 | set (r := modZ m d) in *; 423 | (* Find [divZ ?m' ?d'] and [modZ ?m' ?d'] that are convertible with *) 424 | (* [divZ m d] and [modZ m d] respectively. *) 425 | repeat 426 | match goal with 427 | | |- context [divZ ?m' ?d'] => change (divZ m' d') with q 428 | | |- context [modZ ?m' ?d'] => change (modZ m' d') with r 429 | | H : context [divZ ?m' ?d'] |- _ => change (divZ m' d') with q in H 430 | | H : context [modZ ?m' ?d'] |- _ => change (modZ m' d') with r in H 431 | end; 432 | clearbody q r 433 | in 434 | repeat 435 | match goal with 436 | | [ |- context [divZ ?m ?d] ] => divZ_modZ_to_equations' m d 437 | | [ |- context [modZ ?m ?d] ] => divZ_modZ_to_equations' m d 438 | | [ H : context [divZ ?m ?d] |- _] => divZ_modZ_to_equations' m d 439 | | [ H : context [modZ ?m ?d] |- _] => divZ_modZ_to_equations' m d 440 | end. 441 | 442 | Ltac Zify.zify_post_hook ::= elim_bool_cstr; divZ_modZ_to_equations. 443 | 444 | (******************************************************************************) 445 | (* div (divn, modn, dvdn, gcdn, lcmn, and coprime) *) 446 | (******************************************************************************) 447 | 448 | Fact Op_divn_subproof n m : Z.of_nat (n %/ m) = divZ (Z.of_nat n) (Z.of_nat m). 449 | Proof. 450 | by case: n m => [|n] [|m]; rewrite /divZ //= ?SuccNat2Pos.id_succ; case: divn. 451 | Qed. 452 | 453 | #[global] 454 | Instance Op_divn : BinOp divn := { TBOp := divZ; TBOpInj := Op_divn_subproof }. 455 | Add Zify BinOp Op_divn. 456 | 457 | #[global] 458 | Instance Op_modn : BinOp modn := 459 | { TBOp := modZ; TBOpInj n m := ltac:(move: (divn_eq n m); lia) }. 460 | Add Zify BinOp Op_modn. 461 | 462 | #[global] 463 | Instance Op_dvdn : BinOp dvdn := 464 | { TBOp x y := (modZ y x =? 0)%Z; TBOpInj := ltac:(rewrite /dvdn; lia) }. 465 | Add Zify BinOp Op_dvdn. 466 | 467 | #[global] 468 | Instance Op_odd : UnOp odd := 469 | { TUOp x := (modZ x 2 =? 1)%Z; TUOpInj n := ltac:(case: odd (modn2 n); lia) }. 470 | Add Zify UnOp Op_odd. 471 | 472 | #[global] 473 | Instance Op_odd_trec : UnOp NatTrec.odd := 474 | { TUOp x := (modZ x 2 =? 1)%Z; 475 | TUOpInj n := ltac:(rewrite NatTrec.oddE; lia) }. 476 | Add Zify UnOp Op_odd_trec. 477 | 478 | #[global] 479 | Instance Op_half : UnOp half := 480 | { TUOp x := divZ x 2; TUOpInj _ := ltac:(rewrite -divn2; lia) }. 481 | Add Zify UnOp Op_half. 482 | 483 | #[global] 484 | Instance Op_uphalf : UnOp uphalf := 485 | { TUOp x := divZ (x + 1)%Z 2; TUOpInj _ := ltac:(rewrite uphalf_half; lia) }. 486 | Add Zify UnOp Op_uphalf. 487 | 488 | Fact Op_gcdn_subproof n m : 489 | Z.of_nat (gcdn n m) = Z.gcd (Z.of_nat n) (Z.of_nat m). 490 | Proof. 491 | apply/esym/Z.gcd_unique; first by case: gcdn. 492 | - case/dvdnP: (dvdn_gcdl n m) => k {2}->; exists (Z.of_nat k); lia. 493 | - case/dvdnP: (dvdn_gcdr n m) => k {2}->; exists (Z.of_nat k); lia. 494 | - move=> k [n' Hkn] [m' Hkm]. 495 | suff/dvdnP [k' ->]: Z.abs_nat k %| gcdn n m. 496 | by apply/Znumtheory.Zdivide_Zabs_l; exists (Z.of_nat k'); lia. 497 | rewrite dvdn_gcd; apply/andP; split; apply/dvdnP; 498 | [exists (Z.abs_nat n') | exists (Z.abs_nat m')]; nia. 499 | Qed. 500 | 501 | #[global] 502 | Instance Op_gcdn : BinOp gcdn := { TBOp := Z.gcd; TBOpInj := Op_gcdn_subproof }. 503 | Add Zify BinOp Op_gcdn. 504 | 505 | Fact Op_lcmn_subproof n m : 506 | Z.of_nat (lcmn n m) = Z.lcm (Z.of_nat n) (Z.of_nat m). 507 | Proof. 508 | case: n m => [|n][|m]; rewrite ?lcmn0 // /lcmn /Z.lcm -Op_gcdn_subproof. 509 | case/dvdnP: (dvdn_gcdr n.+1 m.+1) => k {1 3}->. 510 | rewrite mulnA mulnK ?gcdn_gt0 // !Nat2Z.inj_mul Z_div_mult_full //; first nia. 511 | by case: (gcdn _ _) (gcdn_gt0 n.+1 m.+1). 512 | Qed. 513 | 514 | #[global] 515 | Instance Op_lcmn : BinOp lcmn := { TBOp := Z.lcm; TBOpInj := Op_lcmn_subproof }. 516 | Add Zify BinOp Op_lcmn. 517 | 518 | #[global] 519 | Instance Op_coprime : BinOp coprime := 520 | { TBOp x y := (Z.gcd x y =? 1)%Z; 521 | TBOpInj := ltac:(rewrite /= /coprime; lia) }. 522 | Add Zify BinOp Op_coprime. 523 | 524 | (******************************************************************************) 525 | (* natdvd in order.v *) 526 | (******************************************************************************) 527 | 528 | #[global] 529 | Instance Op_natdvd_le : BinOp (<=%O : rel natdvd) := Op_dvdn. 530 | Add Zify BinOp Op_natdvd_le. 531 | 532 | #[global] 533 | Instance Op_natdvd_le' : BinOp (>=^d%O : rel natdvd^d) := Op_dvdn. 534 | Add Zify BinOp Op_natdvd_le'. 535 | 536 | #[global] 537 | Instance Op_natdvd_ge : BinOp ((>=%O : rel natdvd) : nat -> nat -> bool) := 538 | { TBOp x y := (modZ x y =? 0)%Z; TBOpInj := ltac:(simpl; lia) }. 539 | Add Zify BinOp Op_natdvd_ge. 540 | 541 | #[global] 542 | Instance Op_natdvd_ge' : BinOp (<=^d%O : rel natdvd^d) := Op_natdvd_ge. 543 | Add Zify BinOp Op_natdvd_ge'. 544 | 545 | #[global] 546 | Instance Op_natdvd_lt : BinOp ((<%O : rel natdvd) : nat -> nat -> bool) := 547 | { TBOp x y := ~~ (y =? x)%Z && (modZ y x =? 0)%Z; 548 | TBOpInj _ _ := ltac:(rewrite /= sdvdEnat; lia) }. 549 | Add Zify BinOp Op_natdvd_lt. 550 | 551 | #[global] 552 | Instance Op_natdvd_lt' : BinOp (>^d%O : rel natdvd^d) := Op_natdvd_lt. 553 | Add Zify BinOp Op_natdvd_lt'. 554 | 555 | #[global] 556 | Instance Op_natdvd_gt : BinOp ((>%O : rel natdvd) : nat -> nat -> bool) := 557 | { TBOp x y := ~~ (x =? y)%Z && (modZ x y =? 0)%Z; 558 | TBOpInj _ _ := ltac:(rewrite /= sdvdEnat; lia) }. 559 | Add Zify BinOp Op_natdvd_gt. 560 | 561 | #[global] 562 | Instance Op_natdvd_gt' : BinOp (<^d%O : rel natdvd^d) := Op_natdvd_gt. 563 | Add Zify BinOp Op_natdvd_gt'. 564 | 565 | #[global] 566 | Instance Op_natdvd_meet : BinOp (Order.meet : natdvd -> _) := Op_gcdn. 567 | Add Zify BinOp Op_natdvd_meet. 568 | 569 | #[global] 570 | Instance Op_natdvd_meet' : BinOp (Order.join : natdvd^d -> _) := Op_gcdn. 571 | Add Zify BinOp Op_natdvd_meet'. 572 | 573 | #[global] 574 | Instance Op_natdvd_join : BinOp (Order.join : natdvd -> _) := Op_lcmn. 575 | Add Zify BinOp Op_natdvd_join. 576 | 577 | #[global] 578 | Instance Op_natdvd_join' : BinOp (Order.meet : natdvd^d -> _) := Op_lcmn. 579 | Add Zify BinOp Op_natdvd_join'. 580 | 581 | #[global] 582 | Instance Op_natdvd_bottom : CstOp (\bot : natdvd)%O := 583 | { TCst := 1%Z; TCstInj := erefl }. 584 | Add Zify CstOp Op_natdvd_bottom. 585 | 586 | #[global] 587 | Instance Op_natdvd_bottom' : CstOp (\top : natdvd^d)%O := Op_natdvd_bottom. 588 | Add Zify CstOp Op_natdvd_bottom'. 589 | 590 | #[global] 591 | Instance Op_natdvd_top : CstOp (\top : natdvd)%O := Op_O. 592 | Add Zify CstOp Op_natdvd_top. 593 | 594 | #[global] 595 | Instance Op_natdvd_top' : CstOp (\bot : natdvd^d)%O := Op_O. 596 | Add Zify CstOp Op_natdvd_top'. 597 | 598 | Module Exports. 599 | (* Add Zify UnOp Op_bool_inj. *) 600 | (* Add Zify UnOp Op_nat_inj. *) 601 | Add Zify BinOp Op_addb. 602 | Add Zify BinOp Op_eqb. 603 | Add Zify BinOp Op_eq_op_bool. 604 | Add Zify BinOp Op_bool_le. 605 | Add Zify BinOp Op_bool_le'. 606 | Add Zify BinOp Op_bool_ge. 607 | Add Zify BinOp Op_bool_ge'. 608 | Add Zify BinOp Op_bool_lt. 609 | Add Zify BinOp Op_bool_lt'. 610 | Add Zify BinOp Op_bool_gt. 611 | Add Zify BinOp Op_bool_gt'. 612 | Add Zify BinOp Op_bool_min. 613 | Add Zify BinOp Op_bool_min'. 614 | Add Zify BinOp Op_bool_max. 615 | Add Zify BinOp Op_bool_max'. 616 | Add Zify BinOp Op_bool_meet. 617 | Add Zify BinOp Op_bool_meet'. 618 | Add Zify BinOp Op_bool_join. 619 | Add Zify BinOp Op_bool_join'. 620 | Add Zify CstOp Op_bool_bottom. 621 | Add Zify CstOp Op_bool_bottom'. 622 | Add Zify CstOp Op_bool_top. 623 | Add Zify CstOp Op_bool_top'. 624 | Add Zify BinOp Op_bool_sub. 625 | Add Zify UnOp Op_bool_compl. 626 | Add Zify BinOp Op_eqn. 627 | Add Zify BinOp Op_eq_op_nat. 628 | Add Zify BinOp Op_addn_rec. 629 | Add Zify BinOp Op_addn. 630 | Add Zify BinOp Op_addn_trec. 631 | Add Zify BinOp Op_subn_rec. 632 | Add Zify BinOp Op_subn. 633 | Add Zify BinOp Op_muln_rec. 634 | Add Zify BinOp Op_muln. 635 | Add Zify BinOp Op_muln_trec. 636 | Add Zify BinOp Op_leq. 637 | Add Zify BinOp Op_geq. 638 | Add Zify BinOp Op_ltn. 639 | Add Zify BinOp Op_gtn. 640 | Add Zify BinOp Op_minn. 641 | Add Zify BinOp Op_maxn. 642 | Add Zify UnOp Op_nat_of_bool. 643 | Add Zify UnOp Op_double. 644 | Add Zify UnOp Op_double_trec. 645 | Add Zify BinOp Op_expn_rec. 646 | Add Zify BinOp Op_expn. 647 | Add Zify BinOp Op_expn_trec. 648 | Add Zify BinOp Op_eq_op_N. 649 | Add Zify UnOp Op_nat_of_pos. 650 | Add Zify UnOp Op_nat_of_bin. 651 | Add Zify BinOp Op_pos_of_nat. 652 | Add Zify UnOp Op_bin_of_nat. 653 | Add Zify BinOp Op_nat_le. 654 | Add Zify BinOp Op_nat_le'. 655 | Add Zify BinOp Op_nat_ge. 656 | Add Zify BinOp Op_nat_ge'. 657 | Add Zify BinOp Op_nat_lt. 658 | Add Zify BinOp Op_nat_lt'. 659 | Add Zify BinOp Op_nat_gt. 660 | Add Zify BinOp Op_nat_gt'. 661 | Add Zify BinOp Op_nat_min. 662 | Add Zify BinOp Op_nat_min'. 663 | Add Zify BinOp Op_nat_max. 664 | Add Zify BinOp Op_nat_max'. 665 | Add Zify BinOp Op_nat_meet. 666 | Add Zify BinOp Op_nat_meet'. 667 | Add Zify BinOp Op_nat_join. 668 | Add Zify BinOp Op_nat_join'. 669 | Add Zify CstOp Op_nat_bottom. 670 | Add Zify BinOp Op_divZ. 671 | Add Zify BinOp Op_modZ. 672 | Add Zify BinOp Op_divn. 673 | Add Zify BinOp Op_modn. 674 | Add Zify BinOp Op_dvdn. 675 | Add Zify UnOp Op_odd. 676 | Add Zify UnOp Op_odd_trec. 677 | Add Zify UnOp Op_half. 678 | Add Zify UnOp Op_uphalf. 679 | Add Zify BinOp Op_gcdn. 680 | Add Zify BinOp Op_lcmn. 681 | Add Zify BinOp Op_coprime. 682 | Add Zify BinOp Op_natdvd_le. 683 | Add Zify BinOp Op_natdvd_le'. 684 | Add Zify BinOp Op_natdvd_ge. 685 | Add Zify BinOp Op_natdvd_ge'. 686 | Add Zify BinOp Op_natdvd_lt. 687 | Add Zify BinOp Op_natdvd_lt'. 688 | Add Zify BinOp Op_natdvd_gt. 689 | Add Zify BinOp Op_natdvd_gt'. 690 | Add Zify BinOp Op_natdvd_meet. 691 | Add Zify BinOp Op_natdvd_meet'. 692 | Add Zify BinOp Op_natdvd_join. 693 | Add Zify BinOp Op_natdvd_join'. 694 | Add Zify CstOp Op_natdvd_bottom. 695 | Add Zify CstOp Op_natdvd_bottom'. 696 | Add Zify CstOp Op_natdvd_top. 697 | Add Zify CstOp Op_natdvd_top'. 698 | End Exports. 699 | 700 | End SsreflectZifyInstances. 701 | Export SsreflectZifyInstances.Exports. 702 | --------------------------------------------------------------------------------