59 lines
1.8 KiB
Plaintext
59 lines
1.8 KiB
Plaintext
(* implementation conforming to signature *)
|
|
module Frac : RATIO =
|
|
struct
|
|
open Big_int
|
|
|
|
type t = { num : big_int; den : big_int }
|
|
|
|
(* short aliases for big_int values and functions *)
|
|
let zero, one = zero_big_int, unit_big_int
|
|
let big, to_int, eq = big_int_of_int, int_of_big_int, eq_big_int
|
|
let (+~), (-~), ( *~) = add_big_int, sub_big_int, mult_big_int
|
|
|
|
(* helper function *)
|
|
let rec norm ({num=n;den=d} as k) =
|
|
if lt_big_int d zero then
|
|
norm {num=minus_big_int n;den=minus_big_int d}
|
|
else
|
|
let rec hcf a b =
|
|
let q,r = quomod_big_int a b in
|
|
if eq r zero then b else hcf b r in
|
|
let f = hcf n d in
|
|
if eq f one then k else
|
|
let div = div_big_int in
|
|
{ num=div n f; den = div d f } (* inefficient *)
|
|
|
|
(* public functions *)
|
|
let frac a b = norm { num=big a; den=big b }
|
|
|
|
let from_int a = norm { num=big a; den=one }
|
|
|
|
let is_int {num=n; den=d} =
|
|
eq d one ||
|
|
eq (mod_big_int n d) zero
|
|
|
|
let to_string ({num=n; den=d} as r) =
|
|
let r1 = norm r in
|
|
let str = string_of_big_int in
|
|
if is_int r1 then
|
|
str (r1.num)
|
|
else
|
|
str (r1.num) ^ "/" ^ str (r1.den)
|
|
|
|
let cmp a b =
|
|
let a1 = norm a and b1 = norm b in
|
|
compare_big_int (a1.num*~b1.den) (b1.num*~a1.den)
|
|
|
|
let ( */ ) {num=n1; den=d1} {num=n2; den=d2} =
|
|
norm { num = n1*~n2; den = d1*~d2 }
|
|
|
|
let ( // ) {num=n1; den=d1} {num=n2; den=d2} =
|
|
norm { num = n1*~d2; den = d1*~n2 }
|
|
|
|
let ( +/ ) {num=n1; den=d1} {num=n2; den=d2} =
|
|
norm { num = n1*~d2 +~ n2*~d1; den = d1*~d2 }
|
|
|
|
let ( -/ ) {num=n1; den=d1} {num=n2; den=d2} =
|
|
norm { num = n1*~d2 -~ n2*~d1; den = d1*~d2 }
|
|
end
|