(************************************************************************) (* * The Coq Proof Assistant / The Coq Development Team *) (* v * Copyright INRIA, CNRS and contributors *) (* t -> t val sub : t -> t -> t val mul : t -> t -> t val div : t -> t -> t val neg : t -> t val sign : t -> int val equal : t -> t -> bool val compare : t -> t -> int val power_int : t -> int -> t val quomod : t -> t -> t * t val ppcm : t -> t -> t val gcd : t -> t -> t val lcm : t -> t -> t val to_string : t -> string end module Z = struct (* Beware this only works fine in ZArith >= 1.10 due to https://github.com/ocaml/Zarith/issues/58 *) include Z (* Constants *) let two = Z.of_int 2 let ten = Z.of_int 10 let power_int = Big_int_Z.power_big_int_positive_int let quomod = Big_int_Z.quomod_big_int (* zarith fails with division by zero if x == 0 && y == 0 *) let lcm x y = if Z.equal x zero && Z.equal y zero then zero else Z.lcm x y let ppcm x y = let g = gcd x y in let x' = Z.div x g in let y' = Z.div y g in Z.mul g (Z.mul x' y') end module type QArith = sig module Z : ZArith type t val of_int : int -> t val zero : t val one : t val two : t val ten : t val minus_one : t module Notations : sig val ( // ) : t -> t -> t val ( +/ ) : t -> t -> t val ( -/ ) : t -> t -> t val ( */ ) : t -> t -> t val ( =/ ) : t -> t -> bool val ( <>/ ) : t -> t -> bool val ( >/ ) : t -> t -> bool val ( >=/ ) : t -> t -> bool val ( t -> bool val ( <=/ ) : t -> t -> bool end val compare : t -> t -> int val make : Z.t -> Z.t -> t val den : t -> Z.t val num : t -> Z.t val of_bigint : Z.t -> t val to_bigint : t -> Z.t val neg : t -> t (* val inv : t -> t *) val max : t -> t -> t val min : t -> t -> t val sign : t -> int val abs : t -> t val mod_ : t -> t -> t val floor : t -> t (* val floorZ : t -> Z.t *) val ceiling : t -> t val round : t -> t val pow2 : int -> t val pow10 : int -> t val power : int -> t -> t val to_string : t -> string val of_string : string -> t val to_float : t -> float end module Q : QArith with module Z = Z = struct module Z = Z let pow_check_exp x y = let z_res = if y = 0 then Z.one else if y > 0 then Z.pow x y else (* s < 0 *) Z.pow x (abs y) in let z_res = Q.of_bigint z_res in if 0 <= y then z_res else Q.inv z_res include Q let two = Q.(of_int 2) let ten = Q.(of_int 10) module Notations = struct let ( // ) = Q.div let ( +/ ) = Q.add let ( -/ ) = Q.sub let ( */ ) = Q.mul let ( =/ ) = Q.equal let ( <>/ ) x y = not (Q.equal x y) let ( >/ ) = Q.gt let ( >=/ ) = Q.geq let ( Q.of_bigint let ceiling q : t = Z.cdiv (Q.num q) (Q.den q) |> Q.of_bigint let half = Q.make Z.one Z.two (* We imitate Num's round which is to the nearest *) let round q = floor (Q.add half q) (* XXX: review / improve *) let quo x y = let s = sign y in let res = floor (x / abs y) in if Int.equal s (-1) then neg res else res let mod_ x y = x - (y * quo x y) (* XXX: review / improve *) (* Note that Z.pow doesn't support negative exponents *) let pow2 y = pow_check_exp Z.two y let pow10 y = pow_check_exp Z.ten y let power (x : int) (y : t) : t = let y = try Q.to_int y with Z.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") *) in pow_check_exp (Z.of_int x) y end