with Ada.Text_IO, VGeneric, Integer_Subtypes;
use Ada.Text_IO, VGeneric, Integer_Subtypes;

pragma Elaborate_All (Ada.Text_IO,VGeneric,Integer_Subtypes);

generic

  type Component is private;

  with function "="(C1,C2: Component) return Boolean is <>;
  with function IsZero(C: Component) return Boolean is  <>;
  with function IsReal(C: Component) return Boolean is  <>;
  with procedure SetZero(C: in out Component) is <>;
  with procedure Copy(C1: in Component; C2: in out Component) is <>;
  with procedure Swap(C1,C2: in out Component) is <>;
  with procedure Neg(C: in out Component) is <>;
  with procedure Neg(C1: in Component; C2: in out Component) is <>;
  with procedure Add(C1: in Component; C2: in out Component) is <>;
  with procedure Sum(C1,C2: in Component; C3: in out Component) is <>;
  with procedure Sub(C1: in Component; C2: in out Component) is <>;
  with procedure Diff(C1,C2: in Component; C3: in out Component) is <>;
  with procedure Real_Part(C: in out Component) is <>;
  with procedure Imag_Part(C: in out Component) is <>;
  with procedure Adjoint(C: in out Component) is <>;
  with procedure Adjoint(C1: in Component; C2: in out Component) is <>;
  with procedure Show1(N: in String; C: in Component; Whatever: in Boolean := True) is <>;
  with procedure Show2(N: in String; C1,C2: in Component; Whatever: in Boolean := True) is <>;
  with procedure Put(F: in File_Type; C: in Component; Decimal: in Boolean := False) is <>;
  with procedure Get(F: in File_Type; C: in out Component; Decimal: in Boolean := False) is <>;

package Vectors is

  type Vector is array(Integer range <>) of Component;

  --- basic
  function "="(V1,V2: Vector) return Boolean;
  function IsZero is new VF_BProperty (Component,Vector,IsZero);
  function IsReal is new VF_BProperty (Component,Vector,IsReal);
  procedure SetZero is new VP_Modify1 (Component,Vector,SetZero);
  procedure SetZero(F,L: in Integer; V: in out Vector);
  function ZeroVector(F,L: Integer) return Vector;
  procedure Copy is new VP_Map1 (Component,Vector,Copy);
  procedure Swap is new VP_Modify2 (Component,Vector,Swap);
  procedure Neg is new VP_Modify1 (Component,Vector,Neg);
  procedure Neg is new VP_Map1 (Component,Vector,Neg);
  function "-" is new VF_Map1 (Component,Vector,Neg);
  procedure Add is new VP_Map1 (Component,Vector,Add);
  procedure Sum is new VP_Map2 (Component,Vector,Sum);
  function "+" is new VF_Map2 (Component,Vector,Sum);
  procedure Sub is new VP_Map1 (Component,Vector,Sub);
  procedure Diff is new VP_Map2 (Component,Vector,Diff);
  function "-" is new VF_Map2 (Component,Vector,Diff);
  procedure Real_Part is new VP_Modify1 (Component,Vector,Real_Part);
  procedure Imag_Part is new VP_Modify1 (Component,Vector,Imag_Part);
  procedure Adjoint is new VP_Modify1 (Component,Vector,Adjoint);
  procedure Adjoint is new VP_Map1 (Component,Vector,Adjoint);

  --- i/o and conversion
  procedure Show1(N: in String; V: in Vector; Hide0: in Boolean := True);
  procedure Show2(N: in String; V1,V2: in Vector; Hide0: in Boolean := True);
  procedure PutDim(F: in File_Type; L: in Positive);
  procedure PutCoeffs(F: in File_Type; V: in Vector; Decimal: in Boolean := False);
  procedure Put(F: in File_Type; V: in Vector; Decimal: in Boolean := False);
  function Get(F: File_Type; First: Integer; Decimal: Boolean := False) return Vector;
  procedure Get(F: in File_Type; V: in out Vector; Decimal: in Boolean := False);
  procedure Write(FileName: in String; V: in Vector; Decimal: in Boolean := False);
  function Read(FileName: String; First: Integer; Decimal: Boolean := False) return Vector;
  procedure Read(FileName: in String; V: in out Vector; Decimal: in Boolean := False);
  procedure Append(FileName: in String; V: in Vector; Decimal: in Boolean := False);

  --- auxiliary
  function EffFirst(V: Vector) return Integer;
  function EffLast(V: Vector) return Integer;
  procedure Trim(F,L: in Integer; V: in out Vector);

  subtype Polynom1 is Vector; --- Natural range

  --- baby cases
  subtype Vector2 is Vector(OneTwo);
  subtype Vector3 is Vector(OneTwoThree);

  pragma Inline_Always (EffFirst,EffLast);

end Vectors;
