with Flts;
use Flts;

pragma Elaborate_all (Flts);

generic

  Numeric: in Boolean;

  type Scalar is private;

  with procedure Add(S1: in Scalar; S2: in out Scalar) is <>;
  with procedure Sub(S1: in Scalar; S2: in out Scalar) is <>;
  with procedure Center(S: in out Scalar) is <>;
  with function MaxNorm(S: Scalar) return Radius is <>;
  with procedure BallAt0(R: in Flt; S: in out Scalar) is <>;

  type Operator is private; -- linear

  with procedure Quot(S1: in Scalar; L: in Operator; S2: in out Scalar) is <>; -- S2 := (1/L)S1
  with procedure Quot(L1,L2: in Operator; L3: in out Operator) is <>;          -- L3 := (1/L2)L1
  with procedure Copy(L1: in Operator; L2: in out Operator) is <>;
  with procedure Neg(L: in out Operator) is <>;
  with procedure Add(L1: in Operator; L2: in out Operator) is <>;
  with procedure Add(I: in Integer; L: in out Operator) is <>;
  with procedure Prod(L1,L2: in Operator; L3: in out Operator) is <>;
  with procedure Center(L: in out Operator) is <>;
  with function MaxNorm(L: Operator) return Radius is <>;
  with procedure BallAt0(R: in Flt; L: in out Operator) is <>;

package Newton is --- find zeros of functions

  pragma Elaborate_Body;

  --- input S has to be approximate zero
  generic
    with procedure TF(X: in Scalar; Y: in out Scalar; L: in out Operator);
  procedure NumFind0(S: in out Scalar; Steps: in Natural := 64; Verbosity: in Natural := 0);

  --- input S has to be approximate zero
  generic
    with procedure F(X: in Scalar; Y: in out Scalar);
    with procedure DF(X: in Scalar; L: in out Operator);
  procedure NumFindZero(S: in out Scalar; Steps: in Natural := 64; Verbosity: in Natural := 0);

  --- input S has to be approximate zero
  generic
    with procedure TF(X: in Scalar; Y: in out Scalar; L: in out Operator);
  procedure Find0(S: in out Scalar; Steps: in Natural := 64; Verbosity: in Natural := 0);

  --- input S has to be approximate zero
  generic
    with procedure F(X: in Scalar; Y: in out Scalar);
    with procedure DF(X: in Scalar; L: in out Operator);
  procedure FindZero(S: in out Scalar; Steps: in Natural := 64; Verbosity: in Natural := 0);

  --- input S already "encloses" zero
  generic
    with procedure TF(X: in Scalar; Y: in out Scalar; L: in out Operator);
  procedure Improve0(S: in out Scalar; Steps: in Natural := 64);

  --- input S already "encloses" zero
  generic
    with procedure F(X: in Scalar; Y: in out Scalar);
    with procedure DF(X: in Scalar; L: in out Operator);
  procedure ImproveZero(S: in out Scalar; Steps: in Natural := 64);

  --- input S2 has to be approximately 1/S2
  procedure InvNewton(L1: in Operator; L2: in out Operator; Steps: in Natural := 64; Verbosity: in Natural := 0);

  No_Contraction: exception;
  MinErr: Radius := Radius'Last;

end Newton;
