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 template <int K>
00054 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);
00055 template <int K>
00056 static Vec<K> splder(int derivOrder, int degree, Real t, const Vector& x, const Vector_<Vec<K> >&coeff);
00057 };
00058
00059 template <int K>
00060 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) {
00061 SimTK_APIARGCHECK_ALWAYS(degree > 0 && degree%2==1, "GCVSPLUtil", "gcvspl", "degree must be positive and odd");
00062 SimTK_APIARGCHECK_ALWAYS(y.size() >= x.size(), "GCVSPLUtil", "gcvspl", "y is shorter than x");
00063 SimTK_APIARGCHECK_ALWAYS(wx.size() >= x.size(), "GCVSPLUtil", "gcvspl", "wx and x must be the same size");
00064 SimTK_APIARGCHECK_ALWAYS(x.hasContiguousData(), "GCVSPLUtil", "gcvspl", "x must have contiguous storage (i.e. not be a view)");
00065 SimTK_APIARGCHECK_ALWAYS(wk.hasContiguousData(), "GCVSPLUtil", "gcvspl", "wk must have contiguous storage (i.e. not be a view)");
00066
00067
00068
00069 int m = (degree+1)/2;
00070 int n = x.size();
00071 int ny = y.size();
00072 Vector yvec(ny*K);
00073 int index = 0;
00074 for (int j = 0; j < K; ++j)
00075 for (int i = 0; i < ny; ++i)
00076 yvec[index++] = y[i][j];
00077 int nc = n*K;
00078 Vector cvec(nc);
00079 wk.resize(6*(m*n+1)+n);
00080 int k = K;
00081
00082
00083
00084 gcvspl_(&x[0], &yvec[0], &ny, &wx[0], &wy[0], &m, &n, &k, &md, &val, &cvec[0], &n, &wk[0], &ier);
00085 if (ier != 0) {
00086 SimTK_APIARGCHECK_ALWAYS(n >= 2*m, "GCVSPLUtil", "gcvspl", "Too few data points");
00087 SimTK_APIARGCHECK_ALWAYS(ier != 2, "GCVSPLUtil", "gcvspl", "The values in x must be strictly increasing");
00088 SimTK_APIARGCHECK_ALWAYS(ier == 0, "GCVSPLUtil", "gcvspl", "GCVSPL returned an error code");
00089 }
00090 c.resize(n);
00091 index = 0;
00092 for (int j = 0; j < K; ++j)
00093 for (int i = 0; i < n; ++i)
00094 c[i][j] = cvec[index++];
00095 }
00096
00097 template <int K>
00098 Vec<K> GCVSPLUtil::splder(int derivOrder, int degree, Real t, const Vector& x, const Vector_<Vec<K> >&coeff) {
00099 assert(derivOrder >= 0);
00100 assert(t >= x[0] && t <= x[x.size()-1]);
00101 assert(x.size() == coeff.size());
00102 assert(degree > 0 && degree%2==1);
00103 assert(x.hasContiguousData());
00104
00105
00106
00107 Vec<K> result;
00108 int m = (degree+1)/2;
00109 int n = x.size();
00110 int interval = (int) ceil(n*(t-x[0])/(x[n-1]-x[0]));
00111 Vector_<double> q(2*m);
00112 int offset = (int) (&coeff[1][0]-&coeff[0][0]);
00113
00114
00115
00116 for (int i = 0; i < K; ++i)
00117 result[i] = splder_(&derivOrder, &m, &n, &t, &x[0], &coeff[0][i], &interval, &q[0], offset);
00118 return result;
00119 }
00120
00121 }
00122
00123 #endif // SimTK_SIMMATH_GCVSPL_UTIL_H_
00124
00125