home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Geek Gadgets 1
/
ADE-1.bin
/
ade-dist
/
octave-1.1.1p1-src.tgz
/
tar.out
/
fsf
/
octave
/
liboctave
/
NLEqn.cc
< prev
next >
Wrap
C/C++ Source or Header
|
1996-09-28
|
5KB
|
326 lines
// 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: ***
*/