with Ada.Strings.Fixed; package body Rationals is function Reduce (Numerator, Denominator : in Integer) return Fraction is A : Integer := Numerator; B : Integer := Denominator; Temp : Integer; 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 * Right, Left.Den); end "+"; function "+" (Left : in Integer; Right : in Fraction) return Fraction is begin return Reduce (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 * Right, Left.Den); end "-"; function "-" (Left : in Integer; Right : in Fraction) return Fraction is begin return Reduce (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 * Right, Right); end "*"; function "*" (Left : in Integer; Right : in Fraction) return Fraction is begin return Reduce (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 * Right); end "/"; function "/" (Left : in Integer; Right : in Fraction) return Fraction is begin return Reduce (Right.Num, Left * Right.Den); end "/"; function "/" (Left, Right : in Integer) return Fraction is begin return Reduce (Left, 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 = Right and Left.Den = 1; end "="; function "=" (Left : in Integer; Right : in Fraction) return Boolean is begin return 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 * Right; end "<="; function "<=" (Left : in Integer; Right : in Fraction) return Boolean is begin return 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 * Right; end "<"; function "<" (Left : in Integer; Right : in Fraction) return Boolean is begin return 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 * Right; end ">="; function ">=" (Left : in Integer; Right : in Fraction) return Boolean is begin return 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 * Right; end ">"; function ">" (Left : in Integer; Right : in Fraction) return Boolean is begin return Left * Right.Den > Right.Num; end ">"; function Numerator (Item : in Fraction) return Integer is begin return Item.Num; end Numerator; function Denominator (Item : in Fraction) return Integer is begin return Item.Den; end Denominator; function Floor (Item : in Fraction) return Integer is begin return Item.Num / Item.Den; end Floor; function Ceiling (Item : in Fraction) return Integer is begin if Item.Num mod Item.Den = 0 then return Item.Num / Item.Den; else return 1 + Item.Num / Item.Den; end if; end Ceiling; function Round (Item : in Fraction) return Integer is begin if Item.Num mod Item.Den >= Standard."/" (Item.Den, 2) then return 1 + Item.Num / Item.Den; else return Item.Num / Item.Den; end if; end Round; function Image (Item : in Fraction) return String is use Ada.Strings; use Ada.Strings.Fixed; begin return Trim (Integer'Image (Item.Num), Left) & '/' & Trim (Integer'Image (Item.Den), Left); 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 (A, B); end Value; end Rationals;