#
# LMDIF1 
#
@PROBLEM lmdif1
@FUNCTION lmdif1
@LIB $(NETSOLVE_ROOT)/lib/$(NETSOLVE_ARCH)/minpack_$(NETSOLVE_ARCH).a
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /MinPack/
@DESCRIPTION
the purpose of lmdif1 is to minimize the sum of the squares of
m nonlinear functions in n variables by a modification of the
levenberg-marquardt algorithm. this is done by using the more
general least-squares solver lmdif. the user must provide a
subroutine which calculates the functions. the jacobian is
then calculated by a forward-difference approximation.
http://www.netlib.org/minpack/index.html
@INPUT 4
@OBJECT SCALAR I m
m : number of functions
@OBJECT VECTOR D x
x : is an array of length n. on input x must contain
an initial estimate of the solution vector.
@OBJECT SCALAR D tol
tol : a nonnegative input variable. termination occurs
when the algorithm estimates either that the relative
error in the sum of squares is at most tol or that
the relative error between x and the solution is at
most tol.
@OBJECT UPF upf
  upf : the user-supplied subroutine which
  calculates the functions.

  subroutine upf(m,n,x,fvec,iflag)
  integer m,n,iflag
  double precision x(n),fvec(m)
  ----------
  calculate the functions at x and
  return this vector in fvec.
  ----------
  return
  end

  the value of iflag should not be changed by upf unless
  the user wants to terminate execution of lmdif1.
  in this case set iflag to a negative integer.
@OUTPUT 3
@OBJECT VECTOR D x
x : is an array of length n. on output x
contains the final estimate of the solution vector.
@OBJECT VECTOR D fvec
fvec : an output array of length m which contains
the functions evaluated at the output x.
@OBJECT SCALAR I info
info : an integer output variable. if the user has
terminated execution, info is set to the (negative)
value of iflag. see description of upf. otherwise,
info is set as follows.

@COMPLEXITY 2,4

@CALLINGSEQUENCE
@ARG I3
@ARG I0
@ARG mI1
@ARG I1,O0
@ARG O1
@ARG I2
@ARG O2
@ARG ?
@ARG ?
@ARG ?

@CODE
extern void lmdif1();

int lwa;
int *iwa;
double *wa;
int m,n;
extern int upf0();

m = *(@I0@);
n = *(@mI1@);

if (n>m)
  return NS_PROT_BAD_VALUES;


iwa = (int *)malloc(sizeof(int)*n);
lwa =  m*n+5*n+m;
wa = (double *)malloc(sizeof(double)*lwa);

*@mO1@ = m;
@O1@ = (double *)malloc(sizeof(double)*m);
@O2@ = (int *)malloc(sizeof(int));

lmdif1(upf0,&m,&n,@I1@,@O1@,@I2@,@O2@,iwa,wa,&lwa);

*@mO0@ = *@mI1@;
@O0@ = @I1@;


@END_CODE



#
# HYBRD1 
#
@PROBLEM hybrd1
@FUNCTION hybrd1
@LANGUAGE FORTRAN
@MAJOR COL
@PATH /MinPack/
@DESCRIPTION
The purpose of hybrd1 is to find a zero of a system of
n nonlinear functions in n variables by a modification
of the powell hybrid method. this is done by using the
more general nonlinear equation solver hybrd. the user
must provide a subroutine which calculates the functions.
the jacobian is then calculated by a forward-difference
approximation.
http://www.netlib.org/minpack/index.html
@INPUT 3
@OBJECT VECTOR D x
x : is an array of length n. on input x must contain
an initial estimate of the solution vector.
@OBJECT SCALAR D tol
tol : a nonnegative input variable. termination occurs
when the algorithm estimates either that the relative
error in the sum of squares is at most tol or that
the relative error between x and the solution is at
most tol.
@OBJECT UPF  upf
Supplied-function :

  upf : the user-supplied subroutine which
  calculates the functions.

  subroutine upf(n,x,fvec,iflag)
  integer n,iflag
  double precision x(n),fvec(n)
  ----------
  calculate the functions at x and
  return this vector in fvec.
  ----------
  return
  end

  the value of iflag should not be changed by upf unless
  the user wants to terminate execution of hybrd1.
  in this case set iflag to a negative integer.
@OUTPUT 3
@OBJECT VECTOR D x
x : is an array of length n. on output x
contains the final estimate of the solution vector.
@OBJECT VECTOR D fvec
fvec : an output array of length m which contains
the functions evaluated at the output x.
@OBJECT SCALAR I info
info : an integer output variable. if the user has
terminated execution, info is set to the (negative)
value of iflag. see description of upf. otherwise,
info is set as follows.
     info = 0   improper input parameters.
     info = 1   algorithm estimates that the relative error
                between x and the solution is at most tol.
     info = 2   number of calls to fcn has reached or exceeded
                200*(n+1).
     info = 3   tol is too small. no further improvement in
                the approximate solution x is possible.
     info = 4   iteration is not making good progress.
@COMPLEXITY 2,4

@CALLINGSEQUENCE
@ARG I2
@ARG mI0
@ARG I0,O0
@ARG O1
@ARG I1
@ARG O2
@ARG ?
@ARG ?

@CODE
extern void hybrd1();

int lwa;
double *wa;
int n;
extern int upf0();

n = *(@mI0@);

lwa =  (n*(3*n+13))/2;
/* (jakob) XXX: This is never freed ! */
wa = (double *)malloc(sizeof(double)*lwa);

*@mO1@ = n;
@O1@ = (double *)malloc(sizeof(double)*n);
@O2@ = (int *)malloc(sizeof(int));

hybrd1(upf0,&n,@I0@,@O1@,@I1@,@O2@,wa,&lwa);

*@mO0@ = *@mI0@;
@O0@ = @I0@;

@END_CODE
