with Ada.Strings.Fixed; package body Rationals is function Reduce (Numerator, Denominator : in Big_Unsigned) return Fraction is A : Big_Unsigned := Numerator; B : Big_Unsigned := Denominator; Temp : Big_Unsigned; begin -- Euclid's algorithm loop Temp := A; A := B; B := Temp mod B; exit when B = 0; end loop; return (Num => Numerator / A, Den => Denominator / A); end Reduce; function "+" (Left, Right : in Fraction) return Fraction is begin return Reduce (Left.Num * Right.Den + Left.Den * Right.Num, Left.Den * Right.Den); end "+"; function "+" (Left : in Fraction; Right : in Integer) return Fraction is begin return Reduce (Left.Num + Left.Den * Utils.To_Big_Unsigned (Word (Right)), Left.Den); end "+"; function "+" (Left : in Integer; Right : in Fraction) return Fraction is begin return Reduce (Utils.To_Big_Unsigned (Word (Left)) * Right.Den + Right.Num, Right.Den); end "+"; function "-" (Left, Right : in Fraction) return Fraction is begin return Reduce (Left.Num * Right.Den - Left.Den * Right.Num, Left.Den * Right.Den); end "-"; function "-" (Left : in Fraction; Right : in Integer) return Fraction is begin return Reduce (Left.Num - Left.Den * Utils.To_Big_Unsigned (Word (Right)), Left.Den); end "-"; function "-" (Left : in Integer; Right : in Fraction) return Fraction is begin return Reduce (Utils.To_Big_Unsigned (Word (Left)) * Right.Den - Right.Num, Right.Den); end "-"; function "-" (Right : in Fraction) return Fraction is begin return (Num => - Right.Num, Den => Right.Den); end "-"; function "*" (Left, Right : in Fraction) return Fraction is begin return Reduce (Left.Num * Right.Num, Left.Den * Right.Den); end "*"; function "*" (Left : in Fraction; Right : in Integer) return Fraction is begin return Reduce (Left.Num * Utils.To_Big_Unsigned (Word (Right)), Left.Den); end "*"; function "*" (Left : in Integer; Right : in Fraction) return Fraction is begin return Reduce (Utils.To_Big_Unsigned (Word (Left)) * Right.Num, Right.Den); end "*"; function "/" (Left, Right : in Fraction) return Fraction is begin return Reduce (Left.Num * Right.Den, Left.Den * Right.Num); end "/"; function "/" (Left : in Fraction; Right : in Integer) return Fraction is begin return Reduce (Left.Num, Left.Den * Utils.To_Big_Unsigned (Word (Right))); end "/"; function "/" (Left : in Integer; Right : in Fraction) return Fraction is begin return Reduce (Right.Num, Utils.To_Big_Unsigned (Word (Left)) * Right.Den); end "/"; function "/" (Left, Right : in Integer) return Fraction is begin return Reduce (Utils.To_Big_Unsigned (Word (Left)), Utils.To_Big_Unsigned (Word (Right))); end "/"; function "=" (Left, Right : in Fraction) return Boolean is begin return Left.Num = Right.Num and Left.Den = Right.Den; end "="; function "=" (Left : in Fraction; Right : in Integer) return Boolean is begin return Left.Num = Utils.To_Big_Unsigned (Word (Right)) and Left.Den = 1; end "="; function "=" (Left : in Integer; Right : in Fraction) return Boolean is begin return Utils.To_Big_Unsigned (Word (Left)) = Right.Num and Right.Den = 1; end "="; function "<=" (Left, Right : in Fraction) return Boolean is begin return Left.Num * Right.Den <= Left.Den * Right.Num; end "<="; function "<=" (Left : in Fraction; Right : in Integer) return Boolean is begin return Left.Num <= Left.Den * Utils.To_Big_Unsigned (Word (Right)); end "<="; function "<=" (Left : in Integer; Right : in Fraction) return Boolean is begin return Utils.To_Big_Unsigned (Word (Left)) * Right.Den <= Right.Num; end "<="; function "<" (Left, Right : in Fraction) return Boolean is begin return Left.Num * Right.Den < Left.Den * Right.Num; end "<"; function "<" (Left : in Fraction; Right : in Integer) return Boolean is begin return Left.Num < Left.Den * Utils.To_Big_Unsigned (Word (Right)); end "<"; function "<" (Left : in Integer; Right : in Fraction) return Boolean is begin return Utils.To_Big_Unsigned (Word (Left)) * Right.Den < Right.Num; end "<"; function ">=" (Left, Right : in Fraction) return Boolean is begin return Left.Num * Right.Den >= Left.Den * Right.Num; end ">="; function ">=" (Left : in Fraction; Right : in Integer) return Boolean is begin return Left.Num >= Left.Den * Utils.To_Big_Unsigned (Word (Right)); end ">="; function ">=" (Left : in Integer; Right : in Fraction) return Boolean is begin return Utils.To_Big_Unsigned (Word (Left)) * Right.Den >= Right.Num; end ">="; function ">" (Left, Right : in Fraction) return Boolean is begin return Left.Num * Right.Den > Left.Den * Right.Num; end ">"; function ">" (Left : in Fraction; Right : in Integer) return Boolean is begin return Left.Num > Left.Den * Utils.To_Big_Unsigned (Word (Right)); end ">"; function ">" (Left : in Integer; Right : in Fraction) return Boolean is begin return Utils.To_Big_Unsigned (Word (Left)) * Right.Den > Right.Num; end ">"; function Numerator (Item : in Fraction) return Integer is begin return Integer (Utils.To_Words (Item.Num)(1)); end Numerator; function Denominator (Item : in Fraction) return Integer is begin return Integer (Utils.To_Words (Item.Den)(1)); end Denominator; function Floor (Item : in Fraction) return Integer is begin return Integer (Utils.To_Words (Item.Num / Item.Den)(0)); end Floor; function Ceiling (Item : in Fraction) return Integer is begin if Item.Num mod Item.Den = 0 then return Integer (Utils.To_Words (Item.Num / Item.Den)(1)); else return 1 + Integer (Utils.To_Words (Item.Num / Item.Den)(1)); end if; end Ceiling; function Round (Item : in Fraction) return Integer is begin if Item.Num mod Item.Den >= Item.Den / 2 then return 1 + Integer (Utils.To_Words (Item.Num / Item.Den)(1)); else return Integer (Utils.To_Words (Item.Num / Item.Den)(1)); end if; end Round; function Image (Item : in Fraction) return String is begin return Utils.To_String (Item.Num) & '/' & Utils.To_String (Item.Den); end Image; function Value (Item : in String) return Fraction is use Ada.Strings; use Ada.Strings.Fixed; A, B, S : Integer; begin S := Index (Item, "/"); A := Integer'Value (Item (Item'First .. S - 1)); B := Integer'Value (Item (S + 1 .. Item'Last)); return Reduce (Utils.To_Big_Unsigned (Word (A)), Utils.To_Big_Unsigned (Word (B))); end Value; end Rationals;