Simbody
|
00001 #ifndef SimTK_SIMMATH_GCVSPL_UTIL_H_ 00002 #define SimTK_SIMMATH_GCVSPL_UTIL_H_ 00003 00004 /* -------------------------------------------------------------------------- * 00005 * SimTK Core: SimTK Simmath(tm) * 00006 * -------------------------------------------------------------------------- * 00007 * This is part of the SimTK Core biosimulation toolkit originating from * 00008 * Simbios, the NIH National Center for Physics-Based Simulation of * 00009 * Biological Structures at Stanford, funded under the NIH Roadmap for * 00010 * Medical Research, grant U54 GM072970. See https://simtk.org. * 00011 * * 00012 * Portions copyright (c) 2008 Stanford University and the Authors. * 00013 * Authors: Peter Eastman * 00014 * Contributors: * 00015 * * 00016 * Permission is hereby granted, free of charge, to any person obtaining a * 00017 * copy of this software and associated documentation files (the "Software"), * 00018 * to deal in the Software without restriction, including without limitation * 00019 * the rights to use, copy, modify, merge, publish, distribute, sublicense, * 00020 * and/or sell copies of the Software, and to permit persons to whom the * 00021 * Software is furnished to do so, subject to the following conditions: * 00022 * * 00023 * The above copyright notice and this permission notice shall be included in * 00024 * all copies or substantial portions of the Software. * 00025 * * 00026 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * 00027 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * 00028 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * 00029 * THE AUTHORS, CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 00030 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 00031 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * 00032 * USE OR OTHER DEALINGS IN THE SOFTWARE. * 00033 * -------------------------------------------------------------------------- */ 00034 00035 #include "SimTKcommon.h" 00036 #include "simmath/internal/common.h" 00037 00038 // These are global functions. 00039 int SimTK_gcvspl_(const SimTK::Real *, const SimTK::Real *, int *, const SimTK::Real *, const SimTK::Real *, int *, int *, 00040 int *, int *, SimTK::Real *, SimTK::Real *, int *, SimTK::Real *, int *); 00041 SimTK::Real SimTK_splder_(int *, int *, int *, SimTK::Real *, const SimTK::Real *, const SimTK::Real *, int *, SimTK::Real *, int); 00042 00043 namespace SimTK { 00044 00052 class SimTK_SIMMATH_EXPORT GCVSPLUtil { 00053 public: 00054 static void gcvspl(const Vector& x, const Vector& y, const Vector& wx, Real wy, int m, int md, Real val, Vector& c, Vector& wk, int& ier); 00055 template <int K> 00056 static void gcvspl(const Vector& x, const Vector_<Vec<K> >& y, const Vector& wx, Vec<K> wy, int m, int md, Real val, Vector_<Vec<K> >& c, Vector& wk, int& ier); 00057 static Real splder(int derivOrder, int degree, Real t, const Vector& x, const Vector& coeff); 00058 template <int K> 00059 static Vec<K> splder(int derivOrder, int degree, Real t, const Vector& x, const Vector_<Vec<K> >& coeff); 00060 }; 00061 00062 template <int K> 00063 void GCVSPLUtil::gcvspl(const Vector& x, const Vector_<Vec<K> >& y, const Vector& wx, Vec<K> wy, int degree, int md, Real val, Vector_<Vec<K> >& c, Vector& wk, int& ier) { 00064 SimTK_APIARGCHECK_ALWAYS(degree > 0 && degree%2==1, "GCVSPLUtil", "gcvspl", "degree must be positive and odd"); 00065 SimTK_APIARGCHECK_ALWAYS(y.size() >= x.size(), "GCVSPLUtil", "gcvspl", "y is shorter than x"); 00066 SimTK_APIARGCHECK_ALWAYS(wx.size() >= x.size(), "GCVSPLUtil", "gcvspl", "wx and x must be the same size"); 00067 SimTK_APIARGCHECK_ALWAYS(x.hasContiguousData(), "GCVSPLUtil", "gcvspl", "x must have contiguous storage (i.e. not be a view)"); 00068 SimTK_APIARGCHECK_ALWAYS(wk.hasContiguousData(), "GCVSPLUtil", "gcvspl", "wk must have contiguous storage (i.e. not be a view)"); 00069 00070 // Create various temporary variables. 00071 00072 int m = (degree+1)/2; 00073 int n = x.size(); 00074 int ny = y.size(); 00075 Vector yvec(ny*K); 00076 int index = 0; 00077 for (int j = 0; j < K; ++j) 00078 for (int i = 0; i < ny; ++i) 00079 yvec[index++] = y[i][j]; 00080 int nc = n*K; 00081 Vector cvec(nc); 00082 wk.resize(6*(m*n+1)+n); 00083 int k = K; 00084 00085 // Invoke GCV. 00086 00087 SimTK_gcvspl_(&x[0], &yvec[0], &ny, &wx[0], &wy[0], &m, &n, &k, &md, &val, &cvec[0], &n, &wk[0], &ier); 00088 if (ier != 0) { 00089 SimTK_APIARGCHECK_ALWAYS(n >= 2*m, "GCVSPLUtil", "gcvspl", "Too few data points"); 00090 SimTK_APIARGCHECK_ALWAYS(ier != 2, "GCVSPLUtil", "gcvspl", "The values in x must be strictly increasing"); 00091 SimTK_APIARGCHECK_ALWAYS(ier == 0, "GCVSPLUtil", "gcvspl", "GCVSPL returned an error code"); 00092 } 00093 c.resize(n); 00094 index = 0; 00095 for (int j = 0; j < K; ++j) 00096 for (int i = 0; i < n; ++i) 00097 c[i][j] = cvec[index++]; 00098 } 00099 00100 template <int K> 00101 Vec<K> GCVSPLUtil::splder(int derivOrder, int degree, Real t, const Vector& x, const Vector_<Vec<K> >& coeff) { 00102 assert(derivOrder >= 0); 00103 assert(t >= x[0] && t <= x[x.size()-1]); 00104 assert(x.size() == coeff.size()); 00105 assert(degree > 0 && degree%2==1); 00106 assert(x.hasContiguousData()); 00107 00108 // Create various temporary variables. 00109 00110 Vec<K> result; 00111 int m = (degree+1)/2; 00112 int n = x.size(); 00113 int interval = (int) ceil(n*(t-x[0])/(x[n-1]-x[0])); 00114 Vector_<double> q(2*m); 00115 int offset = (int) (&coeff[1][0]-&coeff[0][0]); 00116 00117 // Evaluate the spline one component at a time. 00118 00119 for (int i = 0; i < K; ++i) 00120 result[i] = SimTK_splder_(&derivOrder, &m, &n, &t, &x[0], &coeff[0][i], &interval, &q[0], offset); 00121 return result; 00122 } 00123 00124 } // namespace SimTK 00125 00126 #endif // SimTK_SIMMATH_GCVSPL_UTIL_H_ 00127 00128