with Ada.Text_IO, Flts, Matrices, Vectors;
use Ada.Text_IO, Flts;

pragma Elaborate_All (Ada.Text_IO,Flts,Matrices,Vectors);

generic

  type Scalar is private;

  with function "="(S1,S2: Scalar) return Boolean is <>;
  with function IsZero(S: Scalar) return Boolean is  <>;
  with function IsReal(S: Scalar) return Boolean is  <>;
  with procedure SetZero(S: in out Scalar) is <>;
  with procedure Assign(I: in Integer; 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 Neg(S: in out Scalar) is <>;
  with procedure Neg(S1: in Scalar; S2: 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 procedure Sub(S1: in Scalar; S2: in out Scalar) is <>;
  with procedure Diff(S1,S2: in Scalar; S3: 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 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 Real_Part(S: in out Scalar) is <>;
  with procedure Imag_Part(S: in out Scalar) is <>;
  with procedure Adjoint(S: in out Scalar) is <>;
  with procedure Adjoint(S1: in Scalar; S2: in out 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);
  with package SV is new Vectors (Component => Scalar);

  with function Compare(S1,S2: Scalar) return Integer is <>;
  with function Inf(S: Scalar) return Flt is <>;
  with procedure Max(S1: in Scalar; S2: in out Scalar) is <>;
  with procedure Norm(S1: in Scalar; S2: in out Scalar) is <>;
  with procedure Quot(S1,S2: in Scalar; S3: in out Scalar) is <>;
  with procedure Sqrt(S1: in Scalar; S2: in out Scalar) is <>;

  type Fun is private;
  type Mode is private;
  type Modes is array (Positive range <>) of Mode;

  with function MaxNorm(F: Fun) return Radius is <>;
  with procedure Norm(Q: in Mode; S: in out Scalar) is <>;
  with procedure Assign(Q: in Mode; F: in out Fun) is <>;
  with procedure AddProd(Q: in Mode; S: in Scalar; F: in out Fun; Check: in Boolean) is <>;
  with procedure Extract(Q: in Mode; F: in out Fun; S: in out Scalar; Check: in Boolean) is <>;
  with procedure Show(Q: in Mode) is <>;

package Linear is

  subtype SVector is SV.Vector;
  subtype SMatrix is SM.Matrix;

  procedure Norm(Q: in Modes; V: in SVector; S: in out Scalar);
  procedure AddProd(Q: in Modes; V: in SVector; F: in out Fun);     -- Unpack
  procedure Extract(Q: in Modes; F: in out Fun; V: in out SVector); -- Pack

  generic
    with procedure LinOp(F1: in Fun; F2: in out Fun);
  procedure Op_Norm(Q: in Modes; S: out Radius);

  generic
    with procedure LinOp(F1: in Fun; F2: in out Fun);
  procedure Enclosure(Q: in Modes; A: in out SMatrix);

  procedure Norm(A: in SMatrix; S: in out Scalar);
  function Norm_Bound(A: SMatrix; B: Scalar) return Boolean;
  procedure OpNorm(Q: in Modes; A: in SMatrix; S: in out Scalar);
  procedure SpecRadius(A,Tmp: in out SMatrix; S: in out Scalar; Pow2: in Positive := 5);
  procedure SpecRadius(A: in SMatrix; S: in out Scalar; Pow2: in Positive := 5);
  function SpecRadius_Bound(A: SMatrix; R: Scalar; Pow2: Positive := 5) return Boolean;

  generic
    with procedure LinOp(F1: in Fun; F2: in out Fun);
  procedure Spec_Radius(Q: in Modes; S: in out Scalar; Pow2: in Positive := 5);

  generic
    with procedure LinOp(F1: in Fun; F2: in out Fun);
  function Spec_Radius_Bound(Q: Modes; R: Scalar; Pow2: Positive := 5) return Boolean;

  Check_Modes: Boolean := True;
  Op_Norm_Parallel: Boolean := True;
  Enclosure_Parallel: Boolean := True;

end Linear;
