with Scalars, Flts, ImproveRoots;
use Scalars, Flts;

pragma Elaborate_All (Scalars,Flts,ImproveRoots);

generic

  type Scalar is private;

  with function Info(Dummy: Scalar) return Scalar_Info is <>;
  with function IsZero(S: 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 <>;
  with procedure BallAt0(R: in Flt; S: in out Scalar) is <>;
  with procedure Center(S: in out Scalar) is <>;
  with function Sign(S: Scalar) return Integer is <>;
  with procedure Neg(S: in out 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: in out Scalar) is <>;
  with function "*"(R: Flt; S: Scalar) return 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 function "/"(S: Scalar; R: Flt) return Scalar is <>;
  with procedure Quot(S1: in Scalar; R: in Flt; 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 function Adjoint(S: Scalar) return Scalar is <>;
  with procedure Real_Part(S: in out Scalar) is <>;
  with function MaxNorm(S: Scalar) return Radius 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 ArcCos(S: Scalar) return Scalar is <>;
  with function Cos(S: Scalar) return Scalar is <>;
  with function Scal(I: Integer) return Scalar is <>;

package Roots is

  --- roots of Z*Z+B*Z+C=0, Z1=U1+iV, Z2=U2-iV
  --- real Scalar: Z1=U1+iV, Z2=U2-iV
  --- complex Scalar: Z1=U1, Z2=U2 (V=0)
  procedure Roots2(B,C: in Scalar; U1,U2,V: in out Scalar);
  procedure NewtonRoots2(B,C: in Scalar; U1,U2,V: in out Scalar; Steps: in Natural := 64);

  --- roots of Z*Z*Z+B*Z*Z+C*Z+D=0, Z0=U0, Z1=U1+iV, Z2=U2-iV
  --- real Scalar: Z0=U0, Z1=U1+iV, Z2=U2-iV
  --- complex Scalar: Z0=U0, Z1=U1, Z2=U2 (V=0)
  procedure Roots3(B,C,D: in Scalar; U0,U1,U2,V: in out Scalar);
  procedure NewtonRoots3(B,C,D: in Scalar; U0,U1,U2,V: in out Scalar; Steps: in Natural := 64);

  SNumeric: constant Boolean := Info(Scal(0)).IsNumeric;

  package IR is new ImproveRoots (Numeric => SNumeric, Scalar => Scalar);
  package SN renames IR.ScalNewton;

private

  procedure Decreasing(S1,S2: in out Scalar);
  procedure RRoots2(B,C: in Scalar; U1,U2,V: in out Scalar);
  procedure CRoots2(B,C: in Scalar; U1,U2,V: in out Scalar);
  procedure Decreasing(S1,S2,S3: in out Scalar);
  procedure RRoots3(B,C,D: in Scalar; U0,U1,U2,V: in out Scalar);
  procedure CRoots3(B,C,D: in Scalar; U0,U1,U2,V: in out Scalar);

  SZero: constant Scalar := Scal(0);
  SComplex: constant Boolean := Info(SZero).IsComplex;

end Roots;
