with Ada.Text_IO;
use Ada.Text_IO;

pragma Elaborate_All (Ada.Text_IO);

package Rationals is  --- not for major computations

  subtype LInt is Long_Long_Integer;

  package LInt_IO is new Ada.Text_IO.Integer_IO (LInt);

  function GCD(N,D: LInt) return LInt;
  function Width(I: LInt; Base: Positive := 10) return Positive;
  function Value(S: String) return LInt;
  procedure Show1(N: in String; I: in LInt; NewLine: in Boolean := True);
  function Prompt(N: String) return LInt;

  type Rational is private;

  function LRat(N: Lint; D: LInt := 1) return Rational;
  function IRat(N: Integer; D: Integer := 1) return Rational;
  function LNum(Q: Rational) return Lint;
  function INum(Q: Rational) return Integer;
  function LDen(Q: Rational) return Lint;
  function IDen(Q: Rational) return Integer;
  function LFloor(Q: Rational) return LInt;
  function IFloor(Q: Rational) return Integer;
  function LCeiling(Q: Rational) return LInt;
  function ICeiling(Q: Rational) return Integer;

  function "-"(Q: Rational) return Rational;
  function "+"(P,Q: Rational) return Rational;
  function "-"(P,Q: Rational) return Rational;
  function "*"(P,Q: Rational) return Rational;
  function "/" (P,Q: Rational) return Rational;
  function "mod"(P,Q: Rational) return Rational;
  function Inv(Q: Rational) return Rational;
  function Sqr(Q: Rational) return Rational;
  function "abs"(Q: Rational) return Rational;
  function "<"(P,Q: Rational) return Boolean;

  function "+"(I: Integer; Q: Rational) return Rational;
  function "+"(Q: Rational; I: Integer) return Rational;
  function "-"(I: Integer; Q: Rational) return Rational;
  function "-"(Q: Rational; I: Integer) return Rational;
  function "*"(I: Integer; Q: Rational) return Rational;
  function "*"(Q: Rational; I: Integer) return Rational;
  function "/"(N,D: Integer) return Rational renames IRat;
  function "/"(I: Integer; Q: Rational) return Rational;
  function "/"(Q: Rational; I: Integer) return Rational;
  function "mod"(P: Rational; I: Integer) return Rational;

  function Value(S: String) return Rational;
  procedure Show1(N: in String; Q: in Rational; NewLine: in Boolean := True);
  function Prompt(N: String) return Rational;
  function GetArg return Rational;

  function EvenOverOdd(Q: Rational) return Boolean;
  function OddOverEven(Q: Rational) return Boolean;
  function OddOverOdd(Q: Rational) return Boolean;

private

  subtype Nonnegative_Lint is Lint range 0 .. LInt'Last;

  type Rational is
    record
      Num: Lint;
      Den: Nonnegative_LInt;
    end record;

  function "/"(N,D: LInt) return Rational renames LRat;
  function Normalize(Q: Rational) return Rational; --- should not be needed

end Rationals;
