with Logicals, Scalars, Rationals;
use Logicals, Scalars, Rationals;

pragma Elaborate_All (Logicals,Scalars,Rationals);

package Flts.Std is

  --- auxiliary
  procedure NOP(Dummy: in out LLFloat);
  procedure NOP(Dummy: in out Flt);
  procedure NOP(Dummy1: in Flt; Dummy2: in out LLFloat);
  function ReturnTrue(Dummy: LLFloat) return Boolean;
  function ReturnTrue(Dummy: Flt) return Boolean;
  function IsZero(S: LLFloat) return Boolean;
  procedure SetZero(S: in out LLFloat);
  procedure SetZero(Dummy: in Flt; S: in out LLFloat);
  procedure SetZero(Dummy: in LLFloat; S: in out LLFloat);
  function ReturnZero(Dummy: LLFloat) return Flt;
  function ReturnZero(Dummy: Flt) return LLFloat;
  function ReturnZero(Dummy: LLFloat) return LLFloat;
  procedure Copy(S1: in LLFloat; S2: in out LLFloat);
  function Copy(S: LLFloat) return LLFloat;
  function Approx(S: LLFloat) return Flt;
  function FirstArg(Q: Rational; Dummy: Flt) return LLFloat;
  function FirstArg(S: LLFloat; Dummy: Flt) return LLFloat;
  procedure Between(S1,S2: in Flt; S3: in out LLFloat);
  function Between(S1,S2: Flt) return LLFloat;
  procedure Between(S1: in LLFloat; S2: in out LLFloat);
  function Between(S1,S2: LLFloat) return LLFloat;

  pragma Inline_Always (NOP,ReturnTrue,IsZero,SetZero,ReturnZero,Copy,Approx,FirstArg,Between);

  --- basic
  function Info(Dummy: LLFloat) return Scalar_Info;
  function IsSharp(S: LLFloat) return Boolean renames ReturnTrue;
  function IsSharp(S: Flt) return Boolean renames ReturnTrue;
  function IsNumbers(S: LLFloat) return Boolean renames ReturnTrue;
  procedure SetSmallZero(S: in out LLFloat) renames SetZero;
  procedure Swap(S1,S2: in out LLFloat);

  --- sets
  function Center0(S: LLFloat) return Boolean renames IsZero;
  function Contains0(S: LLFloat) return Logical;
  function Contains(S1,S2: LLFloat) return Logical;
  procedure BallAt0(R: in Flt; S: in out LLFloat) renames SetZero;
  function BallAt0(R: Flt) return LLFloat renames ReturnZero;
  procedure DiskAt0(R: in Flt; S: in out LLFloat) renames SetZero;
  function DiskAt0(R: Flt) return LLFloat renames ReturnZero;
  procedure ToErr(S: in out LLFloat) renames SetZero;
  procedure ToErr(S1: in LLFloat; S2: in out LLFloat) renames SetZero;
  function ToErr(S: LLFloat) return LLFloat renames ReturnZero;
  procedure Center(S: in out LLFloat) renames NOP;
  procedure Center(S: in out Flt) renames NOP;
  procedure Center(S1: in LLFloat; S2: in out LLFloat) renames Copy;
  function Center(S: LLFloat) return LLFloat renames Copy;
  procedure CenterDisk(S: in out LLFloat) renames NOP;
  procedure CenterDisk(S1: in LLFloat; S2: in out LLFloat) renames Copy;
  function CenterDisk(S: LLFloat) return LLFloat renames Copy;
  procedure ModCenter(S: in out LLFloat) renames SetZero;
  procedure ModCenter(S1: in LLFloat; S2: in out LLFloat) renames SetZero;
  function ModCenter(S: LLFloat) return LLFloat renames ReturnZero;
  procedure ModNumbers(S: in out LLFloat) renames SetZero;
  procedure ModNumbers(S1: in LLFloat; S2: in out LLFloat) renames SetZero;
  function ModNumbers(S: LLFloat) return LLFloat renames ReturnZero;
  procedure ErrMult(R: in Radius; S: in out LLFloat) renames NOP;
  procedure Union(S1: in LLFloat; S2: in out LLFloat) renames Between;
  function Union(S1,S2: LLFloat) return LLFloat renames Between;
  procedure Intersection(S1: in LLFloat; S2: in out LLFloat; Empty: out Logical);

  --- order
  function Sign(S: LLFloat) return Integer;
  function Compare(R: Flt; S: LLFloat) return Integer;
  function Compare(S1,S2: LLFloat) return Integer;
  procedure Min(S1: in LLFloat; S2: in out LLFloat);
  procedure Min(S1,S2: in LLFloat; S3: in out LLFloat);
  function Min(S1,S2: LLFloat) return LLFloat renames LLFloat'Min;
  procedure Max(S1: in LLFloat; S2: in out LLFloat);
  procedure Max(S1,S2: in LLFloat; S3: in out LLFloat);
  function Max(S1,S2: LLFloat) return LLFloat renames LLFloat'Max;
  function Inf(S: LLFloat) return Flt renames Approx;
  function Sup(S: LLFloat) return Flt renames Approx;
  function LFloor(R: LLFloat) return LInt;
  function LCeiling(R: LLFloat) return LInt;

  --- arithmetic
  procedure Neg(S: in out LLFloat);
  procedure Neg(S1: in LLFloat; S2: in out LLFloat);
  procedure Add(I: in Integer; S: in out LLFloat);
  procedure Add(S1: in LLFloat; S2: in out LLFloat);
  procedure Sum(S1,S2: in LLFloat; S3: in out LLFloat);
  procedure Sub(S1: in LLFloat; S2: in out LLFloat);
  procedure Diff(S1,S2: in LLFloat; S3: in out LLFloat);
  function "*"(R: Flt; S: LLFloat) return LLFloat;
  procedure Mult(R: in Flt; S,Dummy: in out LLFloat);
  procedure Mult(R: in Flt; S: in out LLFloat);
  procedure Prod(R: in Flt; S1: in LLFloat; S2: in out LLFloat);
  procedure AddProd(R: in Flt; S1: in LLFloat; S2,Dummy: in out LLFloat);
  procedure AddProd(R: in Flt; S1: in LLFloat; S2: in out LLFloat);
  procedure Mult(Q: in Rational; S: in out LLFloat);
  procedure Mult(S1: in LLFloat; S2: in out LLFloat);
  procedure Prod(S1,S2: in LLFloat; S3: in out LLFloat);
  procedure AddProd(S1,S2: in LLFloat; S3,Dummy: in out LLFloat);
  procedure AddProd(S1,S2: in LLFloat; S3: in out LLFloat);
  procedure SumProd(S1,S2,S3: in LLFloat; S4: in out LLFloat);
  procedure SubProd(S1,S2: in LLFloat; S3,Dummy: in out LLFloat);
  procedure Div(R: in Flt; S,Dummy: in out LLFloat);
  procedure Div(R: in Flt; S: in out LLFloat);
  procedure Quot(S1: in LLFloat; R: in Flt; S2: in out LLFloat);
  function "/"(S: LLFloat; R: Flt) return LLFloat;
  procedure Div(S1: in LLFloat; S2: in out LLFloat);
  procedure Quot(S1,S2: in LLFloat; S3: in out LLFloat);
  procedure Inv(S1: in LLFloat; S2: in out LLFloat);
  function Inv(S: LLFloat) return LLFloat;

  --- fun
  function IsReal(S: LLFloat) return Boolean renames ReturnTrue;
  procedure Adjoint(S: in out LLFloat) renames NOP;
  procedure Adjoint(S1: in LLFloat; S2: in out LLFloat) renames Copy;
  function Adjoint(S: LLFloat) return LLFloat renames Copy;
  procedure Real_Part(R: in out LLFloat) renames NOP;
  function Real_Part(R: LLFloat) return LLFloat renames Copy;
  procedure Imag_Part(R: in out LLFloat) renames SetZero;
  function Imag_Part(R: LLFloat) return LLFloat renames ReturnZero;
  procedure Eval0(S: in out LLFloat) renames NOP;
  procedure Norm(S1: in LLFloat; S2: in out LLFloat);
  function Norm(S: LLFloat) return LLFloat renames "abs";
  function MaxNorm(S: LLFloat) return Radius;
  procedure Sqr(S: in out LLFloat);
  procedure Sqr(S1: in LLFloat; S2: in out LLFloat);
  function Sqr(S: LLFloat) return LLFloat;
  procedure Sqrt(S1: in LLFloat; S2: in out LLFloat);
  function Sqrt(S: LLFloat) return LLFloat renames LLFloat_EF.Sqrt;
  procedure Root(K: Positive; S1: in LLFloat; S2: in out LLFloat);
  function Root(K: Positive; S: LLFloat) return LLFloat;
  procedure Exp(S1: in LLFloat; S2: in out LLFloat);
  function Exp(S: LLFloat) return LLFloat renames LLFLoat_EF.Exp;
  procedure Log(S1: in LLFloat; S2: in out LLFloat);
  function Log(S: LLFloat) return LLFloat renames LLFLoat_EF.Log;
  procedure ArcCos(S1: in LLFloat; S2: in out LLFloat);
  function ArcCos(S: LLFloat) return LLFloat renames LLFLoat_EF.ArcCos;
  procedure ArcSin(S1: in LLFloat; S2: in out LLFloat);
  function ArcSin(S: LLFloat) return LLFloat renames LLFLoat_EF.ArcSin;
  procedure Cos(S1: in LLFloat; S2: in out LLFloat);
  function Cos(S: LLFloat) return LLFloat renames LLFLoat_EF.Cos;
  procedure Sin(S1: in LLFloat; S2: in out LLFloat);
  function Sin(S: LLFloat) return LLFloat renames LLFLoat_EF.Sin;
  procedure Simple_Random(S: in out LLFloat);
  function Pi return LLFloat;
  procedure IPower(I: in Integer; S1: in LLFloat; S2,Dummy: in out LLFloat);
  procedure QPower(Q: in Rational; S1: in LLFloat; S2: in out LLFloat);
  procedure Roots2(B,C: in LLFloat; U1,U2,V: in out LLFloat);
  procedure Roots3(B,C,D: in LLFloat; U0,U1,U2,V: in out LLFloat);

  --- conversion, io
  procedure Assign(I: in Integer; S: in out LLFloat);
  procedure Assign(Q: in Rational; S: in out LLFloat);
  procedure Assign(R: in Flt; S: in out LLFloat);
  function Scal(I: Integer) return LLFloat;
  function Scal(Q: Rational) return LLFloat;
  function Scal(R: Flt) return LLFloat;
  procedure Enclose(R1,R2: in Flt; S: in out LLFloat) renames Between;
  function Enclose(R1,R2: Flt) return LLFloat renames Between;
  function Interval(R1,R2: Flt) return LLFloat renames Between;
  procedure Interval(R1,R2: in Flt; S: in out LLFloat) renames Between;
  function Val(S: LLFloat; R: Flt) return LLFloat renames FirstArg;
  procedure ValDec(N: in String; R: in out LLFloat);
  function ValDec(N: String) return LLFloat renames LLFloat'Value;
  procedure ValHex(N: in String; R: in out LLFloat; Rounded: out Boolean) renames LLFloat_FS.ValHex;
  function ValHex(N: String) return LLFloat renames LLFloat_FS.ValHex;
  function DecStr(S: LLFloat; Digs: Natural := 0) return String renames LLFloat_FS.DecStr;
  function HexStr(S: LLFloat; Digs: Natural := 0) return String renames LLFloat_FS.HexStr;
  procedure Show1(N: in String; S: in LLFloat; NewLine: in Boolean := True) renames LLFloat_FS.Show1;
  procedure Show2(N: in String; S1,S2: in LLFloat; NewLine: in Boolean := True) renames LLFloat_FS.Show2;
  procedure Show3(N: in String; S1,S2,S3: in LLFloat; NewLine: in Boolean := True) renames LLFloat_FS.Show3;
  procedure Put(F: in File_Type; S: in LLFloat; Decimal: in Boolean := False) renames LLFloat_FS.Put;
  procedure Get(F: in File_Type; S: in out LLFloat; Decimal: in Boolean := False) renames LLFloat_FS.Get;
  procedure Write(FileName: in String; S: in LLFloat; Decimal: in Boolean := False) renames LLFloat_FS.Write;
  procedure Read(FileName: in String; S: in out LLFloat; Decimal: in Boolean := False) renames LLFloat_FS.Read;

  subtype Rep is LLFloat;

  procedure Val(S: in LLFloat; R: in out Rep) renames Copy;
  function Val(S: LLFloat) return Rep renames Copy;
  function Upper(S: Rep) return LLFloat renames Copy;
  function Lower(S: Rep) return LLFloat renames Copy;
  procedure PutStd(S: in LLFloat; C,R: out LLFloat);
  procedure PutStd(S: in LLFloat; C,R,B: out LLFloat);
  procedure GetStd(C,Dummy: in LLFloat; S: in out LLFloat);
  procedure GetStd(C,Dummy1,Dummy2: in LLFloat; S: in out LLFloat);
  procedure PutNum(S: in LLFloat; R: in out Rep) renames Copy;
  procedure GetNum(R: in Rep; S: in out LLFloat) renames Copy;

  --- misc
  procedure Ceiling(S1: in LLFloat; S2: in out LLFloat);
  function Ceiling(S1: LLFloat) return LLFloat renames LLFloat'Ceiling;
  function Ceiling(S1: Flt) return Flt;
  procedure Floor(S1: in LLFloat; S2: in out LLFloat);
  function Floor(S1: LLFloat) return LLFloat renames LLFloat'Floor;
  function Floor(S1: Flt) return Flt;
  procedure Round(S1: in LLFloat; S2: in out LLFloat);
  function Round(S1: LLFloat) return LLFloat renames LLFloat'Rounding;
  function Scaled(Eps: Flt) return Flt;
  function Epsilon(Eps: Flt) return Flt;
  procedure Set_Precision(Dummy: in Positive);
  function Set_Precision(Dummy: Positive) return Positive;
  procedure Set_Precision(Dummy1: in Positive; Dummy2: in LLFloat);
  function Get_Precision(Dummy: LLFloat) return Positive;
  procedure Proper_Rounding;
  procedure Proper_Rounding(Dummy: in LLFloat);
  procedure Free_Cache(Dummy: in LLFloat);
  procedure Put_Numeric(N: in Positive; S: in Rep);     --- a primitive buffer
  procedure Get_Numeric(N: in Positive; S: in out Rep); --- a primitive buffer

  Scalar_IsNumeric: constant Boolean := True;
  Just_Rounded: Boolean renames LLFloat_FS.Rounded_Last;

  pragma Inline_Always (Scal,Swap,Min,Max,Neg,Add,Sum,Sub,Diff,Mult,Prod,AddProd,Div,Quot,Inv,Norm);

private

  LL_Precision: constant Positive := LLFloat'Machine_Mantissa;
  RepZero:      constant LLFloat  := LLFloat(Zero);
  RepOne:       constant LLFloat  := LLFloat(One);
  RepNegOne:    constant LLFloat  := LLFloat(NegOne);
  RepTwo:       constant LLFloat  := LLFloat(Two);
  RepHalf:      constant LLFloat  := LLFloat(Half);
  LFirst:       constant LLFloat  := LLFloat(LInt'First);
  LLast:        constant LLFloat  := LLFloat(LInt'Last);

end Flts.Std;
