NAME
PDL::Slatec - PDL interface to the slatec numerical programming library
SYNOPSIS
use PDL::Slatec;
($ndeg, $r, $ierr, $a) = polyfit($x, $y, $w, $maxdeg, $eps);
DESCRIPTION
This module serves the dual purpose of providing an interface to parts of the slatec library and showing how to interface PDL to an external library. Using this library requires a fortran compiler; the source for the routines is provided for convenience.
Currently available are routines to: manipulate matrices; calculate FFT's; fit data using polynomials; and interpolate/integrate data using piecewise cubic Hermite interpolation.
Piecewise cubic Hermite interpolation (PCHIP)
PCHIP is the slatec package of routines to perform piecewise cubic Hermite interpolation of data. It features software to produce a monotone and "visually pleasing" interpolant to monotone data. According to Fritsch & Carlson ("Monotone piecewise cubic interpolation", SIAM Journal on Numerical Analysis 17, 2 (April 1980), pp. 238-246), such an interpolant may be more reasonable than a cubic spline if the data contains both "steep" and "flat" sections. Interpolation of cumulative probability distribution functions is another application. These routines are cryptically named (blame FORTRAN), beginning with 'ch', and accept either float or double piddles.
Most of the routines require an integer parameter called check
; if set to 0, then no checks on the validity of the input data are made, otherwise these checks are made. The value of check
can be set to 0 if a routine such as chim has already been successfully called.
If not known, estimate derivative values for the points using the chim, chic, or chsp routines (the following routines require both the function (
f
) and derivative (d
) values at a set of points (x
)).Evaluate, integrate, or differentiate the resulting PCH function using the routines: chfd; chfe; chia; chid.
If desired, you can check the monotonicity of your data using chcm.
EOD # ' un-confuse emacs
# if define chbs, then add something like the following to point 3: # # or use chbs to convert a PCH function into B-representation # for use with the B-spline routines of slatec # (although no interface to them currently exist). #
# add function definitions after finishing the first pp_addpm(), since this # adds a '=head1 FUNCTIONS' line at the end of the text
pp_addpm(<<'END'); =head2 eigsys
Eigenvalues and eigenvectors of a real positive definite symmetric matrix.
($eigvals,$eigvecs) = eigsys($mat)
Note: this function should be extended to calculate only eigenvalues if called in scalar context!
matinv
Inverse of a square matrix
($inv) = matinv($mat)
polyfit
Convenience wrapper routine about the polfit
slatec
function. Separates supplied arguments and return values.
Fit discrete data in a least squares sense by polynomials in one variable. Handles threading correctly--one can pass in a 2D PDL (as $y
) and it will pass back a 2D PDL, the rows of which are the polynomial regression results (in $r
corresponding to the rows of $y.
($ndeg, $r, $ierr, $a) = polyfit($x, $y, $w, $maxdeg, $eps);
where on input:
C<x> and C<y> are the values to fit to a polynomial.
C<w> are weighting factors
C<maxdeg> is the maximum degree of polynomial to use and
C<eps> is the required degree of fit.
and on output:
C<ndeg> is the degree of polynomial actually used
C<r> is the values of the fitted polynomial
C<ierr> is a return status code, and
C<a> is some working array or other
C<eps> is modified to contain the rms error of the fit.
This version of polyfit handles bad values correctly. It strips them out of the $x variable and creates an appropriate $y variable containing indices of the non-bad members of $x before calling the Slatec routine polfit
.
polycoef
Convenience wrapper routine around the pcoef
slatec
function. Separates supplied arguments and return values.
Convert the polyfit
/polfit
coefficients to Taylor series form.
$tc = polycoef($l, $c, $a);
polyvalue
Convenience wrapper routine around the pvalue
slatec
function. Separates supplied arguments and return values.
For multiple input x positions, a corresponding y position is calculated.
The derivatives PDL is one dimensional (of size nder
) if a single x position is supplied, two dimensional if more than one x position is supplied.
Use the coefficients generated by polyfit
(or polfit
) to evaluate the polynomial fit of degree l
, along with the first nder
of its derivatives, at a specified point.
($yfit, $yp) = polyvalue($l, $nder, $x, $a);
detslatec
compute the determinant of an invertible matrix
$mat = zeroes(5,5); $mat->diagonal(0,1) .= 1; # unity matrix
$det = detslatec $mat;
Usage:
$determinant = detslatec $matrix;
Signature: detslatec(mat(n,m); [o] det())
detslatec
computes the determinant of an invertible matrix and barfs if the matrix argument provided is non-invertible. The matrix threads as usual.
This routine was previously known as det
which clashes now with det which is provided by PDL::MatrixOps. For the moment PDL::Slatec will also load PDL::MatrixOps thereby making sure that older scripts work.
PDL::Slatec::fft
Fast Fourier Transform
$v_in = pdl(1,0,1,0);
($azero,$a,$b) = PDL::Slatec::fft($v_in);
PDL::Slatec::fft
is a convenience wrapper for ezfftf, and performs a Fast Fourier Transform on an input vector $v_in
. The return values are the same as for ezfftf.
PDL::Slatec::rfft
reverse Fast Fourier Transform
$v_out = PDL::Slatec::rfft($azero,$a,$b);
print $v_in, $vout
[1 0 1 0] [1 0 1 0]
PDL::Slatec::rfft
is a convenience wrapper for ezfftb, and performs a reverse Fast Fourier Transform. The input is the same as the output of PDL::Slatec::fft, and the output of rfft
is a data vector, similar to what is input into PDL::Slatec::fft.
0 if successful.
> 0 if there were
ierr
switches in the direction of monotonicity (data still valid).-1 if
nelem($x) < 2
.-3 if
$x
is not strictly increasing.
# switch has become mflag, since `switch' is a reserved word in # C. # # can not say (nwk=2*n) --- the rhs has to equal a number # -> could Basic/Gen/PP/Dims.pm be hacked to allow this? # # I didn't have much success with preceeding wk by [t] # defslatec( 'chic', {S => 'pchic', D => 'dpchic'}, 'IntFlag ic (two=2); Mat vc (two=2); Mat mflag (); Dim n; Mat x (n); Mat f (n); Mat [o] d (n); Incfd dummy; Mat wk (nwk); Dim nwk; IntFlag [o] ierr (); ', 'Calculate the derivatives at the given points ($x,$f
, where $x
is strictly increasing). Control over the boundary conditions is given by the $ic
and $vc
piddles, and the value of $mflag
determines the treatment of points where monotoncity switches direction. A simpler, more restricted, interface is available using chim.
The first and second elements of $ic
determine the boundary conditions at the start and end of the data respectively. If the value is 0, then the default condition, as used by chim, is adopted. If greater than zero, no adjustment for monotonicity is made, otherwise if less than zero the derivative will be adjusted. The allowed magnitudes for ic(0)
are:
1 if first derivative at
x(0)
is given invc(0)
.2 if second derivative at
x(0)
is given invc(0)
.3 to use the 3-point difference formula for
d(0)
. (Reverts to the default b.c. ifn < 3
)4 to use the 4-point difference formula for
d(0)
. (Reverts to the default b.c. ifn < 4
)5 to set
d(0)
so that the second derivative is continuous atx(1)
. (Reverts to the default b.c. ifn < 4
)
The values for ic(1)
are the same as above, except that the first-derivative value is stored in vc(1)
for cases 1 and 2. The values of $vc
need only be set if options 1 or 2 are chosen for $ic
.
Set $mflag = 0
if interpolant is required to be monotonic in each interval, regardless of the data. This causes $d
to be set to 0 at all switch points. Set $mflag
to be non-zero to use a formula based on the 3-point difference formula at switch points. If $mflag > 0
, then the interpolant at swich points is forced to not deviate from the data by more than $mflag*dfloc
, where dfloc
is the maximum of the change of $f
on this interval and its two immediate neighbours. If $mflag < 0
, no such control is to be imposed.
The piddle $wk
is only needed for work space. However, I could not get it to work as a temporary variable, so you must supply it; it is a 1D piddle with 2*n
elements.
Error status returned by $ierr
:
0 if successful.
1 if
ic(0) < 0
andd(0)
had to be adjusted for monotonicity.2 if
ic(1) < 0
andd(n-1)
had to be adjusted for monotonicity.3 if both 1 and 2 are true.
-1 if
n < 2
.-3 if
$x
is not strictly increasing.-4 if
abs(ic(0)) > 5
.-5 if
abs(ic(1)) > 5
.-6 if both -4 and -5 are true.
-7 if
nwk < 2*(n-1)
.
# as above, have made wk an actual piddle, rather than a [t] defslatec( 'chsp', {S => 'pchsp', D => 'dpchsp'}, 'IntFlag ic (two=2); Mat vc (two=2); Dim n; Mat x (n); Mat f (n); Mat [o] d (n); Incfd dummy; Mat wk (nwk); Dim nwk; IntFlag [o] ierr (); ', 'Calculate the derivatives, using cubic spline interpolation, at the given points ($x,$f
), with the specified boundary conditions. Control over the boundary conditions is given by the $ic
and $vc
piddles. The resulting values - $x,$f,$d
- can be used in all the functions which expect a cubic Hermite function.
The first and second elements of $ic
determine the boundary conditions at the start and end of the data respectively. The allowed values for ic(0)
are:
0 to set
d(0)
so that the third derivative is continuous atx(1)
.1 if first derivative at
x(0)
is given invc(0
).2 if second derivative at
x(0
) is given invc(0)
.3 to use the 3-point difference formula for
d(0)
. (Reverts to the default b.c. ifn < 3
.)4 to use the 4-point difference formula for
d(0)
. (Reverts to the default b.c. ifn < 4
.)
The values for ic(1)
are the same as above, except that the first-derivative value is stored in vc(1)
for cases 1 and 2. The values of $vc
need only be set if options 1 or 2 are chosen for $ic
.
The piddle $wk
is only needed for work space. However, I could not get it to work as a temporary variable, so you must supply it; it is a 1D piddle with 2*n
elements.
Error status returned by $ierr
:
0 if successful.
-1 if
nelem($x) < 2
.-3 if
$x
is not strictly increasing.-4 if
ic(0) < 0
oric(0) > 4
.-5 if
ic(1) < 0
oric(1) > 4
.-6 if both of the above are true.
-7 if
nwk < 2*n
.-8 in case of trouble solving the linear system for the interior derivative values.
defslatec( 'chfd', {S => 'pchfd', D => 'dpchfd'}, 'Dim n; Mat x (n); Mat f (n); Mat d (n); Incfd dummy; CheckFlag check (); Dim ne; Mat xe (ne); Mat [o] fe (ne); Mat [o] de (ne); IntFlag [o] ierr (); ', 'Given a piecewise cubic Hermite function - such as from chim - evaluate the function ($fe
) and derivative ($de
) at a set of points ($xe
). If function values alone are required, use chfe. Set check
to 0 to skip checks on the input data.
Error status returned by $ierr
:
0 if successful.
>0 if extrapolation was performed at
ierr
points (data still valid).-1 if
nelem($x) < 2
-3 if
$x
is not strictly increasing.-4 if
nelem($xe) < 1
.-5 if an error has occurred in a lower-level routine, which should never happen.
defslatec( 'chfe', {S => 'pchfe', D => 'dpchfe'}, 'Dim n; Mat x (n); Mat f (n); Mat d (n); Incfd dummy; CheckFlag check (); Dim ne; Mat xe (ne); Mat [o] fe (ne); IntFlag [o] ierr (); ', 'Given a piecewise cubic Hermite function - such as from chim - evaluate the function ($fe
) at a set of points ($xe
). If derivative values are also required, use chfd. Set check
to 0 to skip checks on the input data.
Error status returned by $ierr
:
0 if successful.
>0 if extrapolation was performed at
ierr
points (data still valid).-1 if
nelem($x) < 2
-3 if
$x
is not strictly increasing.-4 if
nelem($xe) < 1
.
defslatec( 'chia', {S => 'pchia', D => 'dpchia'}, 'Dim n; Mat x (n); Mat f (n); Mat d (n); Incfd dummy; CheckFlag check (); Mat a (); Mat b (); FuncRet [o] ans (); IntFlag [o] ierr (); ', 'Evaluate the definite integral of a a piecewise cubic Hermite function over an arbitrary interval, given by [$a,$b]
. See chid if the integration limits are data points. Set check
to 0 to skip checks on the input data.
The values of $a
and $b
do not have to lie within $x
, although the resulting integral value will be highly suspect if they are not.
Error status returned by $ierr
:
0 if successful.
1 if
$a
lies outside$x
.2 if
$b
lies outside$x
.3 if both 1 and 2 are true.
-1 if
nelem($x) < 2
-3 if
$x
is not strictly increasing.-4 if an error has occurred in a lower-level routine, which should never happen.
defslatec( 'chid', {S => 'pchid', D => 'dpchid'}, 'Dim n; Mat x (n); Mat f (n); Mat d (n); Incfd dummy; CheckFlag check (); FortranIndex ia (); FortranIndex ib (); FuncRet [o] ans (); IntFlag [o] ierr (); ', 'Evaluate the definite integral of a a piecewise cubic Hermite function between x($ia)
and x($ib)
.
See chia for integration between arbitrary limits.
Although using a fortran routine, the values of $ia
and $ib
are zero offset. Set check
to 0 to skip checks on the input data.
Error status returned by $ierr
:
0 if successful.
-1 if
nelem($x) < 2
.-3 if
$x
is not strictly increasing.-4 if
$ia
or$ib
is out of range.
defslatec( 'chcm', {S => 'pchcm', D => 'dpchcm'}, 'Dim n; Mat x (n); Mat f (n); Mat d (n); Incfd dummy; CheckFlag check (); IntFlag [o] ismon (n); IntFlag [o] ierr (); ', 'The outout piddle $ismon
indicates over which intervals the function is monotonic. Set check
to 0 to skip checks on the input data.
For the data interval [x(i),x(i+1)]
, the values of ismon(i)
can be:
-3 if function is probably decreasing
-1 if function is strictly decreasing
0 if function is constant
1 if function is strictly increasing
2 if function is non-monotonic
3 if function is probably increasing
If abs(ismon(i)) == 3
, the derivative values are near the boundary of the monotonicity region. A small increase produces non-monotonicity, whereas a decrease produces strict monotonicity.
The above applies to i = 0 .. nelem($x)-1
. The last element of $ismon
indicates whether the entire function is monotonic over $x.
Error status returned by $ierr
:
0 if successful.
-1 if
n < 2
.-3 if
$x
is not strictly increasing.
# XXX tsize = 2*n+4 # bsize = 2*n # # ndim gets set to 2*n # # Changed by routine: # nknots # t defslatec( 'chbs', {S => 'pchbs', D => 'dpchbs'}, 'Dim n; Mat x (n); Mat f (n); Mat d (n); Incfd dummy; IntFlag knotyp (); IntFlag nknots (); Mat t (tsize); Mat [o] bcoef (bsize); IntFlag [o] ndim (); IntFlag [o] kord (); IntFlag [o] ierr (); ', 'The resulting B-spline representation of the data (i.e. nknots
, t
, bcoeff
, ndim
, and kord
) can be evaluated by bvalu
(which is currently not available).
Array sizes: tsize = 2*n + 4
, bsize = 2*n
, and ndim = 2*n
.
knotyp
is a flag which controls the knot sequence. The knot sequence t
is normally computed from $x
by putting a double knot at each x
and setting the end knot pairs according to the value of knotyp
(where m = ndim = 2*n
):
0 - Quadruple knots at the first and last points.
1 - Replicate lengths of extreme subintervals:
t( 0 ) = t( 1 ) = x(0) - (x(1)-x(0))
andt(m+3) = t(m+2) = x(n-1) + (x(n-1)-x(n-2))
2 - Periodic placement of boundary knots:
t( 0 ) = t( 1 ) = x(0) - (x(n-1)-x(n-2))
andt(m+3) = t(m+2) = x(n) + (x(1)-x(0))
<0 - Assume the
nknots
andt
were set in a previous call.
nknots
is the number of knots and may be changed by the routine. If knotyp >= 0
, nknots
will be set to ndim+4
, otherwise it is an input variable, and an error will occur if its value is not equal to ndim+4
.
t
is the array of 2*n+4
knots for the B-representation and may be changed by the routine. If knotyp >= 0
, t
will be changed so that the interior double knots are equal to the x-values and the boundary knots set as indicated above, otherwise it is assumed that t
was set by a previous call (no check is made to verify that the data forms a legitimate knot sequence).
Error status returned by $ierr
:
0 if successful.
-4 if
knotyp > 2
.-5 if
knotyp < 0
andnknots != 2*n + 4
.
AUTHOR
Copyright (C) 1997 Tuomas J. Lukka. Copyright (C) 2000 Tim Jenness, Doug Burke. All rights reserved. There is no warranty. You are allowed to redistribute this software / documentation under certain conditions. For details, see the file COPYING in the PDL distribution. If this file is separated from the PDL distribution, the copyright notice should be included in the file.
10 POD Errors
The following errors were encountered while parsing the POD:
- Around line 862:
=back doesn't take any parameters, but you said =back ', 'Calculate the derivatives of (x,f(x)) using cubic Hermite interpolation.' );
- Around line 998:
=back doesn't take any parameters, but you said =back ', 'Calculate the derivatives of (x,f(x)) using cubic Hermite interpolation.' );
- Around line 1103:
=back doesn't take any parameters, but you said =back ', 'Calculate the derivatives of (x,f(x)) using cubic spline interpolation.' );
- Around line 1158:
=back doesn't take any parameters, but you said =back ', 'Interpolate function and derivative values.' );
- Around line 1207:
=back doesn't take any parameters, but you said =back ', 'Interpolate function values.' );
- Around line 1269:
=back doesn't take any parameters, but you said =back ', 'Integrate (x,f(x)) over arbitrary limits.' );
- Around line 1318:
=back doesn't take any parameters, but you said =back ', 'Integrate (x,f(x)) between data points.' );
- Around line 1394:
=back doesn't take any parameters, but you said =back ', 'Check the given piecewise cubic Hermite function for monotonicity.' );
- Around line 1437:
'=item' outside of any '=over'
- Around line 1489:
=back doesn't take any parameters, but you said =back ', 'Piecewise Cubic Hermite function to B-Spline converter.' );