00001 #ifndef SimTK_SIMMATH_GCVSPL_UTIL_H_
00002 #define SimTK_SIMMATH_GCVSPL_UTIL_H_
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "SimTKcommon.h"
00036 #include "simmath/internal/common.h"
00037
00038 int gcvspl_(const SimTK::Real *, const SimTK::Real *, int *, const SimTK::Real *, const SimTK::Real *, int *, int *,
00039 int *, int *, SimTK::Real *, SimTK::Real *, int *, SimTK::Real *, int *);
00040 SimTK::Real splder_(int *, int *, int *, SimTK::Real *, const SimTK::Real *, const SimTK::Real *, int *, SimTK::Real *, int);
00041
00042 namespace SimTK {
00043
00051 class SimTK_SIMMATH_EXPORT GCVSPLUtil {
00052 public:
00053 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);
00054 template <int K>
00055 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);
00056 static Real splder(int derivOrder, int degree, Real t, const Vector& x, const Vector& coeff);
00057 template <int K>
00058 static Vec<K> splder(int derivOrder, int degree, Real t, const Vector& x, const Vector_<Vec<K> >& coeff);
00059 };
00060
00061 template <int K>
00062 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) {
00063 SimTK_APIARGCHECK_ALWAYS(degree > 0 && degree%2==1, "GCVSPLUtil", "gcvspl", "degree must be positive and odd");
00064 SimTK_APIARGCHECK_ALWAYS(y.size() >= x.size(), "GCVSPLUtil", "gcvspl", "y is shorter than x");
00065 SimTK_APIARGCHECK_ALWAYS(wx.size() >= x.size(), "GCVSPLUtil", "gcvspl", "wx and x must be the same size");
00066 SimTK_APIARGCHECK_ALWAYS(x.hasContiguousData(), "GCVSPLUtil", "gcvspl", "x must have contiguous storage (i.e. not be a view)");
00067 SimTK_APIARGCHECK_ALWAYS(wk.hasContiguousData(), "GCVSPLUtil", "gcvspl", "wk must have contiguous storage (i.e. not be a view)");
00068
00069
00070
00071 int m = (degree+1)/2;
00072 int n = x.size();
00073 int ny = y.size();
00074 Vector yvec(ny*K);
00075 int index = 0;
00076 for (int j = 0; j < K; ++j)
00077 for (int i = 0; i < ny; ++i)
00078 yvec[index++] = y[i][j];
00079 int nc = n*K;
00080 Vector cvec(nc);
00081 wk.resize(6*(m*n+1)+n);
00082 int k = K;
00083
00084
00085
00086 gcvspl_(&x[0], &yvec[0], &ny, &wx[0], &wy[0], &m, &n, &k, &md, &val, &cvec[0], &n, &wk[0], &ier);
00087 if (ier != 0) {
00088 SimTK_APIARGCHECK_ALWAYS(n >= 2*m, "GCVSPLUtil", "gcvspl", "Too few data points");
00089 SimTK_APIARGCHECK_ALWAYS(ier != 2, "GCVSPLUtil", "gcvspl", "The values in x must be strictly increasing");
00090 SimTK_APIARGCHECK_ALWAYS(ier == 0, "GCVSPLUtil", "gcvspl", "GCVSPL returned an error code");
00091 }
00092 c.resize(n);
00093 index = 0;
00094 for (int j = 0; j < K; ++j)
00095 for (int i = 0; i < n; ++i)
00096 c[i][j] = cvec[index++];
00097 }
00098
00099 template <int K>
00100 Vec<K> GCVSPLUtil::splder(int derivOrder, int degree, Real t, const Vector& x, const Vector_<Vec<K> >& coeff) {
00101 assert(derivOrder >= 0);
00102 assert(t >= x[0] && t <= x[x.size()-1]);
00103 assert(x.size() == coeff.size());
00104 assert(degree > 0 && degree%2==1);
00105 assert(x.hasContiguousData());
00106
00107
00108
00109 Vec<K> result;
00110 int m = (degree+1)/2;
00111 int n = x.size();
00112 int interval = (int) ceil(n*(t-x[0])/(x[n-1]-x[0]));
00113 Vector_<double> q(2*m);
00114 int offset = (int) (&coeff[1][0]-&coeff[0][0]);
00115
00116
00117
00118 for (int i = 0; i < K; ++i)
00119 result[i] = splder_(&derivOrder, &m, &n, &t, &x[0], &coeff[0][i], &interval, &q[0], offset);
00120 return result;
00121 }
00122
00123 }
00124
00125 #endif // SimTK_SIMMATH_GCVSPL_UTIL_H_
00126
00127