4 added files
sandbox/magfield/src
--- sandbox/magfield/src/spline.cpp (rev 0)
+++ sandbox/magfield/src/spline.cpp 2014-04-03 15:54:52 UTC (rev 3075)
@@ -0,0 +1,987 @@
+// Magic Software, Inc.
+// http://www.magic-software.com
+// Copyright (c) 2000, 2001. All Rights Reserved
+//
+// Source code from Magic Software is supplied under the terms of a license
+// agreement and may not be copied or disclosed except in accordance with the
+// terms of that agreement. The various license agreements may be found at
+// the Magic Software web site. This file is subject to the license
+//
+// FREE SOURCE CODE
+// http://www.magic-software.com/License/free.pdf
+
+#include <fstream>
+#include <math.h>
+#include <float.h>
+#include "spline.h"
+//===========================================================================
+const double mgcSpline::INVALID_DATA = FLT_MAX;
+
+// error handling
+int mgcSpline::verbose = 0;
+unsigned mgcSpline::error = 0;
+const unsigned mgcSpline::invalid_dimensions = 0x00000001;
+const unsigned mgcSpline::invalid_degree = 0x00000002;
+const unsigned mgcSpline::invalid_dim = 0x00000004;
+const unsigned mgcSpline::null_data = 0x00000008;
+const unsigned mgcSpline::allocation_failed = 0x00000010;
+const char* mgcSpline::message[5] = {
+ "invalid number of dimensions",
+ "degree must be positive",
+ "dimension must be at least DEGREE+1",
+ "input data pointer is null",
+ "failed to allocate memory"
+};
+//---------------------------------------------------------------------------
+void mgcSpline::
+InitNull ()
+{
+ dimensions = 0;
+ degree = 0;
+ Dp1 = 0;
+ Dp1_to_N = 0;
+ Dp1_to_2N = 0;
+ dim = 0;
+ data = 0;
+ dom_min = 0;
+ dom_max = 0;
+ grid_min = 0;
+ grid_max = 0;
+ base = 0;
+ old_base = 0;
+ cache = 0;
+ inter = 0;
+ poly = 0;
+ coeff = 0;
+ matrix = 0;
+ product = 0;
+ skip = 0;
+}
+//---------------------------------------------------------------------------
+void mgcSpline::
+FreeStorage ()
+{
+ if ( dim == 0 ) // nothing to free
+ return;
+
+ delete[] dim;
+ delete[] base;
+ delete[] old_base;
+ delete[] dom_min;
+ delete[] dom_max;
+ delete[] grid_min;
+ delete[] grid_max;
+ delete[] cache;
+ delete[] inter;
+ delete[] product;
+ delete[] skip;
+
+ int d;
+ for (d = 0; d < dimensions; d++)
+ delete[] poly[d];
+ delete[] poly;
+
+ for (d = 0; d <= degree; d++) {
+ delete[] matrix[d];
+ delete[] coeff[d];
+ }
+ delete[] matrix;
+ delete[] coeff;
+}
+//---------------------------------------------------------------------------
+void mgcSpline::
+Create ()
+{
+ int k, d;
+
+ // setup degree constants
+ Dp1 = degree+1;
+ Dp1_to_N = 1;
+ for (d = 0; d < dimensions; d++)
+ Dp1_to_N *= Dp1;
+ Dp1_to_2N = Dp1_to_N*Dp1_to_N;
+
+ // initialize base indices
+ base = new int[dimensions];
+ if ( base == 0 ) {
+ Report(allocation_failed);
+ return;
+ }
+ old_base = new int[dimensions];
+ if ( old_base == 0 ) {
+ Report(allocation_failed);
+ return;
+ }
+ for (d = 0; d < dimensions; d++)
+ old_base[d] = -1;
+
+ grid_min = new int[dimensions];
+ if ( grid_min == 0 ) {
+ Report(allocation_failed);
+ return;
+ }
+ grid_max = new int[dimensions];
+ if ( grid_max == 0 ) {
+ Report(allocation_failed);
+ return;
+ }
+ for (d = 0; d < dimensions; d++) {
+ grid_min[d] = -1;
+ grid_max[d] = -1;
+ }
+
+ // compute domain [min,max] for B-spline
+ dom_min = new double[dimensions];
+ if ( dom_min == 0 ) {
+ Report(allocation_failed);
+ return;
+ }
+
+ dom_max = new double[dimensions];
+ if ( dom_max == 0 ) {
+ Report(allocation_failed);
+ return;
+ }
+
+ for (d = 0; d < dimensions; d++) {
+ double tmpmin = 1.0f, tmpmax, dom_sup = double(dim[d]-degree+1);
+ double next = (tmpmin+dom_sup)/2;
+ do {
+ tmpmax = next;
+ next = (next+dom_sup)/2;
+ } while ( next < dom_sup );
+
+ dom_min[d] = tmpmin;
+ dom_max[d] = tmpmax;
+ }
+
+ // cache for optimizing compute_intermediate()
+ cache = new double[Dp1_to_N];
+ if ( cache == 0 ) {
+ Report(allocation_failed);
+ return;
+ }
+
+ // storage for intermediate tensor product
+ inter = new double[Dp1_to_N];
+ if ( inter == 0 ) {
+ Report(allocation_failed);
+ return;
+ }
+
+ // polynomial allocations
+ poly = new double*[dimensions];
+ if ( poly == 0 ) {
+ Report(allocation_failed);
+ return;
+ }
+ for (d = 0; d < dimensions; d++) {
+ poly[d] = new double[Dp1];
+ if ( poly[d] == 0 ) {
+ Report(allocation_failed);
+ return;
+ }
+ }
+
+ // coefficients for polynomial calculations
+ coeff = new double*[Dp1];
+ if ( coeff == 0 ) {
+ Report(allocation_failed);
+ return;
+ }
+ for (int row = 0; row <= degree; row++) {
+ coeff[row] = new double[Dp1];
+ if ( coeff[row] == 0 ) {
+ Report(allocation_failed);
+ return;
+ }
+ for (int col = row; col <= degree; col++) {
+ coeff[row][col] = 1;
+ for (d = 0; d <= row-1; d++)
+ coeff[row][col] *= col-d;
+ }
+ }
+
+ // generate spline blending matrix
+ matrix = BlendMatrix(degree);
+
+ // tensor product of m with itself N times
+ product = new double[Dp1_to_2N];
+ if ( product == 0 ) {
+ Report(allocation_failed);
+ return;
+ }
+ skip = new int[Dp1_to_2N];
+ if ( skip == 0 ) {
+ Report(allocation_failed);
+ return;
+ }
+ int* coord = new int[2*dimensions]; // for address decoding
+ if ( coord == 0 ) {
+ Report(allocation_failed);
+ return;
+ }
+ for (k = 0; k < Dp1_to_2N; k++) {
+ int temp = k;
+ for (d = 0; d < 2*dimensions; d++) {
+ coord[d] = temp % Dp1;
+ temp /= Dp1;
+ }
+ product[k] = 1;
+ for (int s = 0; s < dimensions; s++)
+ product[k] *= matrix[coord[s]][coord[s+dimensions]];
+
+ skip[k] = 1;
+ }
+ delete[] coord;
+
+ // compute increments to skip zero values of mtensor
+ for (k = 0; k < Dp1_to_2N; ) {
+ for (d = k+1; d < Dp1_to_2N && product[d] == 0; d++)
+ skip[k]++;
+ k = d;
+ }
+
+ evaluate_callback = 0;
+}
+//---------------------------------------------------------------------------
+mgcSpline& mgcSpline::
+Renew (int _dimensions, int _degree, const int* _dim, double* _data)
+{
+ int d;
+
+ // blow away old data
+ FreeStorage();
+
+ // get number of dimensions
+ if ( (dimensions = _dimensions) <= 0 ) {
+ Report(invalid_dimensions);
+ return *this;
+ }
+
+ // get degree and check if valid
+ if ( (degree = _degree) <= 0 ) {
+ Report(invalid_degree);
+ return *this;
+ }
+
+ // get dimension bounds and check if valid
+ if ( _dim == 0 ) {
+ Report(invalid_dim);
+ return *this;
+ }
+
+ for (d = 0; d < dimensions; d++)
+ if ( _dim[d] <= degree+1 ) {
+ Report(invalid_dim);
+ return *this;
+ }
+
+ dim = new int[dimensions];
+ if ( dim == 0 ) {
+ Report(allocation_failed);
+ return *this;
+ }
+ for (d = 0; d < dimensions; d++)
+ dim[d] = _dim[d];
+
+ // get spline data
+ if ( (data = _data) == 0 ) {
+ Report(null_data);
+ return *this;
+ }
+
+ Create();
+
+ return *this;
+}
+//---------------------------------------------------------------------------
+mgcSpline::
+mgcSpline (int _dimensions, int _degree, const int* _dim, double* _data)
+{
+ InitNull();
+ Renew(_dimensions,_degree,_dim,_data);
+}
+//---------------------------------------------------------------------------
+void mgcSpline::
+SetPolynomial (int order, double diff, double* poly)
+{
+ double diffpower = 1;
+ for (int d = order; d <= degree; d++) {
+ poly[d] = coeff[order][d]*diffpower;
+ diffpower *= diff;
+ }
+}
+//---------------------------------------------------------------------------
+int mgcSpline::
+Choose (int n, int k)
+{
+ int i;
+
+ // computes combination "n choose k"
+
+ if ( n <= 1 || k >= n )
+ return 1;
+
+ int result = 1;
+ for (i = 0; i < k; i++)
+ result *= n-i;
+ for (i = 1; i <= k; i++)
+ result /= i;
+
+ return result;
+}
+//---------------------------------------------------------------------------
+double** mgcSpline::
+BlendMatrix (int deg)
+{
+ int degp1 = deg+1;
+ int row, col, i, j, d;
+
+ // allocate triple arrays
+ int*** a = new int**[degp1];
+ if ( a == 0 ) {
+ Report(allocation_failed);
+ return 0;
+ }
+ int*** b = new int**[degp1];
+ if ( b == 0 ) {
+ Report(allocation_failed);
+ return 0;
+ }
+ for (d = 0; d <= deg; d++) {
+ a[d] = new int*[degp1];
+ if ( a[d] == 0 ) {
+ Report(allocation_failed);
+ return 0;
+ }
+ b[d] = new int*[degp1];
+ if ( b[d] == 0 ) {
+ Report(allocation_failed);
+ return 0;
+ }
+ for (row = 0; row <= deg; row++) {
+ a[d][row] = new int[degp1];
+ if ( a[d][row] == 0 ) {
+ Report(allocation_failed);
+ return 0;
+ }
+ b[d][row] = new int[degp1];
+ if ( b[d][row] == 0 ) {
+ Report(allocation_failed);
+ return 0;
+ }
+ for (col = 0; col <= deg; col++) {
+ a[d][row][col] = 0;
+ b[d][row][col] = 0;
+ }
+ }
+ }
+
+ a[0][0][0] = 1;
+ b[0][0][0] = 1;
+
+ for (d = 1; d <= deg; d++) {
+ // compute a[]
+ for (row = 0; row <= d; row++) {
+ for (col = 0; col <= d; col++) {
+ a[d][row][col] = 0;
+ if ( col >= 1 ) {
+ a[d][row][col] += a[d-1][row][col-1];
+ if ( row >= 1 )
+ a[d][row][col] -= b[d-1][row-1][col-1];
+ }
+ if ( row >= 1 )
+ a[d][row][col] += (d+1)*b[d-1][row-1][col];
+ }
+ }
+
+ // compute b[]
+ for (row = 0; row <= d; row++) {
+ for (col = 0; col <= d; col++) {
+ b[d][row][col]= 0;
+ for (i = col; i <= d; i++)
+ if ( (i-col) % 2 )
+ b[d][row][col] -= Choose(i,col)*a[d][row][i];
+ else
+ b[d][row][col] += Choose(i,col)*a[d][row][i];
+ }
+ }
+ }
+
+ double** imat = new double*[degp1];
+ if ( imat == 0 ) {
+ Report(allocation_failed);
+ return 0;
+ }
+ for (row = 0; row <= deg; row++) {
+ imat[row] = new double[degp1];
+ if ( imat[row] == 0 ) {
+ Report(allocation_failed);
+ return 0;
+ }
+ for (col = 0; col <= deg; col++) {
+ imat[row][col]= 0;
+ for (i = col; i <= deg; i++) {
+ int prod = 1;
+ for (j = 1; j <= i-col; j++)
+ prod *= deg-row;
+ imat[row][col] += prod*Choose(i,col)*a[deg][deg-row][i];
+ }
+ }
+ }
+
+ double factorial = 1;
+ for (d = 1; d <= deg; d++)
+ factorial *= d;
+ double** mat = new double*[degp1];
+ if ( mat == 0 ) {
+ Report(allocation_failed);
+ return 0;
+ }
+ for (row = 0; row <= deg; row++) {
+ mat[row] = new double[degp1];
+ if ( mat[row] == 0 ) {
+ Report(allocation_failed);
+ return 0;
+ }
+ for (col = 0; col <= deg; col++)
+ mat[row][col] = imat[row][col]/factorial;
+ }
+
+ // deallocate triple arrays
+ for (d = 0; d <= deg; d++) {
+ for (row = 0; row <= deg; row++) {
+ delete[] b[d][row];
+ delete[] a[d][row];
+ }
+ delete[] b[d];
+ delete[] a[d];
+ }
+ delete[] b;
+ delete[] a;
+
+ // deallocate integer matrix
+ for (d = 0; d <= deg; d++)
+ delete[] imat[d];
+ delete[] imat;
+
+ return mat;
+}
+//---------------------------------------------------------------------------
+int mgcSpline::
+Number (unsigned single_error)
+{
+ int result;
+ for (result = -1; single_error; single_error >>= 1)
+ result++;
+ return result;
+}
+//---------------------------------------------------------------------------
+void mgcSpline::
+Report (unsigned single_error)
+{
+ if ( mgcSpline::verbose )
+ std::cout << "mgcSpline: " << message[Number(single_error)] << std::endl;
+ else
+ std::ofstream("spline.err",std::ios::out|std::ios::app)
+ << "mgcSpline: " << message[Number(single_error)] << std::endl;
+
+ error |= single_error;
+}
+//---------------------------------------------------------------------------
+void mgcSpline::
+Report (std::ostream& ostr)
+{
+ for (unsigned single_error = 1; single_error; single_error <<= 1)
+ if ( error & single_error )
+ ostr << "mgcSpline: " << message[Number(single_error)] << std::endl;
+
+ error = 0;
+}
+//===========================================================================
+const double mgcSplineD::INVALID_DATA = DBL_MAX;
+
+// error handling
+int mgcSplineD::verbose = 0;
+unsigned mgcSplineD::error = 0;
+const unsigned mgcSplineD::invalid_dimensions = 0x00000001;
+const unsigned mgcSplineD::invalid_degree = 0x00000002;
+const unsigned mgcSplineD::invalid_dim = 0x00000004;
+const unsigned mgcSplineD::null_data = 0x00000008;
+const unsigned mgcSplineD::allocation_failed = 0x00000010;
+const char* mgcSplineD::message[5] = {
+ "invalid number of dimensions",
+ "degree must be positive",
+ "dimension must be at least DEGREE+1",
+ "input data pointer is null",
+ "failed to allocate memory"
+};
+//---------------------------------------------------------------------------
+void mgcSplineD::
+InitNull ()
+{
+ dimensions = 0;
+ degree = 0;
+ Dp1 = 0;
+ Dp1_to_N = 0;
+ Dp1_to_2N = 0;
+ dim = 0;
+ data = 0;
+ dom_min = 0;
+ dom_max = 0;
+ grid_min = 0;
+ grid_max = 0;
+ base = 0;
+ old_base = 0;
+ cache = 0;
+ inter = 0;
+ poly = 0;
+ coeff = 0;
+ matrix = 0;
+ product = 0;
+ skip = 0;
+}
+//---------------------------------------------------------------------------
+void mgcSplineD::
+FreeStorage ()
+{
+ if ( dim == 0 ) // no storage to deallocate
+ return;
+
+ delete[] dim;
+ delete[] base;
+ delete[] old_base;
+ delete[] dom_min;
+ delete[] dom_max;
+ delete[] grid_min;
+ delete[] grid_max;
+ delete[] cache;
+ delete[] inter;
+ delete[] product;
+ delete[] skip;
+
+ int d;
+ for (d = 0; d < dimensions; d++)
+ delete[] poly[d];
+ delete[] poly;
+
+ for (d = 0; d <= degree; d++) {
+ delete[] matrix[d];
+ delete[] coeff[d];
+ }
+ delete[] matrix;
+ delete[] coeff;
+}
+//---------------------------------------------------------------------------
+void mgcSplineD::
+Create ()
+{
+ int k, d;
+
+ // setup degree constants
+ Dp1 = degree+1;
+ Dp1_to_N = 1;
+ for (d = 0; d < dimensions; d++)
+ Dp1_to_N *= Dp1;
+ Dp1_to_2N = Dp1_to_N*Dp1_to_N;
+
+ // initialize base indices
+ base = new int[dimensions];
+ if ( base == 0 ) {
+ Report(allocation_failed);
+ return;
+ }
+ old_base = new int[dimensions];
+ if ( old_base == 0 ) {
+ Report(allocation_failed);
+ return;
+ }
+ for (d = 0; d < dimensions; d++)
+ old_base[d] = -1;
+
+ grid_min = new int[dimensions];
+ if ( grid_min == 0 ) {
+ Report(allocation_failed);
+ return;
+ }
+ grid_max = new int[dimensions];
+ if ( grid_max == 0 ) {
+ Report(allocation_failed);
+ return;
+ }
+ for (d = 0; d < dimensions; d++) {
+ grid_min[d] = -1;
+ grid_max[d] = -1;
+ }
+
+ // compute domain [min,max] for B-spline
+ dom_min = new double[dimensions];
+ if ( dom_min == 0 ) {
+ Report(allocation_failed);
+ return;
+ }
+
+ dom_max = new double[dimensions];
+ if ( dom_max == 0 ) {
+ Report(allocation_failed);
+ return;
+ }
+
+ for (d = 0; d < dimensions; d++) {
+ double tmpmin = 1, tmpmax, dom_sup = dim[d]-degree+1;
+ double next = (tmpmin+dom_sup)/2;
+ do {
+ tmpmax = next;
+ next = (next+dom_sup)/2;
+ } while ( next < dom_sup );
+
+ dom_min[d] = tmpmin;
+ dom_max[d] = tmpmax;
+ }
+
+ // cache for optimizing compute_intermediate()
+ cache = new double[Dp1_to_N];
+ if ( cache == 0 ) {
+ Report(allocation_failed);
+ return;
+ }
+
+ // storage for intermediate tensor product
+ inter = new double[Dp1_to_N];
+ if ( inter == 0 ) {
+ Report(allocation_failed);
+ return;
+ }
+
+ // polynomial allocations
+ poly = new double*[dimensions];
+ if ( poly == 0 ) {
+ Report(allocation_failed);
+ return;
+ }
+ for (d = 0; d < dimensions; d++) {
+ poly[d] = new double[Dp1];
+ if ( poly[d] == 0 ) {
+ Report(allocation_failed);
+ return;
+ }
+ }
+
+ // coefficients for polynomial calculations
+ coeff = new double*[Dp1];
+ if ( coeff == 0 ) {
+ Report(allocation_failed);
+ return;
+ }
+ for (int row = 0; row <= degree; row++) {
+ coeff[row] = new double[Dp1];
+ if ( coeff[row] == 0 ) {
+ Report(allocation_failed);
+ return;
+ }
+ for (int col = row; col <= degree; col++) {
+ coeff[row][col] = 1;
+ for (d = 0; d <= row-1; d++)
+ coeff[row][col] *= col-d;
+ }
+ }
+
+ // generate spline blending matrix
+ matrix = BlendMatrix(degree);
+
+ // tensor product of m with itself N times
+ product = new double[Dp1_to_2N];
+ if ( product == 0 ) {
+ Report(allocation_failed);
+ return;
+ }
+ skip = new int[Dp1_to_2N];
+ if ( skip == 0 ) {
+ Report(allocation_failed);
+ return;
+ }
+ int* coord = new int[2*dimensions]; // for address decoding
+ if ( coord == 0 ) {
+ Report(allocation_failed);
+ return;
+ }
+ for (k = 0; k < Dp1_to_2N; k++) {
+ int temp = k;
+ for (d = 0; d < 2*dimensions; d++) {
+ coord[d] = temp % Dp1;
+ temp /= Dp1;
+ }
+ product[k] = 1;
+ for (int s = 0; s < dimensions; s++)
+ product[k] *= matrix[coord[s]][coord[s+dimensions]];
+
+ skip[k] = 1;
+ }
+ delete[] coord;
+
+ // compute increments to skip zero values of mtensor
+ for (k = 0; k < Dp1_to_2N; ) {
+ for (d = k+1; d < Dp1_to_2N && product[d] == 0; d++)
+ skip[k]++;
+ k = d;
+ }
+
+ evaluate_callback = 0;
+}
+//---------------------------------------------------------------------------
+mgcSplineD& mgcSplineD::
+Renew (int _dimensions, int _degree, const int* _dim, double* _data)
+{
+ // blow away old data
+ FreeStorage();
+
+ // get number of dimensions
+ if ( (dimensions = _dimensions) <= 0 ) {
+ Report(invalid_dimensions);
+ return *this;
+ }
+
+ // get degree and check if valid
+ if ( (degree = _degree) <= 0 ) {
+ Report(invalid_degree);
+ return *this;
+ }
+
+ // get dimension bounds and check if valid
+ if ( _dim == 0 ) {
+ Report(invalid_dim);
+ return *this;
+ }
+
+ int d;
+ for (d = 0; d < dimensions; d++)
+ if ( _dim[d] <= degree+1 ) {
+ Report(invalid_dim);
+ return *this;
+ }
+
+ dim = new int[dimensions];
+ if ( dim == 0 ) {
+ Report(allocation_failed);
+ return *this;
+ }
+ for (d = 0; d < dimensions; d++)
+ dim[d] = _dim[d];
+
+ // get spline data
+ if ( (data = _data) == 0 ) {
+ Report(null_data);
+ return *this;
+ }
+
+ Create();
+
+ return *this;
+}
+//---------------------------------------------------------------------------
+mgcSplineD::
+mgcSplineD (int _dimensions, int _degree, const int* _dim, double* _data)
+{
+ InitNull();
+ Renew(_dimensions,_degree,_dim,_data);
+}
+//---------------------------------------------------------------------------
+void mgcSplineD::
+SetPolynomial (int order, double diff, double* poly)
+{
+ double diffpower = 1;
+ for (int d = order; d <= degree; d++) {
+ poly[d] = coeff[order][d]*diffpower;
+ diffpower *= diff;
+ }
+}
+//---------------------------------------------------------------------------
+int mgcSplineD::
+Choose (int n, int k)
+{
+ int i;
+
+ // computes combination "n choose k"
+
+ if ( n <= 1 || k >= n )
+ return 1;
+
+ int result = 1;
+ for (i = 0; i < k; i++)
+ result *= n-i;
+ for (i = 1; i <= k; i++)
+ result /= i;
+
+ return result;
+}
+//---------------------------------------------------------------------------
+double** mgcSplineD::
+BlendMatrix (int deg)
+{
+ int degp1 = deg+1;
+ int row, col, i, j, d;
+
+ // allocate triple arrays
+ int*** a = new int**[degp1];
+ if ( a == 0 ) {
+ Report(allocation_failed);
+ return 0;
+ }
+ int*** b = new int**[degp1];
+ if ( b == 0 ) {
+ Report(allocation_failed);
+ return 0;
+ }
+ for (d = 0; d <= deg; d++) {
+ a[d] = new int*[degp1];
+ if ( a[d] == 0 ) {
+ Report(allocation_failed);
+ return 0;
+ }
+ b[d] = new int*[degp1];
+ if ( b[d] == 0 ) {
+ Report(allocation_failed);
+ return 0;
+ }
+ for (row = 0; row <= deg; row++) {
+ a[d][row] = new int[degp1];
+ if ( a[d][row] == 0 ) {
+ Report(allocation_failed);
+ return 0;
+ }
+ b[d][row] = new int[degp1];
+ if ( b[d][row] == 0 ) {
+ Report(allocation_failed);
+ return 0;
+ }
+ for (col = 0; col <= deg; col++) {
+ a[d][row][col] = 0;
+ b[d][row][col] = 0;
+ }
+ }
+ }
+
+ a[0][0][0] = 1;
+ b[0][0][0] = 1;
+
+ for (d = 1; d <= deg; d++) {
+ // compute a[]
+ for (row = 0; row <= d; row++) {
+ for (col = 0; col <= d; col++) {
+ a[d][row][col] = 0;
+ if ( col >= 1 ) {
+ a[d][row][col] += a[d-1][row][col-1];
+ if ( row >= 1 )
+ a[d][row][col] -= b[d-1][row-1][col-1];
+ }
+ if ( row >= 1 )
+ a[d][row][col] += (d+1)*b[d-1][row-1][col];
+ }
+ }
+
+ // compute b[]
+ for (row = 0; row <= d; row++) {
+ for (col = 0; col <= d; col++) {
+ b[d][row][col]= 0;
+ for (i = col; i <= d; i++)
+ if ( (i-col) % 2 )
+ b[d][row][col] -= Choose(i,col)*a[d][row][i];
+ else
+ b[d][row][col] += Choose(i,col)*a[d][row][i];
+ }
+ }
+ }
+
+ double** imat = new double*[degp1];
+ if ( imat == 0 ) {
+ Report(allocation_failed);
+ return 0;
+ }
+ for (row = 0; row <= deg; row++) {
+ imat[row] = new double[degp1];
+ if ( imat[row] == 0 ) {
+ Report(allocation_failed);
+ return 0;
+ }
+ for (col = 0; col <= deg; col++) {
+ imat[row][col]= 0;
+ for (i = col; i <= deg; i++) {
+ int prod = 1;
+ for (j = 1; j <= i-col; j++)
+ prod *= deg-row;
+ imat[row][col] += prod*Choose(i,col)*a[deg][deg-row][i];
+ }
+ }
+ }
+
+ double factorial = 1;
+ for (d = 1; d <= deg; d++)
+ factorial *= d;
+ double** mat = new double*[degp1];
+ if ( mat == 0 ) {
+ Report(allocation_failed);
+ return 0;
+ }
+ for (row = 0; row <= deg; row++) {
+ mat[row] = new double[degp1];
+ if ( mat[row] == 0 ) {
+ Report(allocation_failed);
+ return 0;
+ }
+ for (col = 0; col <= deg; col++)
+ mat[row][col] = imat[row][col]/factorial;
+ }
+
+ // deallocate triple arrays
+ for (d = 0; d <= deg; d++) {
+ for (row = 0; row <= deg; row++) {
+ delete[] b[d][row];
+ delete[] a[d][row];
+ }
+ delete[] b[d];
+ delete[] a[d];
+ }
+ delete[] b;
+ delete[] a;
+
+ // deallocate integer matrix
+ for (d = 0; d <= deg; d++)
+ delete[] imat[d];
+ delete[] imat;
+
+ return mat;
+}
+//---------------------------------------------------------------------------
+int mgcSplineD::
+Number (unsigned single_error)
+{
+ int result;
+ for (result = -1; single_error; single_error >>= 1)
+ result++;
+ return result;
+}
+//---------------------------------------------------------------------------
+void mgcSplineD::
+Report (unsigned single_error)
+{
+ if ( mgcSplineD::verbose )
+ std::cout << "mgcSplineD: " << message[Number(single_error)] << std::endl;
+ else
+ std::ofstream("spline.err",std::ios::out|std::ios::app)
+ << "mgcSplineD: " << message[Number(single_error)] << std::endl;
+
+ error |= single_error;
+}
+//---------------------------------------------------------------------------
+void mgcSplineD::
+Report (std::ostream& ostr)
+{
+ for (unsigned single_error = 1; single_error; single_error <<= 1)
+ if ( error & single_error )
+ ostr << "mgcSplineD: " << message[Number(single_error)] << std::endl;
+
+ error = 0;
+}
+//===========================================================================
+
sandbox/magfield/src
--- sandbox/magfield/src/spline.h (rev 0)
+++ sandbox/magfield/src/spline.h 2014-04-03 15:54:52 UTC (rev 3075)
@@ -0,0 +1,177 @@
+// Magic Software, Inc.
+// http://www.magic-software.com
+// Copyright (c) 2000, 2001. All Rights Reserved
+//
+// Source code from Magic Software is supplied under the terms of a license
+// agreement and may not be copied or disclosed except in accordance with the
+// terms of that agreement. The various license agreements may be found at
+// the Magic Software web site. This file is subject to the license
+//
+// FREE SOURCE CODE
+// http://www.magic-software.com/License/free.pdf
+
+#ifndef SPLINE_H
+#define SPLINE_H
+
+#include <iostream>
+#include <math.h>
+
+class mgcSpline
+{
+public:
+ mgcSpline () { InitNull(); }
+ mgcSpline (int _dimensions, int _degree, const int* _dim, double* _data);
+ virtual ~mgcSpline () { FreeStorage(); }
+
+ int Dimensions () { return dimensions; }
+ int Degree () { return degree; }
+ const double** Matrix () { return (const double**)matrix; }
+ double DomainMin (int d = 0) { return dom_min[d]; }
+ double DomainMax (int d = 0) { return dom_max[d]; }
+ int GridMin (int d = 0) { return grid_min[d]; }
+ int GridMax (int d = 0) { return grid_max[d]; }
+ double (*evaluate_callback)(int);
+
+ static const double INVALID_DATA;
+
+ // spline evaluation for function interpolation (no derivatives)
+ virtual double operator() (double* x) = 0;
+
+ // spline evaluation, derivative counts given in dx[]
+ virtual double operator() (int* dx, double* x) = 0;
+
+ // reallocate spline with new parameters
+ mgcSpline& Renew ( int _dimensions, int _degree, const int* _dim,
+ double* _data );
+
+protected:
+ int dimensions; // N, number of dimensions
+ int degree; // D, degree of polynomial spline
+ int Dp1; // D+1
+ int Dp1_to_N; // power(D+1,N)
+ int Dp1_to_2N; // power(D+1,2N)
+ int* dim; // dimension sizes dim[0] through dim[N-1]
+ double* data; // N-dimensional array of data
+ double* dom_min; // minimum allowed value of spline input vector
+ double* dom_max; // maximum allowed value of spline input vector
+ int* grid_min; // minimum allowed value for current local grid
+ int* grid_max; // maximum allowed value for current local grid
+ int* base; // base indices for grid of local control points
+ int* old_base; // old base indices for grid of local control points
+ double* cache; // cache for subblock of data
+ double* inter; // intermediate product of data with blending matrix
+ double** poly; // poly[N][D+1] for storing polynomials and derivatives
+ double** coeff; // coefficients for polynomial construction
+ double** matrix; // (D+1)x(D+1) blending matrix
+ double* product; // outer tensor product of m with itself N times
+ int* skip; // for skipping zero values of mtensor
+
+ virtual void EvaluateUnknownData () = 0;
+ virtual void ComputeIntermediate () = 0;
+ void SetPolynomial (int order, double diff, double* poly);
+
+private:
+ void InitNull ();
+ void FreeStorage ();
+ void Create ();
+ static int Choose (int n, int k);
+ static double** BlendMatrix (int deg);
+
+// error handling
+public:
+ static int verbose;
+ static unsigned error;
+ static void Report (std::ostream& ostr);
+private:
+ static const unsigned invalid_dimensions;
+ static const unsigned invalid_degree;
+ static const unsigned invalid_dim;
+ static const unsigned null_data;
+ static const unsigned allocation_failed;
+ static const char* message[5];
+ static int Number (unsigned single_error);
+ static void Report (unsigned single_error);
+};
+
+
+
+class mgcSplineD
+{
+public:
+ mgcSplineD () { InitNull(); }
+ mgcSplineD (int _dimensions, int _degree, const int* _dim, double* _data);
+ virtual ~mgcSplineD () { FreeStorage(); }
+
+ int Dimensions () { return dimensions; }
+ int Degree () { return degree; }
+ const double** Matrix () { return (const double**)matrix; }
+ double DomainMin (int d = 0) { return dom_min[d]; }
+ double DomainMax (int d = 0) { return dom_max[d]; }
+ int GridMin (int d = 0) { return grid_min[d]; }
+ int GridMax (int d = 0) { return grid_max[d]; }
+ double (*evaluate_callback)(int);
+
+ static const double INVALID_DATA;
+
+ // spline evaluation for function interpolation (no derivatives)
+ virtual double operator() (double* x) = 0;
+
+ // spline evaluation, derivative counts given in dx[]
+ virtual double operator() (int* dx, double* x) = 0;
+
+ // reallocate spline with new parameters
+ mgcSplineD& Renew ( int _dimensions, int _degree, const int* _dim,
+ double* _data );
+
+protected:
+ int dimensions; // N, number of dimensions
+ int degree; // D, degree of polynomial spline
+ int Dp1; // D+1
+ int Dp1_to_N; // power(D+1,N)
+ int Dp1_to_2N; // power(D+1,2N)
+ int* dim; // dimension sizes dim[0] through dim[N-1]
+ double* data; // N-dimensional array of data
+ double* dom_min; // minimum allowed value of spline input vector
+ double* dom_max; // maximum allowed value of spline input vector
+ int* grid_min; // minimum allowed value for current local grid
+ int* grid_max; // maximum allowed value for current local grid
+ int* base; // base indices for grid of local control points
+ int* old_base; // old base indices for grid of local control points
+ double* cache; // cache for subblock of data
+ double* inter; // intermediate product of data with blending matrix
+ double** poly; // poly[N][D+1] for storing polynomials and derivatives
+ double** coeff; // coefficients for polynomial construction
+ double** matrix; // (D+1)x(D+1) blending matrix
+ double* product; // outer tensor product of m with itself N times
+ int* skip; // for skipping zero values of mtensor
+
+ virtual void EvaluateUnknownData () = 0;
+ virtual void ComputeIntermediate () = 0;
+ void SetPolynomial (int order, double diff, double* poly);
+
+private:
+ void InitNull ();
+ void FreeStorage ();
+ void Create ();
+ static int Choose (int n, int k);
+ static double** BlendMatrix (int deg);
+
+// error handling
+public:
+ static int verbose;
+ static unsigned error;
+ static void Report (std::ostream& ostr);
+private:
+ static const unsigned invalid_dimensions;
+ static const unsigned invalid_degree;
+ static const unsigned invalid_dim;
+ static const unsigned null_data;
+ static const unsigned allocation_failed;
+ static const char* message[5];
+ static int Number (unsigned single_error);
+ static void Report (unsigned single_error);
+};
+
+
+#endif
+
sandbox/magfield/src
--- sandbox/magfield/src/spline1.cpp (rev 0)
+++ sandbox/magfield/src/spline1.cpp 2014-04-03 15:54:52 UTC (rev 3075)
@@ -0,0 +1,173 @@
+// Magic Software, Inc.
+// http://www.magic-software.com
+// Copyright (c) 2000, 2001. All Rights Reserved
+//
+// Source code from Magic Software is supplied under the terms of a license
+// agreement and may not be copied or disclosed except in accordance with the
+// terms of that agreement. The various license agreements may be found at
+// the Magic Software web site. This file is subject to the license
+//
+// FREE SOURCE CODE
+// http://www.magic-software.com/License/free.pdf
+
+#include "spline1.h"
+//===========================================================================
+const int mgcSpline1::N = 1;
+//---------------------------------------------------------------------------
+mgcSpline1::
+mgcSpline1 (int _degree, int _dim, double* _data) :
+ mgcSpline(N,_degree,&_dim,_data)
+{
+}
+//---------------------------------------------------------------------------
+void mgcSpline1::
+EvaluateUnknownData ()
+{
+ for (int k = grid_min[0]; k <= grid_max[0]; k++)
+ if ( data[k] == INVALID_DATA )
+ data[k] = evaluate_callback(k);
+}
+//---------------------------------------------------------------------------
+void mgcSpline1::
+ComputeIntermediate ()
+{
+ for (int k = 0; k <= degree; k++) {
+ inter[k] = 0;
+ for (int i = 0, j = base[0]-1; i <= degree; i++, j++)
+ inter[k] += data[j]*matrix[i][k];
+ }
+}
+//---------------------------------------------------------------------------
+double mgcSpline1::
+operator () (double x)
+{
+ base[0] = int(floor(x));
+ if ( old_base[0] != base[0] ) {
+ // switch to new local grid
+ old_base[0] = base[0];
+ grid_min[0] = base[0]-1;
+ grid_max[0] = grid_min[0]+degree;
+
+ // fill in missing grid data if necessary
+ if ( evaluate_callback )
+ EvaluateUnknownData();
+
+ ComputeIntermediate();
+ }
+
+ SetPolynomial(0,x-base[0],poly[0]);
+
+ double result = 0;
+ for (int k = 0; k <= degree; k++)
+ result += poly[0][k]*inter[k];
+ return result;
+}
+//---------------------------------------------------------------------------
+double mgcSpline1::
+operator () (int dx, double x)
+{
+ base[0] = int(floor(x));
+ if ( old_base[0] != base[0] ) {
+ // switch to new local grid
+ old_base[0] = base[0];
+ grid_min[0] = base[0]-1;
+ grid_max[0] = grid_min[0]+degree;
+
+ // fill in missing grid data if necessary
+ if ( evaluate_callback )
+ EvaluateUnknownData();
+
+ ComputeIntermediate();
+ }
+
+ SetPolynomial(dx,x-base[0],poly[0]);
+
+ double result = 0;
+ for (int k = dx; k <= degree; k++)
+ result += poly[0][k]*inter[k];
+ return result;
+}
+//===========================================================================
+const int mgcSplineD1::N = 1;
+//---------------------------------------------------------------------------
+mgcSplineD1::
+mgcSplineD1 (int _degree, int _dim, double* _data) :
+ mgcSplineD(N,_degree,&_dim,_data)
+{
+}
+//---------------------------------------------------------------------------
+void mgcSplineD1::
+EvaluateUnknownData ()
+{
+ for (int k = grid_min[0]; k <= grid_max[0]; k++)
+ if ( data[k] == INVALID_DATA )
+ data[k] = evaluate_callback(k);
+}
+//---------------------------------------------------------------------------
+void mgcSplineD1::
+ComputeIntermediate ()
+{
+ for (int k = 0; k <= degree; k++) {
+ inter[k] = 0;
+ for (int i = 0, j = base[0]-1; i <= degree; i++, j++)
+ inter[k] += data[j]*matrix[i][k];
+ }
+}
+//---------------------------------------------------------------------------
+double mgcSplineD1::
+operator () (double x)
+{
+ base[0] = int(floor(x));
+ if ( old_base[0] != base[0] ) {
+ // switch to new local grid
+ old_base[0] = base[0];
+ grid_min[0] = base[0]-1;
+ grid_max[0] = grid_min[0]+degree;
+
+ // fill in missing grid data if necessary
+ if ( evaluate_callback )
+ EvaluateUnknownData();
+
+ ComputeIntermediate();
+ }
+
+ SetPolynomial(0,x-base[0],poly[0]);
+
+ double result = 0;
+ for (int k = 0; k <= degree; k++)
+ result += poly[0][k]*inter[k];
+ return result;
+}
+//---------------------------------------------------------------------------
+double mgcSplineD1::
+operator () (int dx, double x)
+{
+ base[0] = int(floor(x));
+ if ( old_base[0] != base[0] ) {
+ // switch to new local grid
+ old_base[0] = base[0];
+ grid_min[0] = base[0]-1;
+ grid_max[0] = grid_min[0]+degree;
+
+ // fill in missing grid data if necessary
+ if ( evaluate_callback )
+ EvaluateUnknownData();
+
+ ComputeIntermediate();
+ }
+
+ SetPolynomial(dx,x-base[0],poly[0]);
+
+ double result = 0;
+ for (int k = dx; k <= degree; k++)
+ result += poly[0][k]*inter[k];
+ return result;
+}
+//===========================================================================
+
+
+#ifdef SPLINE1_TEST
+
+
+#endif
+
sandbox/magfield/src
--- sandbox/magfield/src/spline1.h (rev 0)
+++ sandbox/magfield/src/spline1.h 2014-04-03 15:54:52 UTC (rev 3075)
@@ -0,0 +1,74 @@
+// Magic Software, Inc.
+// http://www.magic-software.com
+// Copyright (c) 2000, 2001. All Rights Reserved
+//
+// Source code from Magic Software is supplied under the terms of a license
+// agreement and may not be copied or disclosed except in accordance with the
+// terms of that agreement. The various license agreements may be found at
+// the Magic Software web site. This file is subject to the license
+//
+// FREE SOURCE CODE
+// http://www.magic-software.com/License/free.pdf
+
+#ifndef SPLINE1_H
+#define SPLINE1_H
+
+#include "spline.h"
+class mgcSpline1 : public mgcSpline
+{
+public:
+ mgcSpline1 () : mgcSpline() {;}
+ mgcSpline1 (int _degree, int _dim, double* _data);
+
+ // spline evaluation for function interpolation (no derivatives)
+ double operator() (double x);
+ double operator() (double* x) { return (*this)(*x); }
+
+ // spline evaluation, derivative count given in dx
+ double operator() (int dx, double x);
+ double operator() (int* dx, double* x) { return (*this)(*dx,*x); }
+
+ // reallocate spline with new parameters
+ mgcSpline1& Renew (int _degree, int _dim, double* _data)
+ {
+ mgcSpline::Renew(1,_degree,(const int*)&_dim,_data);
+ return *this;
+ }
+
+private:
+ static const int N;
+
+ void EvaluateUnknownData ();
+ void ComputeIntermediate ();
+};
+
+
+class mgcSplineD1 : public mgcSplineD
+{
+public:
+ mgcSplineD1 () : mgcSplineD() {;}
+ mgcSplineD1 (int _degree, int _dim, double* _data);
+
+ // spline evaluation for function interpolation (no derivatives)
+ double operator() (double x);
+ double operator() (double* x) { return (*this)(*x); }
+
+ // spline evaluation, derivative count given in dx
+ double operator() (int dx, double x);
+ double operator() (int* dx, double* x) { return (*this)(*dx,*x); }
+
+ // reallocate spline with new parameters
+ mgcSplineD1& Renew (int _degree, int _dim, double* _data)
+ {
+ mgcSplineD::Renew(1,_degree,(const int*)&_dim,_data);
+ return *this;
+ }
+
+private:
+ static const int N;
+
+ void EvaluateUnknownData ();
+ void ComputeIntermediate ();
+};
+#endif
+
SVNspam 0.1