/*
* LIBOIL - Library of Optimized Inner Loops
* Copyright (c) 2001,2006 David A. Schleef <ds@schleef.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <math.h>
#include <stdlib.h>
#include <string.h>
#include <liboil/liboildebug.h>
#include "functable.h"
void
functable_function_sinc(double *fx, double *dfx, double x,
double param1, double param2)
{
double y;
if(x==0){
*fx = 1;
*dfx = 0;
return;
}
y = x * param1;
*fx = sin(y)/y;
*dfx = (cos(y) - sin(y)/y)/x;
}
void
functable_function_boxcar(double *fx, double *dfx, double x,
double param1, double param2)
{
double width = param1;
if (x < width && x > -width) {
*fx = 1;
} else {
*fx = 0;
}
*dfx = 0;
}
void
functable_function_hanning(double *fx, double *dfx, double x,
double param1, double param2)
{
double width = param1;
if (x < width && x > -width) {
x /= width;
*fx = (1-x*x)*(1-x*x);
*dfx = -2*2*x/width*(1-x*x);
} else {
*fx = 0;
*dfx = 0;
}
}
Functable *
functable_new (int length, int oversample, double offset, double multiplier)
{
Functable *ft;
ft = malloc (sizeof(Functable));
memset (ft, 0, sizeof(Functable));
ft->length = length;
ft->offset = offset;
ft->multiplier = multiplier;
ft->oversample = oversample;
ft->inv_multiplier = 1.0 / ft->multiplier;
ft->submultiplier = ft->multiplier / ft->oversample;
ft->inv_submultiplier = 1.0 / ft->submultiplier;
ft->fx = malloc(sizeof(double)*ft->length*(ft->oversample + 1));
ft->dfx = malloc(sizeof(double)*ft->length*(ft->oversample + 1));
memset (ft->fx, 0, sizeof(double)*ft->length*(ft->oversample + 1));
memset (ft->dfx, 0, sizeof(double)*ft->length*(ft->oversample + 1));
return ft;
}
void
functable_free (Functable *ft)
{
free (ft->fx);
free (ft->dfx);
free (ft);
}
void
functable_calculate (Functable *t, FunctableFunc func, double param1,
double param2)
{
int i, j;
double x;
double *fx;
double *dfx;
for(j=0;j<t->oversample + 1;j++){
fx = t->fx + t->length*j;
dfx = t->dfx + t->length*j;
for(i=0;i<t->length;i++){
x = t->offset + t->submultiplier * (i * t->oversample + j);
func (&fx[i], &dfx[i], x, param1, param2);
dfx[i] *= t->submultiplier;
}
}
}
void
functable_calculate_multiply (Functable *t, FunctableFunc func,
double param1, double param2)
{
int i;
int j;
double x;
double *fx;
double *dfx;
double afx, dafx, bfx, dbfx;
for(j=0;j<t->oversample + 1;j++){
fx = t->fx + t->length*j;
dfx = t->dfx + t->length*j;
for(i=0;i<t->length;i++){
x = t->offset + t->submultiplier * (i * t->oversample + j);
afx = fx[i];
dafx = dfx[i];
func (&bfx, &dbfx, x, param1, param2);
fx[i] = afx * bfx;
dfx[i] = afx * dbfx + dafx * bfx;
}
}
}
double
functable_evaluate (Functable *t, double x)
{
int i, j;
double f0, f1, w0, w1;
double x2, x3;
double w;
double *fx1, *fx2;
double *dfx1, *dfx2;
int xi;
if(x<t->offset || x>(t->offset+t->length*t->multiplier)){
OIL_DEBUG ("x out of range %g",x);
return 0;
}
x -= t->offset;
x *= t->inv_submultiplier;
xi = floor(x);
j = xi % t->oversample;
i = xi / t->oversample;
x -= xi;
fx1 = t->fx + j*t->length;
fx2 = t->fx + (j+1)*t->length;
dfx1 = t->dfx + j*t->length;
dfx2 = t->dfx + (j+1)*t->length;
x2 = x * x;
x3 = x2 * x;
f1 = 3 * x2 - 2 * x3;
f0 = 1 - f1;
w0 = x - 2 * x2 + x3;
w1 = -x2 + x3;
w = fx1[i] * f0 + fx2[i] * f1 + dfx1[i] * w0 + dfx2[i] * w1;
return w;
}
double
functable_mult_and_sum (Functable *t, double x, double *data, int n)
{
int i, j;
double f0, f1, w0, w1;
double x2, x3;
double w;
double *fx1, *fx2;
double *dfx1, *dfx2;
int xi;
double sum;
if(x<t->offset || x>(t->offset+t->length*t->multiplier)){
OIL_DEBUG ("x out of range %g",x);
return 0;
}
x -= t->offset;
x *= t->inv_submultiplier;
xi = floor(x);
j = xi % t->oversample;
i = xi / t->oversample;
x -= xi;
fx1 = t->fx + j*t->length + i;
fx2 = t->fx + (j+1)*t->length + i;
dfx1 = t->dfx + j*t->length + i;
dfx2 = t->dfx + (j+1)*t->length + i;
x2 = x * x;
x3 = x2 * x;
f1 = 3 * x2 - 2 * x3;
f0 = 1 - f1;
w0 = x - 2 * x2 + x3;
w1 = -x2 + x3;
sum = 0;
for(i=0;i<n;i++){
w = fx1[i] * f0 + fx2[i] * f1 + dfx1[i] * w0 + dfx2[i] * w1;
sum += w * data[i];
}
return sum;
}
syntax highlighted by Code2HTML, v. 0.9.1