with Ada.Text_IO, Rationals, Logicals, Flts, Scalars;
use Ada.Text_IO, Rationals, Logicals, Flts, Scalars;
with Matrices;

pragma Elaborate_All (Ada.Text_IO,Rationals,Logicals,Flts);
pragma Elaborate_All (Matrices);

generic

  PDeg: in Positive;

  -------------------- begin_include scalars Scalar

  type Scalar is private;

  --- basic
  with function Info(Dummy: Scalar) return Scalar_Info is <>;
  with function IsSharp(S: Scalar) return Boolean is <>;
  with function IsZero(S: Scalar) return Boolean is <>;
  with function "="(S1,S2: Scalar) return Boolean is <>;
  with procedure SetZero(S: in out Scalar) is <>;
  with procedure Copy(S1: in Scalar; S2: in out Scalar) is <>;
  with procedure Swap(S1,S2: in out Scalar) is <>;

  --- sets
  with function Center0(S: Scalar) return Boolean is <>;
  with function Contains0(S: Scalar) return Logical is <>;
  with function Contains(S1,S2: Scalar) return Logical is <>;
  with procedure BallAt0(R: in Flt; S: in out Scalar) is <>;
  with function BallAt0(R: Flt) return Scalar is <>;
  with procedure ToErr(S: in out Scalar) is <>;
  with procedure ToErr(S1: in Scalar; S2: in out Scalar) is <>;
  with function ToErr(S: Scalar) return Scalar is <>;
  with procedure Center(S: in out Scalar) is <>;
  with procedure Center(S1: in Scalar; S2: in out Scalar) is <>;
  with function Center(S: Scalar) return Scalar is <>;
  with procedure ModCenter(S: in out Scalar) is <>;
  with procedure ModCenter(S1: in Scalar; S2: in out Scalar) is <>;
  with function ModCenter(S: Scalar) return Scalar is <>;
  with procedure ErrMult(R: in Radius; S: in out Scalar) is <>;
  with procedure Union(S1: in Scalar; S2: in out Scalar) is <>;
  with function Union(S1,S2: Scalar) return Scalar is <>;
  with procedure Intersection(S1: in Scalar; S2: in out Scalar; Empty: out Logical) is <>;

  --- order
  with function Sign(S: Scalar) return Integer is <>;
  with function Compare(S1,S2: Scalar) return Integer is <>; --- sign of S1-S2
  with function "<"(S1,S2: Scalar) return Boolean is <>;
  with function "<="(S1,S2: Scalar) return Boolean is <>;
  with function ">"(S1,S2: Scalar) return Boolean is <>;
  with function ">="(S1,S2: Scalar) return Boolean is <>;
  with procedure Min(S1: in Scalar; S2: in out Scalar) is <>;
  with procedure Min(S1,S2: in Scalar; S3: in out Scalar) is <>;
  with function Min(S1,S2: Scalar) return Scalar is <>;
  with procedure Max(S1: in Scalar; S2: in out Scalar) is <>;
  with procedure Max(S1,S2: in Scalar; S3: in out Scalar) is <>;
  with function Max(S1,S2: Scalar) return Scalar is <>;
  with function Inf(S: Scalar) return Flt is <>; -- inf of real part
  with function Sup(S: Scalar) return Flt is <>; -- sup of real part

  --- arithmetic
  with procedure Neg(S: in out Scalar) is <>;
  with procedure Neg(S1: in Scalar; S2: in out Scalar) is <>;
  with function "-"(S: Scalar) return Scalar is <>;
  with procedure Add(I: in Integer; S: in out Scalar) is <>;
  with procedure Add(S1: in Scalar; S2: in out Scalar) is <>;
  with procedure Sum(S1,S2: in Scalar; S3: in out Scalar) is <>;
  with function "+"(S1,S2: Scalar) return Scalar is <>;
  with procedure Sub(S1: in Scalar; S2: in out Scalar) is <>;
  with procedure Diff(S1,S2: in Scalar; S3: in out Scalar) is <>;
  with function "-"(S1,S2: Scalar) return Scalar is <>;
  with procedure Mult(R: in Flt; S,Tmp: in out Scalar) is <>;
  with procedure Mult(R: in Flt; S: in out Scalar) is <>;
  with procedure Prod(R: in Flt; S1: in Scalar; S2: in out Scalar) is <>;
  with function "*"(R: Flt; S: Scalar) return Scalar is <>;
  with procedure AddProd(R: in Flt; S1: in Scalar; S2,Tmp: in out Scalar) is <>;
  with procedure AddProd(R: in Flt; S1: in Scalar; S2: in out Scalar) is <>;
  with procedure Mult(Q: in Rational; S: in out Scalar) is <>;
  with procedure Mult(S1: in Scalar; S2: in out Scalar) is <>;
  with procedure Prod(S1,S2: in Scalar; S3: in out Scalar) is <>;
  with function "*"(S1,S2: Scalar) return Scalar is <>;
  with procedure AddProd(S1,S2: in Scalar; S3,Tmp: in out Scalar) is <>;
  with procedure AddProd(S1,S2: in Scalar; S3: in out Scalar) is <>;
  with procedure SubProd(S1,S2: in Scalar; S3,Tmp: in out Scalar) is <>;
  with procedure Div(R: in Flt; S,Tmp: in out Scalar) is <>;
  with procedure Div(R: in Flt; S: in out Scalar) is <>;
  with procedure Quot(S1: in Scalar; R: in Flt; S2: in out Scalar) is <>;
  with function "/"(S: Scalar; R: Flt) return Scalar is <>;
  with procedure Div(S1: in Scalar; S2: in out Scalar) is <>;
  with procedure Quot(S1,S2: in Scalar; S3: in out Scalar) is <>;
  with function "/"(S1,S2: Scalar) return Scalar is <>;
  with procedure Inv(S1: in Scalar; S2: in out Scalar) is <>;
  with function Inv(S: Scalar) return Scalar is <>;
  with function "**"(S: Scalar; I: Integer) return Scalar is <>;

  --- fun
  with function IsReal(S: Scalar) return Boolean is <>;
  with procedure Adjoint(S: in out Scalar) is <>;
  with procedure Adjoint(S1: in Scalar; S2: in out Scalar) is <>;
  with function Adjoint(S: Scalar) return Scalar is <>;
  with procedure Real_Part(S: in out Scalar) is <>;
  with procedure Imag_Part(S: in out Scalar) is <>;
  with procedure Eval0(S: in out Scalar) is <>;
  with function "abs"(S: Scalar) return Scalar is <>;
  with procedure Norm(S1: in Scalar; S2: in out Scalar) is <>;
  with function Norm(S: Scalar) return Scalar is <>;
  with function MaxNorm(S: Scalar) return Radius is <>;
  with procedure Sqr(S: in out Scalar) is <>;
  with function Sqr(S: Scalar) return Scalar is <>;
  with procedure Sqrt(S1: in Scalar; S2: in out Scalar) is <>;
  with function Sqrt(S: Scalar) return Scalar is <>;
  with procedure Root(K: in Positive; S1: in Scalar; S2: in out Scalar) is <>;
  with function Root(K: Positive; S: Scalar) return Scalar is <>;
  with procedure Exp(S1: in Scalar; S2: in out Scalar) is <>;
  with function Exp(S: Scalar) return Scalar is <>;
  with procedure ArcCos(S1: in Scalar; S2: in out Scalar) is <>;
  with function ArcCos(S: Scalar) return Scalar is <>;
  with procedure ArcSin(S1: in Scalar; S2: in out Scalar) is <>;
  with function ArcSin(S: Scalar) return Scalar is <>;
  with procedure Cos(S1: in Scalar; S2: in out Scalar) is <>;
  with function Cos(S: Scalar) return Scalar is <>;
  with procedure Sin(S1: in Scalar; S2: in out Scalar) is <>;
  with function Sin(S: Scalar) return Scalar is <>;
  with procedure Log(S1: in Scalar; S2: in out Scalar) is <>;
  with function Log(S: Scalar) return Scalar is <>;
  with procedure Simple_Random(S: in out Scalar) is <>;
  with procedure QPower(Q: in Rational; S1: in Scalar; S2: in out Scalar) is <>;
  with procedure Roots2(B,C: in Scalar; U1,U2,V: in out Scalar) is <>;
  with procedure Roots3(B,C,D: in Scalar; U0,U1,U2,V: in out Scalar) is <>;

  --- conversion and i/o
  with function Approx(S: Scalar) return Flt is <>;
  with procedure Assign(K: in Integer; S: in out Scalar) is <>;
  with procedure Assign(Q: in Rational; S: in out Scalar) is <>;
  with procedure Assign(R: in Flt; S: in out Scalar) is <>;
  with function Scal(I: Integer) return Scalar is <>;
  with function Scal(Q: Rational) return Scalar is <>;
  with function Scal(R: Flt) return Scalar is <>;
  with procedure Enclose(R1,R2: in Flt; S: in out Scalar) is <>;
  with function Enclose(R1,R2: Flt) return Scalar is <>;
  with procedure Show1(N: in String; S: in Scalar; Whatever: in Boolean := True) is <>;
  with procedure Show2(N: in String; S1,S2: in Scalar; Whatever: in Boolean := True) is <>;
  with procedure Put(F: in File_Type; S: in Scalar; Decimal: in Boolean := False) is <>;
  with procedure Get(F: in File_Type; S: in out Scalar; Decimal: in Boolean := False) is <>;
  with procedure Proper_Rounding is <>;

  with package SM is new Matrices (Scalar => Scalar);

package Polynoms2 is

  subtype Power is Integer range 0 .. PDeg;
  subtype Triangular is SM.Triangular;

  procedure SetZero(P: in out Triangular; Deg: in Positive);

  subtype Polynom2 is Triangular(Power,Power); -- P(I,J) undefined if I+J>PDeg

  function IsSharp(P: Polynom2) return Boolean;
  function IsZero(P: Polynom2) return Boolean;
  function "="(P1,P2: Polynom2) return Boolean;
  procedure SetZero(P: in out Polynom2);
  procedure Copy(P1: in Polynom2; P2: in out Polynom2);
  procedure Swap(P1,P2: in out Polynom2);
  function Center0(P: Polynom2) return Boolean;
  function Contains0(P: Polynom2) return Logical;
  function Contains(P1,P2: Polynom2) return Logical;
  procedure ToErr(P: in out Polynom2);
  procedure ToErr(P1: in Polynom2; P2: in out Polynom2);
  procedure Center(P: in out Polynom2);
  procedure Center(P1: in Polynom2; P2: in out Polynom2);
  procedure ModCenter(P: in out Polynom2);
  procedure ModCenter(P1: in Polynom2; P2: in out Polynom2);
  procedure ErrMult(R: in Radius; P: in out Polynom2);
  procedure Union(P1: in Polynom2; P2: in out Polynom2);
  function QuasiDeg(P: Polynom2) return Natural;
  function QuasiDeg0(P: Polynom2) return Boolean;
  procedure Intersection(P1: in Polynom2; P2: in out Polynom2; Empty: out Logical);
  procedure Neg(P: in out Polynom2);
  procedure Neg(P1: in Polynom2; P2: in out Polynom2);
  procedure Add(P1: in Triangular; P2: in out Polynom2);
  procedure Sum(P1,P2: in Polynom2; P3: in out Polynom2);
  procedure Sub(P1: in Polynom2; P2: in out Polynom2);
  procedure Diff(P1,P2: in Polynom2; P3: in out Polynom2);
  procedure Mult(R: in Flt; P: in out Polynom2; Tmp: in out Scalar);
  procedure Prod(R: in Flt; P1: in Polynom2; P2: in out Polynom2);
  procedure Add_Prod(P1,P2: in Polynom2; D1,D2,D3: in Natural; P3: in out Triangular);
  procedure Div(R: in Flt; P: in out Polynom2; Tmp: in out Scalar);
  procedure Quot(P1: in Polynom2; R: in Flt; P2: in out Polynom2);
  function IsReal(P: Polynom2) return Boolean;
  procedure Adjoint(P: in out Polynom2);
  procedure Adjoint(P1: in Polynom2; P2: in out Polynom2);
  procedure Real_Part(P: in out Polynom2);
  procedure Imag_Part(P: in out Polynom2);
  procedure Mult(S: in Scalar; P: in out Polynom2);
  procedure Prod(S: in Scalar; P1: in Polynom2; P2: in out Polynom2);
  procedure AddProd(S: in Scalar; P1: in Polynom2; P2: in out Polynom2);
  procedure AddProd(R: in Flt; P1: in Polynom2; P2: in out Polynom2; Tmp: in out Scalar);
  procedure Evaluate(P: in Polynom2; S1,S2: in Scalar; S3: in out Scalar; Deg: in Natural);
  procedure Evaluate(P: in Polynom2; S1,S2: in Scalar; S3: in out Scalar);
  procedure Evaluate(P: in Polynom2; R1,R2: in Flt; S3: in out Scalar; Deg: in Natural);
  procedure Evaluate(P: in Polynom2; R1,R2: in Flt; S3: in out Scalar);
  procedure Show1(N: in String; P: in Polynom2; Hide0: in Boolean := True);
  procedure Show2(N: in String; P1,P2: in Polynom2; Hide0: in Boolean := True);

  procedure Num_Der1(P: in out Polynom2);
  procedure Num_ValDer1(P: in Polynom2; S1,S2: in Scalar; D1: in out Scalar);
  procedure Num_Der2(P: in out Polynom2);
  procedure Num_ValDer2(P: in Polynom2; S1,S2: in Scalar; D2: in out Scalar);
  procedure Num_MDer(P: in out Polynom2);                                     -- generator of dilation
  procedure Inv_MDer(P: in out Polynom2; CheckConst: in Boolean := True);     -- inverse of MDer

  PProd_Parallel: Boolean := False;

  pragma Inline (SetZero,Copy,Neg);


end Polynoms2;
