00001 #ifndef SimTK_SimTKCOMMON_FUNCTION_H_
00002 #define SimTK_SimTKCOMMON_FUNCTION_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
00036
00037
00038 #include "SimTKcommon/basics.h"
00039 #include "SimTKcommon/Simmatrix.h"
00040 #include <cassert>
00041
00042 namespace SimTK {
00043
00058 template <class T>
00059 class Function_ {
00060 public:
00061 class Constant;
00062 class Linear;
00063 class Polynomial;
00064 class Step;
00065 virtual ~Function_() {
00066 }
00073 virtual T calcValue(const Vector& x) const = 0;
00093 virtual T calcDerivative(const Array_<int>& derivComponents,
00094 const Vector& x) const = 0;
00095
00098 T calcDerivative(const std::vector<int>& derivComponents, const Vector& x) const
00099 { return calcDerivative(ArrayViewConst_<int>(derivComponents),x); }
00100
00104 virtual int getArgumentSize() const = 0;
00108 virtual int getMaxDerivativeOrder() const = 0;
00109 };
00110
00113 typedef Function_<Real> Function;
00114
00115
00116
00121 template <class T>
00122 class Function_<T>::Constant : public Function_<T> {
00123 public:
00131 explicit Constant(T value, int argumentSize=1)
00132 : argumentSize(argumentSize), value(value) {
00133 }
00134 T calcValue(const Vector& x) const {
00135 assert(x.size() == argumentSize);
00136 return value;
00137 }
00138 T calcDerivative(const Array_<int>& derivComponents, const Vector& x) const {
00139 return static_cast<T>(0);
00140 }
00141 virtual int getArgumentSize() const {
00142 return argumentSize;
00143 }
00144 int getMaxDerivativeOrder() const {
00145 return std::numeric_limits<int>::max();
00146 }
00147
00150 T calcDerivative(const std::vector<int>& derivComponents, const Vector& x) const
00151 { return calcDerivative(ArrayViewConst_<int>(derivComponents),x); }
00152
00153 private:
00154 const int argumentSize;
00155 const T value;
00156 };
00157
00162 template <class T>
00163 class Function_<T>::Linear : public Function_<T> {
00164 public:
00175 explicit Linear(const Vector_<T>& coefficients) : coefficients(coefficients) {
00176 }
00177 T calcValue(const Vector& x) const {
00178 assert(x.size() == coefficients.size()-1);
00179 T value = static_cast<T>(0);
00180 for (int i = 0; i < x.size(); ++i)
00181 value += x[i]*coefficients[i];
00182 value += coefficients[x.size()];
00183 return value;
00184 }
00185 T calcDerivative(const Array_<int>& derivComponents, const Vector& x) const {
00186 assert(x.size() == coefficients.size()-1);
00187 assert(derivComponents.size() > 0);
00188 if (derivComponents.size() == 1)
00189 return coefficients(derivComponents[0]);
00190 return static_cast<T>(0);
00191 }
00192 virtual int getArgumentSize() const {
00193 return coefficients.size()-1;
00194 }
00195 int getMaxDerivativeOrder() const {
00196 return std::numeric_limits<int>::max();
00197 }
00198
00201 T calcDerivative(const std::vector<int>& derivComponents, const Vector& x) const
00202 { return calcDerivative(ArrayViewConst_<int>(derivComponents),x); }
00203 private:
00204 const Vector_<T> coefficients;
00205 };
00206
00207
00212 template <class T>
00213 class Function_<T>::Polynomial : public Function_<T> {
00214 public:
00221 Polynomial(const Vector_<T>& coefficients) : coefficients(coefficients) {
00222 }
00223 T calcValue(const Vector& x) const {
00224 assert(x.size() == 1);
00225 Real arg = x[0];
00226 T value = static_cast<T>(0);
00227 for (int i = 0; i < coefficients.size(); ++i)
00228 value = value*arg + coefficients[i];
00229 return value;
00230 }
00231 T calcDerivative(const Array_<int>& derivComponents, const Vector& x) const {
00232 assert(x.size() == 1);
00233 assert(derivComponents.size() > 0);
00234 Real arg = x[0];
00235 T value = static_cast<T>(0);
00236 const int derivOrder = (int)derivComponents.size();
00237 const int polyOrder = coefficients.size()-1;
00238 for (int i = 0; i <= polyOrder-derivOrder; ++i) {
00239 T coeff = coefficients[i];
00240 for (int j = 0; j < derivOrder; ++j)
00241 coeff *= polyOrder-i-j;
00242 value = value*arg + coeff;
00243 }
00244 return value;
00245 }
00246 virtual int getArgumentSize() const {
00247 return 1;
00248 }
00249 int getMaxDerivativeOrder() const {
00250 return std::numeric_limits<int>::max();
00251 }
00252
00255 T calcDerivative(const std::vector<int>& derivComponents, const Vector& x) const
00256 { return calcDerivative(ArrayViewConst_<int>(derivComponents),x); }
00257 private:
00258 const Vector_<T> coefficients;
00259 };
00260
00268 template <class T>
00269 class Function_<T>::Step : public Function_<T> {
00270 public:
00288 Step(const T& y0, const T& y1, Real x0, Real x1)
00289 : m_y0(y0), m_y1(y1), m_yr(y1-y0), m_zero(Real(0)*y0),
00290 m_x0(x0), m_x1(x1), m_ooxr(1/(x1-x0)), m_sign(sign(m_ooxr))
00291 { SimTK_ERRCHK1_ALWAYS(x0 != x1, "Function_<T>::Step::ctor()",
00292 "A zero-length switching interval is illegal; both ends were %g.", x0);
00293 }
00294
00295 T calcValue(const Vector& xin) const {
00296 SimTK_ERRCHK1_ALWAYS(xin.size() == 1,
00297 "Function_<T>::Step::calcValue()",
00298 "Expected just one input argument but got %d.", xin.size());
00299
00300 const Real x = xin[0];
00301 if ((x-m_x0)*m_sign <= 0) return m_y0;
00302 if ((x-m_x1)*m_sign >= 0) return m_y1;
00303
00304 const Real f = stepAny(0,1,m_x0,m_ooxr, x);
00305 return m_y0 + f*m_yr;
00306 }
00307
00308 T calcDerivative(const Array_<int>& derivComponents, const Vector& xin) const {
00309 SimTK_ERRCHK1_ALWAYS(xin.size() == 1,
00310 "Function_<T>::Step::calcDerivative()",
00311 "Expected just one input argument but got %d.", xin.size());
00312
00313 const int derivOrder = (int)derivComponents.size();
00314 SimTK_ERRCHK1_ALWAYS(1 <= derivOrder && derivOrder <= 3,
00315 "Function_<T>::Step::calcDerivative()",
00316 "Only 1st, 2nd, and 3rd derivatives of the step are available,"
00317 " but derivative %d was requested.", derivOrder);
00318 const Real x = xin[0];
00319 if ((x-m_x0)*m_sign <= 0) return m_zero;
00320 if ((x-m_x1)*m_sign >= 0) return m_zero;
00321 switch(derivOrder) {
00322 case 1: return dstepAny (1,m_x0,m_ooxr, x) * m_yr;
00323 case 2: return d2stepAny(1,m_x0,m_ooxr, x) * m_yr;
00324 case 3: return d3stepAny(1,m_x0,m_ooxr, x) * m_yr;
00325 default: assert(!"impossible derivOrder");
00326 }
00327 return NaN*m_yr;
00328 }
00329
00330 virtual int getArgumentSize() const {return 1;}
00331 int getMaxDerivativeOrder() const {return 3;}
00332
00335 T calcDerivative(const std::vector<int>& derivComponents, const Vector& x) const
00336 { return calcDerivative(ArrayViewConst_<int>(derivComponents),x); }
00337 private:
00338 const T m_y0, m_y1, m_yr;
00339 const T m_zero;
00340 const Real m_x0, m_x1, m_ooxr;
00341 const Real m_sign;
00342 };
00343
00344 }
00345
00346 #endif // SimTK_SimTKCOMMON_FUNCTION_H_
00347
00348