home *** CD-ROM | disk | FTP | other *** search
- // NLEqn.cc -*- C++ -*-
- /*
-
- Copyright (C) 1992, 1993, 1994, 1995 John W. Eaton
-
- This file is part of Octave.
-
- Octave is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- Octave is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- for more details.
-
- You should have received a copy of the GNU General Public License
- along with Octave; see the file COPYING. If not, write to the Free
- Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- */
-
- #ifdef HAVE_CONFIG_H
- #include "config.h"
- #endif
-
- #include <float.h>
- #include <math.h>
-
- #include "NLEqn.h"
- #include "dMatrix.h"
- #include "f77-uscore.h"
- #include "lo-error.h"
-
- extern "C"
- {
- int F77_FCN (hybrd1) (int (*)(int*, double*, double*, int*),
- const int*, double*, double*, const double*,
- int*, double*, const int*);
-
- int F77_FCN (hybrj1) (int (*)(int*, double*, double*, double*, int*, int*),
- const int*, double*, double*, double*, const int*,
- const double*, int*, double*, const int*);
- }
-
- static nonlinear_fcn user_fun;
- static jacobian_fcn user_jac;
-
- // error handling
-
- void
- NLEqn::error (const char* msg)
- {
- (*current_liboctave_error_handler) ("fatal NLEqn error: %s", msg);
- }
-
- // Constructors
-
- NLEqn::NLEqn (void) : NLFunc (), n (0), x () { }
-
- NLEqn::NLEqn (const Vector& xvec, const NLFunc f)
- : NLFunc (f), n (xvec.capacity ()), x (xvec) { }
-
- NLEqn::NLEqn (const NLEqn& a) : NLFunc (a.fun, a.jac), n (a.n), x (a.x) { }
-
- void
- NLEqn::resize (int nn)
- {
- if (n != nn)
- {
- n = nn;
- x.resize (n);
- }
- }
-
- int
- NLEqn::size (void) const
- {
- return n;
- }
-
- // Assignment
-
- NLEqn&
- NLEqn::operator = (const NLEqn& a)
- {
- fun = a.fun;
- jac = a.jac;
- x = a.n;
-
- return *this;
- }
-
- Vector
- NLEqn::states (void) const
- {
- return x;
- }
-
- void
- NLEqn::set_states (const Vector& xvec)
- {
- if (xvec.capacity () != n)
- {
- error ("dimension error");
- return;
- }
-
- x = xvec;
- }
-
- // Other operations
-
- Vector
- NLEqn::solve (const Vector& xvec)
- {
- set_states (xvec);
- int info;
- return solve (info);
- }
-
- Vector
- NLEqn::solve (const Vector& xvec, int& info)
- {
- set_states (xvec);
- return solve (info);
- }
-
- Vector
- NLEqn::solve (void)
- {
- int info;
- return solve (info);
- }
-
- int
- hybrd1_fcn (int *n, double *x, double *fvec, int *iflag)
- {
- int nn = *n;
- Vector tmp_f (nn);
- Vector tmp_x (nn);
-
- for (int i = 0; i < nn; i++)
- tmp_x.elem (i) = x[i];
-
- tmp_f = (*user_fun) (tmp_x);
-
- if (tmp_f.length () == 0)
- *iflag = -1;
- else
- {
- for (i = 0; i < nn; i++)
- fvec[i] = tmp_f.elem (i);
- }
-
- return 0;
- }
-
- int
- hybrj1_fcn (int *n, double *x, double *fvec, double *fjac,
- int *ldfjac, int *iflag)
- {
- int nn = *n;
- Vector tmp_x (nn);
-
- for (int i = 0; i < nn; i++)
- tmp_x.elem (i) = x[i];
-
- int flag = *iflag;
- if (flag == 1)
- {
- Vector tmp_f (nn);
-
- tmp_f = (*user_fun) (tmp_x);
-
- if (tmp_f.length () == 0)
- *iflag = -1;
- else
- {
- for (i = 0; i < nn; i++)
- fvec[i] = tmp_f.elem (i);
- }
- }
- else
- {
- Matrix tmp_fj (nn, nn);
-
- tmp_fj = (*user_jac) (tmp_x);
-
- if (tmp_fj.rows () == 0 || tmp_fj.columns () == 0)
- *iflag = -1;
- else
- {
- int ld = *ldfjac;
- for (int j = 0; j < nn; j++)
- for (i = 0; i < nn; i++)
- fjac[j*ld+i] = tmp_fj.elem (i, j);
- }
- }
-
- return 0;
- }
-
- Vector
- NLEqn::solve (int& info)
- {
- int tmp_info = 0;
-
- if (n == 0)
- {
- error ("equation set not initialized");
- return Vector ();
- }
-
- double tol = tolerance ();
-
- double *fvec = new double [n];
- double *px = new double [n];
- for (int i = 0; i < n; i++)
- px[i] = x.elem (i);
-
- user_fun = fun;
- user_jac = jac;
-
- if (jac)
- {
- int lwa = (n*(n+13))/2;
- double *wa = new double [lwa];
- double *fjac = new double [n*n];
-
- F77_FCN (hybrj1) (hybrj1_fcn, &n, px, fvec, fjac, &n, &tol,
- &tmp_info, wa, &lwa);
-
- delete [] wa;
- delete [] fjac;
- }
- else
- {
- int lwa = (n*(3*n+13))/2;
- double *wa = new double [lwa];
-
- F77_FCN (hybrd1) (hybrd1_fcn, &n, px, fvec, &tol, &tmp_info, wa, &lwa);
-
- delete [] wa;
- }
-
- Vector retval;
-
- info = tmp_info;
-
- if (info >= 0)
- {
- retval.resize (n);
-
- for (i = 0; i < n; i++)
- retval.elem (i) = px[i];
- }
-
- delete [] fvec;
- delete [] px;
-
- return retval;
- }
-
- NLEqn_options::NLEqn_options (void)
- {
- init ();
- }
-
- NLEqn_options::NLEqn_options (const NLEqn_options& opt)
- {
- copy (opt);
- }
-
- NLEqn_options&
- NLEqn_options::operator = (const NLEqn_options& opt)
- {
- if (this != &opt)
- copy (opt);
-
- return *this;
- }
-
- NLEqn_options::~NLEqn_options (void)
- {
- }
-
- void
- NLEqn_options::init (void)
- {
- double sqrt_eps = sqrt (DBL_EPSILON);
- x_tolerance = sqrt_eps;
- }
-
- void
- NLEqn_options::copy (const NLEqn_options& opt)
- {
- x_tolerance = opt.x_tolerance;
- }
-
- void
- NLEqn_options::set_default_options (void)
- {
- init ();
- }
-
- void
- NLEqn_options::set_tolerance (double val)
- {
- x_tolerance = (val > 0.0) ? val : sqrt (DBL_EPSILON);
- }
-
- double
- NLEqn_options::tolerance (void)
- {
- return x_tolerance;
- }
-
- /*
- ;;; Local Variables: ***
- ;;; mode: C++ ***
- ;;; page-delimiter: "^/\\*" ***
- ;;; End: ***
- */
-