Octave interface to gsl_deriv for finite differences with adaptive step size

Paul Koufalas <[email protected]> Tue, 15 Aug 2006 17:41:49 +0930
Newsgroups gmane.comp.gnu.octave.sources
Message-ID <[email protected]>
This is a multi-part message in MIME format.
--------------000509070608050809000108
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

G'day all,

Please find attached an Octave interface to the GSL numerical
differentiation function gsl_deriv(). This interface provides an
adaptive step size forward difference approximation to the gradient of a
vector-valued function. Compile it using

mkoctfile -v gsl_deriv.cc -lgsl

For an relevant article on the topic, see
http://www.nezumi.demon.co.uk/consult/deriv.htm

Cheers,
Paul.



--------------000509070608050809000108
Content-Type: text/x-c++src;
 name="gsl_deriv.cc"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="gsl_deriv.cc"

#include <octave/oct.h>
#include <octave/parse.h>
#include <gsl/gsl_deriv.h>

//$Id: gsl_deriv.cc,v 1.3 2006/07/25 13:40:02 pkoufalas Exp $

std::string fstr="";
octave_value_list* fargsinptr;
double* x_=NULL;
double fun (double xj, void * jay) {
  int* j = (int *)jay;
  x_[*j]=xj;
  octave_value_list fargsout;
  fargsout=feval(fstr,*fargsinptr,1);
#ifdef DEBUG
  octave_value((*fargsinptr)(0)).print(std::cout);
  fargsout(0).print(std::cout);
#endif
  return fargsout(0).scalar_value();
}

DEFUN_DLD (gsl_deriv, args, ,
           "[deriv,abserr] = gsl_deriv (fun,x,h0,method,varargin)\n\
Calculate finite differences using central, forward or backward methods\n\
with adaptive step size using GSL routine gsl_deriv.\n\
 fun, name of function, string\n\
 x, point at which to evaluate derivative, column vector\n\
 h0, initial step size, scalar\n\
 method, 0 for forward,\n\
         1 for backward,\n\
         2 for central.\n\
 varargin, additional args to pass to fun.\n") {

    octave_value_list retval; 

    if (args.length() < 4) { 
        print_usage("gsl_deriv");
        return retval;
    }
    if (error_state) {
      print_usage("gsl_deriv: invalid parameters specified.");
      return retval;
    }

    octave_value_list fargsin;
    fargsinptr = &fargsin;
    const Matrix x ( args(1).matrix_value() );
    fargsin.append(x);

    x_ = (double *)x.fortran_vec();

    int i;
    int nargs = args.length()-4;
    for (i=0;i<nargs;i++)
      fargsin.append(args(i+4));

    gsl_function F;
    fstr = args(0).string_value();

    F.function = &fun;

    double h = args(2).scalar_value();
    int method = args(3).int_value();
    int ndim = x.rows();
    double result[ndim]; 
    double abserr[ndim];
    double x__[ndim];
    for (i=0;i<ndim;i++) // save x!
      x__[i]=x_[i]; 

    switch (method) {
    case 0:
      for (i=0;i<ndim;i++) {
	F.params = &i;
	gsl_deriv_forward(&F,x(i,0),h,&(result[i]),&(abserr[i]));
      }
      break;
    case 1:
    case 2:
    default:
      error("sorry, only forward differences in this version.");
    }

    Matrix d (ndim,1);
    Matrix e (ndim,1);
    Matrix f (ndim,1);
    for (i=0;i<ndim;i++) {
      d(i,0)=result[i];
      e(i,0)=abserr[i];
      f(i,0)=x_[i]-x__[i];
      x_[i]=x__[i]; // restore x! i.e. undo changes to x through pointer
      // trickery in using const Matrix x, x_ = (double *)x.fortran_vec()...
    }

    retval.append(d);
    retval.append(e);
    retval.append(f);
    return retval;

}

--------------000509070608050809000108
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
Octave-sources mailing list
[email protected]
https://www.cae.wisc.edu/mailman/listinfo/octave-sources

--------------000509070608050809000108--