module type COMPARABLE = sig type t val eq: t -> t -> bool val neq: t -> t -> bool val lt: t -> t -> bool val le: t -> t -> bool val gt: t -> t -> bool val ge: t -> t -> bool end module Comparable = struct let eq = (=) let neq = (<>) let lt = (<) let le = (<=) let gt = (>) let ge = (>=) end module Num = struct let rnd () = let value = Random.bits () in Q.make (Z.of_int value) (Z.of_int (1 lsl 30)) include Q let is_integer t = (Q.den t) == Z.one let eq = Q.equal let neq a b = not (Q.equal a b) let mult = Q.mul let floor t = let num = Q.num t and den = Q.den t in if is_integer t then Q.of_bigint num else Q.of_bigint @@ Z.fdiv num den let round_down t = let num = Q.num t and den = Q.den t in if is_integer t then Q.of_bigint num else Q.of_bigint @@ Z.div num den let round t = if is_integer t then t else let t' = match Q.sign t with | 1 -> Q.add t @@ Q.of_ints 1 2 | -1 -> Q.add t @@ Q.of_ints (-1) 2 | _ -> t in let num = Q.num t' and den = Q.den t' in Q.of_bigint (Z.div num den) let ge = Q.geq let ge = Q.geq let le = Q.leq let pow t q_factor = begin if is_integer q_factor then let factor = Q.to_int q_factor and num = Q.num t and den = Q.den t in Q.make (Z.pow num factor) (Z.pow den factor) else let factor = Q.to_float q_factor and num = Z.to_float @@ Q.num t and den = Z.to_float @@ Q.den t in Q.div (Q.of_float (num ** factor)) (Q.of_float (den ** factor)) end let gcd t1 t2 = Q.of_bigint @@ Z.gcd (Q.to_bigint t1) (Q.to_bigint t2) let lcm t1 t2 = Q.of_bigint @@ Z.lcm (Q.to_bigint t1) (Q.to_bigint t2) end module Bool = struct type t = bool include Comparable let true_ = true let false_ = false let or_ = (||) let and_ = (&&) let not = Pervasives.not end module String = struct type t = UTF8.t include Comparable end module Date = Date.Make(Num)