cosmotool/src/interpolate.cpp

279 lines
5.1 KiB
C++
Raw Normal View History

#include <cassert>
#include <cmath>
2009-01-08 16:18:03 +01:00
#include <algorithm>
#include "interpolate.hpp"
#include <vector>
#include <fstream>
#include <inttypes.h>
#include <sstream>
using namespace std;
using namespace CosmoTool;
Interpolate::Interpolate(double *xs, double *values, uint32_t N, bool autofree,
bool logx, bool logy)
2009-01-08 16:18:03 +01:00
{
spline = gsl_spline_alloc (gsl_interp_linear, N);
gsl_spline_init (spline, xs, values, N);
accel_interp = gsl_interp_accel_alloc();
this->logx = logx;
this->logy = logy;
2009-01-08 16:18:03 +01:00
this->autoFree = autofree;
}
Interpolate::~Interpolate()
{
if (spline != 0)
gsl_spline_free (spline);
if (accel_interp != 0)
gsl_interp_accel_free (accel_interp);
}
double Interpolate::compute(double x)
throw (InvalidRangeException)
{
double y;
if (logx)
x = log(x);
2009-01-08 16:18:03 +01:00
int err = gsl_spline_eval_e(spline, x, accel_interp, &y);
if (err)
throw InvalidRangeException("Interpolate argument outside range");
if (logy)
return exp(y);
else
return y;
2009-01-08 16:18:03 +01:00
}
double Interpolate::compute(double x) const
throw (InvalidRangeException)
{
double y;
if (logx)
x = log(x);
int err = gsl_spline_eval_e(spline, x, 0, &y);
if (err)
throw InvalidRangeException("Interpolate argument outside range");
if (logy)
return exp(y);
else
return y;
}
double Interpolate::derivative(double x)
throw (InvalidRangeException)
{
double y, dy, x0 = x;
if (logx)
x0 = log(x0);
int err = gsl_spline_eval_deriv_e(spline, x0, accel_interp, &dy);
if (err)
throw InvalidRangeException("Interpolate argument outside range");
if (logy)
{
int err = gsl_spline_eval_e(spline, x0, accel_interp, &y);
assert(err == 0);
return dy*exp(y)/x0;
}
else
return dy;
}
2009-01-08 16:18:03 +01:00
uint32_t Interpolate::getNumPoints() const
{
return spline->size;
}
void Interpolate::fillWithXY(double *x, double *y) const
{
if (x != 0)
memcpy(x, spline->x, sizeof(double)*spline->size);
if (y != 0)
memcpy(y, spline->y, sizeof(double)*spline->size);
}
const Interpolate& Interpolate::operator=(const Interpolate& a)
{
double *x, *y;
if (spline != NULL)
{
gsl_spline_free (spline);
gsl_interp_accel_free (accel_interp);
}
autoFree = true;
spline = gsl_spline_alloc (gsl_interp_linear, a.spline->size);
accel_interp = gsl_interp_accel_alloc ();
gsl_spline_init(spline, a.spline->x, a.spline->y, a.spline->size);
2011-01-18 13:56:19 +01:00
logx = a.logx;
logy = a.logy;
2009-01-08 16:18:03 +01:00
}
double Interpolate::getMaxX() const
{
if (logx)
return exp(spline->x[spline->size-1]);
else
return spline->x[spline->size-1];
2009-01-08 16:18:03 +01:00
}
typedef struct {
double a, b;
} MyPair;
bool operator<(const MyPair& a, const MyPair& b)
{
return a.a < b.a;
}
Interpolate CosmoTool::buildFromVector(const InterpolatePairs& v)
{
double *x = new double[v.size()];
double *y = new double[v.size()];
for (uint32_t i = 0; i < v.size(); i++)
{
x[i] = v[i].first;
y[i] = v[i].second;
}
Interpolate inter = Interpolate(x, y, v.size(), true);
delete[] x;
delete[] y;
return inter;
}
Interpolate CosmoTool::buildInterpolateFromFile(const char *fname)
throw (NoSuchFileException)
{
vector<MyPair> allData;
ifstream f(fname);
if (!f)
throw NoSuchFileException(fname);
do
{
MyPair m;
2010-12-06 03:55:12 +01:00
if (!(f >> m.a >> m.b))
2009-01-08 16:18:03 +01:00
break;
allData.push_back(m);
}
while (1);
sort(allData.begin(), allData.end());
double *x = new double[allData.size()];
double *y = new double[allData.size()];
for (uint32_t i = 0; i < allData.size(); i++)
{
x[i] = allData[i].a;
y[i] = allData[i].b;
}
Interpolate inter = Interpolate(x, y, allData.size(), true);
delete[] x;
delete[] y;
return inter;
}
Interpolate CosmoTool::buildInterpolateFromColumns(const char *fname, uint32_t col1, uint32_t col2, bool logx,
bool logy)
2009-01-08 16:18:03 +01:00
throw (NoSuchFileException,InvalidRangeException)
{
vector<MyPair> allData;
ifstream f(fname);
if (!f)
throw NoSuchFileException(fname);
bool swapped = (col1 > col2);
uint32_t colMin = min(col1, col2);
uint32_t colMax = max(col1, col2);
do
{
MyPair m;
string line;
if (getline(f, line).eof())
break;
istringstream iss(line);
double dummy;
double val1, val2;
for (uint32_t i = 0; i < colMin; i++)
iss >> dummy;
if (!(iss >> val1))
throw InvalidRangeException("Invalid first column");
if (col2 != col1)
{
for (uint32_t i = 0; i < (colMax-colMin-1); i++)
iss >> dummy;
if (!(iss >> val2))
throw InvalidRangeException("Invalid second column");
}
else
val2 = val2;
if (!swapped)
{
m.a = val1;
m.b = val2;
}
else
{
m.a = val2;
m.b = val1;
}
allData.push_back(m);
}
while (1);
sort(allData.begin(), allData.end());
double *x = new double[allData.size()];
double *y = new double[allData.size()];
for (uint32_t i = 0; i < allData.size(); i++)
{
x[i] = logx ? log(allData[i].a) : allData[i].a;
y[i] = logy ? log(allData[i].b) : allData[i].b;
2009-01-08 16:18:03 +01:00
}
Interpolate inter = Interpolate(x, y, allData.size(), true, logx, logy);
2009-01-08 16:18:03 +01:00
delete[] x;
delete[] y;
return inter;
}