with Ada.Text_IO, Ada.Numerics.Float_Random;
use Ada.Text_IO, Ada.Numerics.Float_Random;
with Ada.Numerics.Generic_Elementary_Functions,FltStr;

pragma Elaborate_All(Ada.Text_IO,Ada.Numerics.Float_Random);
pragma Elaborate_All(Ada.Numerics.Generic_Elementary_Functions,FltStr);

package Flts is

  type LLFloat is new Long_Long_Float;
  type Flt is new LLFloat;

  package LLFloat_FS is new FltStr(LLFloat);
  package LLFloat_IO renames LLFloat_FS.Flt_IO;
  package LLFloat_EF is new Ada.Numerics.Generic_Elementary_Functions(LLFloat);
  package Flt_FS is new FltStr(Flt);
  package Flt_IO renames Flt_FS.Flt_IO;
  package Flt_EF is new Ada.Numerics.Generic_Elementary_Functions(Flt);

  function RMin(R1,R2: Flt) return Flt renames Flt'Min;
  function RMax(R1,R2: Flt) return Flt renames Flt'Max;
  function RMin(R1,R2,R3: Flt) return Flt;
  function RMax(R1,R2,R3: Flt) return Flt;
  function Sqr(R: Flt) return Flt;
  function NPower(R: Flt; N: Natural) return Flt;
  function Convert(K: Integer) return Flt;
  function Frac(N: Integer; D: Positive) return Flt;
  function Between(A,B: Flt; P: Natural; Q: Positive) return Flt;
  function Scaled(Eps: in Flt; Binary_Digits: in Positive) return Flt;
  function Epsilon(Eps: in Flt; Binary_Digits: in Positive) return Flt;
  function Simple_Random return Flt;                                    -- in [-1,1]
  procedure Reset_Random(I: Integer);

  procedure Put(P: in File_Access; R: in Flt; F: in Field := Flt_IO.Default_Fore;
                                              A: in Field := Flt_IO.Default_Aft; E: in Field := Flt_IO.Default_Exp) renames Flt_FS.Put;
  procedure Put(F: in File_Type; R: in Flt; Decimal: in Boolean := False) renames Flt_FS.Put;
  procedure Get(F: in File_Type; R: in out Flt; Decimal: in Boolean := False) renames Flt_FS.Get;
  function Prompt(N: String) return Flt renames Flt_FS.Prompt;
  function GetArg return Flt renames Flt_FS.GetArg;
  procedure Show1(N: in String; R: in Flt; NewLine: in Boolean := True) renames Flt_FS.Show1;
  procedure Show2(N: in String; R1,R2: in Flt; NewLine: in Boolean := True) renames Flt_FS.Show2;
  procedure Show3(N: in String; R1,R2,R3: in Flt; NewLine: in Boolean := True) renames Flt_FS.Show3;

  Zero:    constant Flt := Flt(0);
  One:     constant Flt := Flt(1);
  Two:     constant Flt := Flt(2);
  Three:   constant Flt := Flt(3);
  Four:    constant Flt := Flt(4);
  Five:    constant Flt := Flt(5);
  NegOne:  constant Flt := Flt(-1);
  Half:    constant Flt := One/Two;
  NegHalf: constant Flt := NegOne/Two;
  Half3:   constant Flt := Three/Two;
  Quarter: constant Flt := One/Four;

  subtype Radius is Flt range Zero .. Flt'Last;
  type RadVec is array(Integer range <>) of Radius;
  subtype RadPair is RadVec(1..2);

  function Max(P: RadVec) return Radius;
  function Min(P1,P2: RadPair) return RadPair;
  function Max(P1,P2: RadPair) return RadPair;
  procedure Swap(P1,P2: in out RadPair);
  function Between(P1,P2: RadPair; R: Flt := Half) return RadPair;   -- purely numerical
  function PowersOf(R: Radius; MaxPower: Positive) return RadVec;

  Zero_RadPair: constant RadPair := (Zero,Zero);
  Gen: Generator;
  A_Numeric_Mode: access procedure := null; -- set later when needed

  pragma Inline_Always (Min,Max,Swap,Simple_Random);

end Flts;
