123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169(************************************************************************)(* * The Rocq Prover / The Rocq Development Team *)(* v * Copyright INRIA, CNRS and contributors *)(* <O___,, * (see version control and CREDITS file for authors & dates) *)(* \VV/ **************************************************************)(* // * This file is distributed under the terms of the *)(* * GNU Lesser General Public License Version 2.1 *)(* * (see LICENSE file for the text of the license) *)(************************************************************************)moduletypeZArith=sigtypetvalzero:tvalone:tvaltwo:tvaladd:t->t->tvalsub:t->t->tvalmul:t->t->tvaldiv:t->t->tvalneg:t->tvalsign:t->intvalequal:t->t->boolvalcompare:t->t->intvalpower_int:t->int->tvalquomod:t->t->t*tvalppcm:t->t->tvalgcd:t->t->tvallcm:t->t->tvalto_string:t->stringendmoduleZ=struct(* Beware this only works fine in ZArith >= 1.10 due to
https://github.com/ocaml/Zarith/issues/58 *)includeZ(* Constants *)lettwo=Z.of_int2letten=Z.of_int10letpower_int=Big_int_Z.power_big_int_positive_intletquomod=Big_int_Z.quomod_big_int(* zarith fails with division by zero if x == 0 && y == 0 *)letlcmxy=ifZ.equalxzero&&Z.equalyzerothenzeroelseZ.lcmxyletppcmxy=letg=gcdxyinletx'=Z.divxginlety'=Z.divyginZ.mulg(Z.mulx'y')endmoduletypeQArith=sigmoduleZ:ZArithtypetvalof_int:int->tvalzero:tvalone:tvaltwo:tvalten:tvalminus_one:tmoduleNotations:sigval(//):t->t->tval(+/):t->t->tval(-/):t->t->tval(*/):t->t->tval(=/):t->t->boolval(<>/):t->t->boolval(>/):t->t->boolval(>=/):t->t->boolval(</):t->t->boolval(<=/):t->t->boolendvalcompare:t->t->intvalmake:Z.t->Z.t->tvalden:t->Z.tvalnum:t->Z.tvalof_bigint:Z.t->tvalto_bigint:t-> Z.tvalneg:t->t(* val inv : t -> t *)valmax:t->t->tvalmin:t->t->tvalsign:t->intvalabs:t->tvalmod_:t->t->tvalfloor:t->t(* val floorZ : t -> Z.t *)valceiling:t->tvalround:t->tvalpow2:int->tvalpow10:int->tvalpower:int->t->tvalto_string:t->stringvalof_string:string->tvalto_float:t->floatendmoduleQ:QArithwithmoduleZ=Z=structmoduleZ=Zletpow_check_expxy=letz_res=ify=0thenZ.oneelseify>0thenZ.powxyelse(* s < 0 *)Z.powx(absy)inletz_res=Q.of_bigintz_resinif0<=ythenz_reselseQ.invz_resincludeQlettwo=Q.(of_int2)letten=Q.(of_int10)moduleNotations=structlet(//)=Q.divlet(+/)=Q.addlet(-/)=Q.sublet(*/)=Q.mullet(=/)=Q.equallet(<>/)xy=not(Q.equalxy)let(>/)=Q.gtlet(>=/)=Q.geqlet(</)=Q.ltlet(<=/)=Q.leqend(* XXX: review / improve *)letfloorZq:Z.t=Z.fdiv(numq)(denq)letfloorq:t=floorZq|>Q.of_bigintletceilingq:t=Z.cdiv(Q.numq)(Q.denq)|>Q.of_bigintlethalf=Q.makeZ.oneZ.two(* We imitate Num's round which is to the nearest *)letroundq=floor(Q.addhalfq)(* XXX: review / improve *)letquoxy=lets=signyinletres=floor(x/absy)inifInt.equals(-1)thennegreselseresletmod_xy=x-(y*quoxy)(* XXX: review / improve *)(* Note that Z.pow doesn't support negative exponents *)letpow2y=pow_check_expZ.twoyletpow10y=pow_check_expZ.tenyletpower(x:int)(y:t):t=lety=tryQ.to_intywithZ.Overflow->(* XXX: make doesn't link Pp / CErrors for csdpcert, that could be fixed *)raise(Invalid_argument"[micromega] overflow in exponentiation")(* CErrors.user_err (Pp.str "[micromega] overflow in exponentiation") *)inpow_check_exp(Z.of_intx)yend