#% -*- mode: tm; mode: fold -*-

#%{{{Macros

#i linuxdoc.tm
#i mathsym.tm

#d slang \bf{S-lang}
#d exmp#1 \tt{$1}
#d var#1 \tt{$1}

#d ivar#1 \tt{$1}
#d ifun#1 \tt{$1}
#d cvar#1 \tt{$1}
#d cfun#1 \tt{$1}
#d svar#1 \tt{$1}
#d sfun#1 \tt{$1}
#d icon#1 \tt{$1}

#d chapter#1 <chapt>$1<p>
#d preface <preface>
#d tag#1 <tag>$1</tag>

#d function#1 \sect1{<bf>$1</bf>\label{$1}}<descrip>
#d variable#1 \sect1{<bf>$1</bf>\label{$1}}<descrip>
#d function_sect#1 \sect{$1}
#d begin_constant_sect#1 \sect{$1}<itemize>
#d constant#1 <item><tt>$1</tt>
#d end_constant_sect </itemize>

#d synopsis#1 <tag> Synopsis </tag> $1
#d keywords#1 <tag> Keywords </tag> $1
#d usage#1 <tag> Usage </tag> <tt>$1</tt>
#d description <tag> Description </tag>
#d example <tag> Example </tag>
#d notes <tag> Notes </tag>
#d seealso#1 <tag> See Also </tag> <tt>\linuxdoc_list_to_ref{$1}</tt>
#d done </descrip><p>
#d -1 <tt>-1</tt>
#d 0 <tt>0</tt>
#d 1 <tt>1</tt>
#d 2 <tt>2</tt>
#d 3 <tt>3</tt>
#d 4 <tt>4</tt>
#d 5 <tt>5</tt>
#d 6 <tt>6</tt>
#d 7 <tt>7</tt>
#d 8 <tt>8</tt>
#d 9 <tt>9</tt>
#d NULL <tt>NULL</tt>
#d documentstyle book

#%}}}

#d GSLurl http://www.gnu.org/software/gsl/
#d GSLdoc http://www.gnu.org/software/gsl/manual/gsl-ref_toc.html
#d GSLmoduleurl http://space.mit.edu/CXC/software/slang/modules/gsl/

#d GSL \url{\GSLurl}{GSL}
#d module#1 \tt{$1}
#d file#1 \tt{$1}
#d slang-documentation \
 \url{http://www.jedsoft.org/slang/doc/html/slang.html}{S-Lang documentation}

\linuxdoc
\begin{\documentstyle}

\title S-Lang GSL Module Reference
\author John E. Davis, \tt{jed@jedsoft.org}
\date \__today__

\toc

\chapter{Introduction to GSL} #%{{{
 The GNU Scientific Library (\GSL) is a vast collection of robust and
 well documented numerical functions.  It includes support for many
 special functions, random numbers, interpolation and integration
 routines, and much more.  For more information about GSL, visit \url{\GSLurl}.

 Many of the routines in the GSL may be made available to the \slang
 interpreter via the GSL modules described by this document, whose
 most recent version may be found at \url{\GSLmoduleurl}.

 At the moment, the following GSL modules are available:
\itemize{
   \item \module{gslsf}: The GSL special function module.  Currently,
   this module provides an interface to nearly 200 GSL special
   functions.

   \item \module{gslconst}: The GSL constants module.  This module
   defines many constants such as \icon{CONST_MKSA_SPEED_OF_LIGHT},
   \icon{CONST_CGSM_BOLTZMANN}, etc.

   \item \module{gslinterp}: The GSL interpolation module, which
   includes routines for linear interpolation, cubic splines, etc.

   \item \module{gslrand}: The GSL random number module.  This module
   supports most of GSL's random number generators and distributions.

   \item \module{gslcdf} The GSL cumulative distribution function
   module.

   \item \module{gslfft}  The GSL fast-fourier transform module.

   \item \module{gslmatrix}  A set of GSL routines that deal with
   matrices. These include eigenvalue, eigenvector, and a number of
   other linear algebra functions.

   \item\module{gsldwt} The GSL Discrete Wavelet Transform module

   \item\module{gslinteg} The GSL numerical integration module
}

 There are many functions that are not yet wrapped.  For example, none
 of GSL's ODE functions have been wrapped.  Future releases of the GSL
 module will include more functionality.  Nevertheless, what has been
 implemented should prove useful.

#%}}}

\chapter{Using the GSL Modules} #%{{{
 To use one of the GSL modules in a \slang script, the module must
 first be loaded using the \sfun{require} function. For example, to
 load the GSL special function module, use
#v+
   require ("gslsf");
#v-

 The \file{gsl.sl} file exists as a convenient way to load
 all GSL modules (\module{gslsf}, \module{gslrand}, etc.), e.g.,
#v+
    require ("gsl");
#v-

 Finally, it may be desirable to import the GSL module into a separate
 namespace.  For example, to load the GSL special function module
 \module{gslsf} into a namespace called \exmp{GSL}, use
#v+
   require ("gsl", "G")
#v-
 Then to access, e.g., the \exmp{hypot} function, use the
 \exmp{GSL->hypot}.  See the \slang-documentation for more information
 about namespaces.

 Once the desired module has been loaded, intrinsics functions and
 variables defined by the module may be used in the usual way, e.g.,
#v+
    require ("gslsf");
        .
        .
    % Use the GSL hypot function to filter a list of (x,y) pairs
    % to those values that fall in a circle of radius R centered
    % on (0,0)
    define filter_region_in_circle (x, y, R)
    {
       variable i = where (hypot (x,y) < R);
       return (x[i], y[i]);
    }
#v-

#%}}}

\chapter{Error Handling} #%{{{

 This section describes how the GSL modules handle errors reported by
 the GSL library.

 The following GSL error codes are defined by the \module{gsl}
 module:
#v+
   GSL_EDOM        input domain error, e.g sqrt(-1)
   GSL_ERANGE      output range error, e.g. exp(1e100)
   GSL_EFAULT      invalid pointer
   GSL_EINVAL      invalid argument supplied by user
   GSL_EFAILED     generic failure
   GSL_EFACTOR     factorization failed
   GSL_ESANITY     sanity check failed - shouldn't happen
   GSL_ENOMEM      malloc failed
   GSL_EBADFUNC    problem with user-supplied function
   GSL_ERUNAWAY    iterative process is out of control
   GSL_EMAXITER    exceeded max number of iterations
   GSL_EZERODIV    tried to divide by zero
   GSL_EBADTOL     user specified an invalid tolerance
   GSL_ETOL        failed to reach the specified tolerance
   GSL_EUNDRFLW    underflow
   GSL_EOVRFLW     overflow
   GSL_ELOSS       loss of accuracy
   GSL_EROUND      failed because of roundoff error
   GSL_EBADLEN     matrix, vector lengths are not conformant
   GSL_ENOTSQR     matrix not square
   GSL_ESING       apparent singularity detected
   GSL_EDIVERGE    integral or series is divergent
   GSL_EUNSUP      requested feature is not supported by the hardware
   GSL_EUNIMPL     requested feature not (yet) implemented
   GSL_ECACHE      cache limit exceeded
   GSL_ETABLE      table limit exceeded
   GSL_ENOPROG     iteration is not making progress towards solution
   GSL_ENOPROGJ    jacobian evaluations are not improving the solution
   GSL_ETOLF       cannot reach the specified tolerance in F
   GSL_ETOLX       cannot reach the specified tolerance in X
   GSL_ETOLG       cannot reach the specified tolerance in gradient
   GSL_EOF         end of file
#v-

 The \ifun{gsl_set_error_disposition} function may be used to indicate
 how the module is to handle a specified error. It takes two
 arguments: an error code and a value controlling how the
 error is to be handled:
#v+
    gsl_set_error_disposition (error_code, control_value)
#v-
 If the control value is 0, the error will be ignored by the module.
 If the control value is 1, the module will print a warning message
 when the specified error is encountered.  If the control value is -1,
 the module will generate an exception when the error is encountered.
 For example,
#v+
    gsl_set_error_disposition (GSL_EDOM, -1);
#v-
 will cause domain errors to generate an exception, whereas
#v+
    gsl_set_error_disposition (GSL_EUNDRFLW, 0);
#v-
 will cause the GSL modules to ignore underflow errors.

 Alternatively, the control value may be the reference to a function
 to be called when the specified error occurs.  The function will be
 passed two arguments: a string whose value is the function name
 generating the error and the error code itself, e.g.,
#v+
    static define edom_callback (fname, err_code)
    {
       vmessage ("%s: domain error.", fname);
    }
    gsl_set_error_disposition (GSL_EDOM, &edom_callback);

    y = log_1plusx (-10);
#v-
 will result in the message \exmp{"log_1plusx: domain error."}.

 By default, all errors will generate exceptions except for the
 following, which will generate warnings:
#v+
   GSL_EDOM
   GSL_ERANGE
   GSL_EUNDRFLW
   GSL_EOVRFLW
#v-

#%}}}

\chapter{gslinterp: The GSL Interpolation Module} #%{{{

 The \module{gslinterp} module provides S-Lang interpreter access to
 GSL's interpolations routines.  The interpolation methods include
 linear, polynomial, and spline interpolation.  Both Cubic and Akima
 splines are supported with normal or periodic boundary conditions. In
 addition, routines for computing first and second order derivatives,
 as well as integrals based upon these interpolation methods are
 included.

 The wrapping of these functions differs somewhat from the interface
 provided by the GSL API in the interest of ease of use.  The
 \module{gslinterp} modules actual defines two interfaces to the
 underlying GSL routines.

 The higher-level interface is the simplest to use and should suffice
 for most applications.  As an example of its use, suppose one has a
 set of (x,y) pairs represented by the arrays \exmp{xa} and \exmp{ya}
 that one wants to use for interpolation.  Then
#v+
    y = interp_cspline (x, xa, ya);
#v-
 will fit a cubic spline to the points and return the of the spline at
 the point \exmp{x}.  If \exmp{x} is an array, then the spline will be
 evaluated at each of the points in the array returning an array of
 the same shape.

 The low-level interface consists of several method-specific
 initialization functions and functions that carry out the actual
 interpolation.  The above example may be written in terms of this
 interface as
#v+
    c = interp_cspline_init (xa, ya);
    y = interp_eval (c, x);
#v-
 Here \ifun{interp_cspline_init} returns an object of type
 \var{GSL_Interp_Type} that represents the spline function.  It is
 then passed to the \ifun{interp_eval} function to evaluate the spline
 at \exmp{x}.

 The advantage of the lower level interface is that it moves the
 overhead associated with the computation of the interpolating
 function (the spline in the above example) out of the function that
 performs the interpolation.  This means that code such as
#v+
    c = interp_cspline_init (xa, ya);
    y0 = interp_eval (c, x0);
    y1 = interp_eval (c, x1);
#v-
 will execute in less time than
#v+
    y0 = interp_cspline (x0, xa, ya);
    y1 = interp_cspline (x1, xa, ya);
#v-

#i rtl/gslinterp.tm

#%}}}

\chapter{gslsf: The GSL Special Functions Module} #%{{{

 The special function module, \module{gslsf}, wraps nearly 200 GSL
 special functions.  Since the special functions are described in
 detail in the \url{\GSLdoc}{documentation for the GSL library}, no
 attempt will be made here to duplicate the main documentation.
 Rather, a description of how the special functions have been wrapped
 by the module is given.

 GSL prefixes the special functions with the string \exmp{gsl_sf_}.
 This prefix is omitted from the corresponding intrinsic functions of
 the \module{gslsf} module.  For example, the GSL function that
 computes spherical harmonics is called \exmp{gsl_sf_legendre_sphPlm}.
 However, it is represented in the module by simply
 \exmp{legendre_sphPlm}.

 Most of GSL's special functions take scalar arguments and returns a
 scalar.  For example, \exmp{gsl_sf_legendre_sphPlm} takes three
 arguments (int, int, and a double) and returns a double, e.g.,
#v+
    int l = 5, m = 0;
    double x = 0.5;
    double y = gsl_sf_legendre_sphPlm (l, m, x);
#v-
 While the module supports the scalar usage, e.g,
#v+
    variable l = 5, m = 0, x = 0.5;
    variable y = legendre_sphPlm (l, m, x);
#v-
 it also supports vector arguments, e.g.,
#v+
    variable l = 5, m = 0, x = [-1:1:0.1];
    variable y = legendre_sphPlm (l, m, x);
#v-
 and
#v+
    variable l = 5, m = [0:l], x = 0.5;
    variable y = legendre_sphPlm (l, m, x);
#v-

 Some of the functions are expensive to compute to full double
 precision accuracy.  In the interest of speed, it may want to perform
 perform the computation with less precision.  Hence, several of the
 special functions take an optional mode argument that specifies the
 desired precision: \icon{GSL_PREC_DOUBLE} for double precision
 accuracy, \icon{GSL_PREC_SINGLE} for single precision accuracy, and
 \icon{GSL_PREC_APPROX} for a relative accuracy of 5e-4.  For example,
 to compute the Airy function to double precision accuracy use:
#v+
     y = airy_Ai (x, GSL_PREC_DOUBLE);
#v-
 If called without the mode argument, i.e.,
#v+
     y = airy_Ai (x);
#v-
 the function will be computed to a default precision of
 \icon{GSL_PREC_SINGLE}.  The default precision can be set and queried
 by the \ifun{gslsf_set_precision} and \ifun{gslsf_get_precision}
 functions, resp.  Functions that do not take the optional mode
 argument will always be computed at full precision.

#i rtl/gslsf-module.tm

#%}}}

\chapter{gslrand: The GSL Random Number Module} #%{{{

 GSL provides more than 60 types of random number generators and about
 40 random number distributions.   The \module{gslrand} module
 provides access to all of the GSL random number generators and to
 nearly all of its random number distributions.

 Using the \module{gslrand} module is rather straightforward.  First,
 import the module into the interpreter as described above via a
 statement such as
#v+
   require ("gslrand");
#v-
 The next step is to allocate a random number generator via the
 \ifun{rng_alloc} function.  As stated above, there are more than 60
 generators to choose from.  To allocate an instance of the default
 generator (\exmp{"mt19937"}), use
#v+
    r = rng_alloc ();
#v-
 Or to allocate an instance of some other generator, e.g., the
 lagged-fibonacci generator \exmp{"gfsr4"}, use
#v+
    r = rng_alloc ("gfsr4");
#v-
 Once the generator has been allocated, it may be used to construct
 random number sequences from a specific random distribution.  For
 example,
#v+
   x = ran_flat (r, 0, 1);
#v-
 may be used to obtain a random number uniformly distributed between 0
 and 1.  In a similar vein,
#v+
   x = ran_gaussian (r, 2.0);
#v-
 will produce a gaussian distributed random number with a sigma of 2.0.

 For many applications, it is desirable to be able to produce arrays
 of random numbers.  This may be accomplished by passing an addition
 argument to the random number distribution function that specifies
 how many random numbers to produce.  For example,
#v+
   a = ran_gaussian (r, 2.0, 10000);
#v-
 will create an array of 10000 gaussian distributed random numbers
 with a sigma of 2.0.

 If the random generator is omitted from the call to the random number
 distribution routines, then a default generator will be used.  For
 example,
#v+
   x = ran_gaussian (2.0);
#v-
  will generate a gaussian distributed random number with a sigma of
  2.0 using the default generator.

#i rtl/gslrand.tm

#%}}}

\chapter{gslfft: The GSL FFT module} #%{{{

 The \module{gslfft} may be used to compute N dimensional fast fourier
 transforms (FFT).  The module itself currently provides a single function
 called \ifun{_gsl_fft_complex} that performs a forward or backward
 n-dimensional FFT.  The underlying GSL routines used by this
 function are the Swarztrauber mixed-radix routines from FFTPACK and
 the more general Singleton routine.

 The \ifun{_gsl_fft_complex} function is not meant to be called directly;
 rather the user should call the \sfun{fft} function, which provides a
 convenient wrapper for the \ifun{_gsl_fft_complex} function.

#i rtl/gslfft.tm

#%}}}

\chapter{gsldwt: The GSL Discrete Wavelet Transform module} #%{{{

 The \module{gsldwt} may be used to perform discrete wavelet
 transforms (DWT) for real data in both one and two dimensions. The
 module itself currently provides a single function called \ifun{dwt}
 that performs a forward or backward n-dimensional DWT.

#i rtl/gsldwt.tm

#%}}}

\chapter{gslmatrix: A Collection of Matrix-Oriented GSL functions} #%{{{

 The \slang interpreter has wide-spread native support for
 manipulating arrays and matrices.  The \module{gslmatrix} supplements
 this by adding some linear algebra routines such LU decomposition as
 well as routines for dealing with eigenvalues and eigenvectors.

 \GSL has separate functions for complex numbers.  Rather than
 creating separate wrappers for each of these functions, the
 complex-valued routines have been incorporated into single wrappers
 that support for both real and complex numbers.  In this way the
 interface is polymorphic.

#i rtl/gslmatrix.tm

#%}}}

\chapter{gslcdf: The GSL Cumulative Distribution Function Module} #%{{{

  The \module{gslcdf} module wraps the GSL cumulative distribution
  functions.
#i rtl/gslcdf-module.tm

#%}}}

\chapter{gslconst: The GSL Constants Module} #%{{{

 The GSL constants module \module{gslconst} defines about 200 physical
 constants such as the speed of light
 (\icon{CONST_MKSA_SPEED_OF_LIGHT}) and Boltzmann's constant
 (\icon{CONST_MKSA_BOLTZMANN}).  In addition to providing values in the
 MKSA (meters, kilograms, seconds, amperes) system, the module also
 includes CGSM (centimeters, grams, seconds, gauss) versions, e.g.,
 \icon{CONST_CGSM_SPEED_OF_LIGHT}.

#i rtl/gslconst-module.tm

#%}}}

\chapter{gslcdf: The GSL Cumulative Distribution Function Module} #%{{{

  The \module{gslcdf} module wraps the GSL cumulative distribution
  functions.
#i rtl/gslcdf-module.tm

#%}}}

\chapter{gslinteg: The GSL Numerical Integration Module} #%{{{

 The \module{gslinteg} wraps the GSL 1-d numerical integration
 of functions of the form

 \displayeq{\\int_a^b dx\\;w(x)f(x;p)}{\\Large},

 where \em{w(x)} is a weight function whose form depends upon the
 specific integration routine, and \em{p} represents an optional set
 of paramters that the function depends upon.  The function \em{f(x;p)} must be
 supplied by the user in one of the following forms, depending upon
 the existence of the optional parameters.
#v+
   define func (x) { ...; return f };
   define func (x, parms) { ...; return f; }
#v-
 The \exmp{parms} variable in the second form is the list of optional
 parameters represented by \em{p}. For example, consider the function
 \displayeq{f(x;a,b) = (x-a)^b}

 It may be coded as
#v+
   define func (x,parms)
   {
      variable a = parms[0], b = parms[1];
      return (x-a)^b;
   }
#v-

 To illustrate the use of module, the example for the
 \exmp{gsl_integration_fixed} function that appears in the GSL
 documentation.
 \url{https://www.gnu.org/software/gsl/doc/html/integration.html#c.gsl_integration_fixed_workspace}
 will be given:
#v+
   define example_func (x, parms)
   {
      return x^parms[0] + 1.0;
   }
   define slsh_main ()
   {
      variable m = 10, n = 6;
      variable w = integration_fixed_alloc ("hermite", n, 0, 1, 0, 0);

      variable parms = {m};  % parms is a list of optional parameters
      variable res = integration_fixed (&example_func, parms, w);

      vmessage ("Result = %S", res.result);
      vmessage ("Function calls: %S", res.neval);
      vmessage ("Status: %S", res.status);
      vmessage ("Abserror: %S", res.abserr);
   }
#v-
 As the example illustrates, the integration function returns a
 structure with the following fields:
#v+
     result  : The value computed by the integrator
     abserr  : An estimate the absolute error
     neval   : The number of function evaluations
     status  : The status value returned from the integrator
#v-
  Not all of the integration routines return a meaningful value of the
  \exmp{abserr}.

  Many of the underlying integration routines require a workspace to be
  allocated.  For such cases, the module handles handles this
  internally.  Compare the following with the corresponding example
  given in the GSL documentation that utilizes the
  \exmp{gsl_integration_qags} integrator:
#v+
   define example_func (x, parms)
   {
      variable alpha = parms[0];
      return log (alpha*x)/sqrt(x);
   }
   define slsh_main ()
   {
      variable alpha = 1.0;
      variable parms = {alpha};
      variable res
         = integration_qags (&example_func, parms, 0, 1, 0, 1e-7, 1000);

      vmessage ("Result = %S", res.result);
      vmessage ("Function calls: %S", res.neval);
      vmessage ("Status: %S", res.status);
      vmessage ("Abserror: %S", res.abserr);
   }
#v-


#i rtl/gslinteg.tm


#%}}}

\end{\documentstyle}
