Math-Derivative_XS
view release on metacpan or search on metacpan
Derivative_XS.xs view on Meta::CPAN
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
MODULE = Math::Derivative_XS PACKAGE = Math::Derivative_XS
void
Derivative2(x, y, yp1_sv = NULL, ypn_sv = NULL)
AV * x
AV * y
SV * yp1_sv
SV * ypn_sv
PPCODE:
{
int i;
int n = av_len(x);
NV * y2 = calloc(n, sizeof(NV));
NV * u = calloc(n, sizeof(NV));
if (!yp1_sv || !SvOK(yp1_sv))
{
y2[0] = 0;
u[0] = 0;
}
else
{
y2[0] = -0.5;
NV x_0 = SvNV(*av_fetch(x, 0, 1));
NV x_1 = SvNV(*av_fetch(x, 1, 1));
NV y_0 = SvNV(*av_fetch(y, 0, 1));
NV y_1 = SvNV(*av_fetch(y, 1, 1));
u[0] = (3 / x_1 - x_0) * ((y_1 - y_0)/(x_1 - x_0) - SvNV(yp1_sv));
}
NV x_i_minus_1 = SvNV(*av_fetch(x, 0, 1));
NV x_i = SvNV(*av_fetch(x, 1, 1));
NV y_i_minus_1 = SvNV(*av_fetch(y, 0, 1));
NV y_i = SvNV(*av_fetch(y, 1, 1));
for (i=1; i < n; i++)
{
NV x_i_plus_1 = SvNV(*av_fetch(x, i+1, 1));
NV y_i_plus_1 = SvNV(*av_fetch(y, i+1, 1));
NV sig = (x_i - x_i_minus_1) / (x_i_plus_1 - x_i_minus_1);
NV p = sig * y2[i-1] + 2.;
y2[i] = (sig - 1.) / p;
u[i] = (6.0 * ( (y_i_plus_1 - y_i) / (x_i_plus_1 - x_i) -
(y_i - y_i_minus_1) / (x_i - x_i_minus_1)
)/
(x_i_plus_1 - x_i_minus_1) -sig * u[i-1]) / p;
x_i_minus_1 = x_i;
x_i = x_i_plus_1;
y_i_minus_1 = y_i;
y_i = y_i_plus_1;
}
NV qn, un;
if (!ypn_sv || !SvOK(ypn_sv))
{
qn = 0;
un = 0;
}
else
{
NV x_n = SvNV(*av_fetch(x, n, 1));
NV x_n_minus_1 = SvNV(*av_fetch(x, n-1, 1));
NV y_n = SvNV(*av_fetch(y, n, 1));
NV y_n_minus_1 = SvNV(*av_fetch(y, n-1, 1));
NV ypn = SvNV(ypn_sv);
( run in 0.696 second using v1.01-cache-2.11-cpan-71847e10f99 )