Print

Print


Commit in sandbox/magfield/src on MAIN
spline.cpp+987added 3075
spline.h+177added 3075
spline1.cpp+173added 3075
spline1.h+74added 3075
+1411
4 added files
core spline classes to be used for fitting the field map.

sandbox/magfield/src
spline.cpp added at 3075
--- 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
spline.h added at 3075
--- 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
spline1.cpp added at 3075
--- 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
spline1.h added at 3075
--- 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


Use REPLY-ALL to reply to list

To unsubscribe from the LCDET-SVN list, click the following link:
https://listserv.slac.stanford.edu/cgi-bin/wa?SUBED1=LCDET-SVN&A=1