Simbody
|
00001 #ifndef SimTK_SIMMATRIX_NEGATOR_H_ 00002 #define SimTK_SIMMATRIX_NEGATOR_H_ 00003 00004 /* -------------------------------------------------------------------------- * 00005 * SimTK Core: SimTK Simmatrix(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) 2005-7 Stanford University and the Authors. * 00013 * Authors: Michael Sherman * 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 00065 #include <iostream> 00066 00067 namespace SimTK { 00068 00069 // Specializations of this class provide information about Composite Numerical Types 00070 // (i.e. composite types) in the style of std::numeric_limits<T>. 00071 template <class T> class CNT; 00072 template <class N> class NTraits; // Same, but only defined for numeric types. 00073 template <class N> class negator; // negator is only defined for numbers. 00074 00075 00082 template <class NUMBER> 00083 class SimTK_SimTKCOMMON_EXPORT negator { 00084 typedef NUMBER N; 00085 typedef typename NTraits<N>::TReal NReal; 00086 typedef typename NTraits<N>::TImag NImag; 00087 typedef typename NTraits<N>::TComplex NComplex; 00088 typedef typename NTraits<N>::THerm NHerm; 00089 typedef typename NTraits<N>::TInvert NInvert; 00090 public: 00091 typedef negator<N> T; 00092 typedef NUMBER TNeg; // negator evaporates 00093 typedef NUMBER TWithoutNegator; // " 00094 typedef typename CNT<NReal>::TNeg TReal; 00095 typedef typename CNT<NImag>::TNeg TImag; 00096 typedef typename CNT<NComplex>::TNeg TComplex; 00097 typedef typename CNT<NHerm>::TNeg THerm; 00098 typedef negator<N> TPosTrans; 00099 typedef typename NTraits<N>::TSqHermT TSqHermT; 00100 typedef typename NTraits<N>::TSqTHerm TSqTHerm; 00101 typedef negator<N> TElement; 00102 typedef negator<N> TRow; 00103 typedef negator<N> TCol; 00104 00105 typedef typename NTraits<N>::TSqrt TSqrt; 00106 typedef typename NTraits<N>::TAbs TAbs; 00107 typedef typename NTraits<N>::TStandard TStandard; 00108 typedef typename CNT<NInvert>::TNeg TInvert; 00109 typedef typename NTraits<N>::TStandard TNormalize; // neg<conj> -> complex 00110 00111 00112 typedef negator<N> Scalar; 00113 typedef negator<N> ULessScalar; 00114 typedef NUMBER Number; 00115 typedef typename NTraits<N>::StdNumber StdNumber; 00116 typedef typename NTraits<N>::Precision Precision; 00117 typedef typename NTraits<N>::ScalarNormSq ScalarNormSq; 00118 00119 // negator may be used in combination with any composite numerical type, not just 00120 // numbers. Hence we must use CNT<P> here rather than NTraits<P> (they are 00121 // the same when P turns out to be a numeric type). 00122 // Typeof( Neg<N>*P ) is Typeof(P*N)::TNeg 00123 // Typeof( Neg<N>/P ) is Typeof(N/P)::TNeg 00124 // Typeof( Neg<N>+P ) is Typeof(P-N) 00125 // Typeof( Neg<N>-P ) is Typeof(P+N)::TNeg 00126 // No need to specialize because we strip off the "negator" here. 00127 template <class P> struct Result { 00128 private: 00129 // These are the type of the calculations we actually perform. 00130 typedef typename CNT<P>::template Result<N>::Mul PMul; 00131 typedef typename NTraits<N>::template Result<P>::Dvd PDvd; 00132 typedef typename CNT<P>::template Result<N>::Sub PAdd; 00133 typedef typename CNT<P>::template Result<N>::Add PSub; 00134 public: 00135 // These are the types to which we must recast the results. 00136 typedef typename CNT<PMul>::TNeg Mul; 00137 typedef typename CNT<PDvd>::TNeg Dvd; 00138 typedef PAdd Add; 00139 typedef typename CNT<PSub>::TNeg Sub; 00140 }; 00141 00142 // Shape-preserving element substitution (easy for scalars!) 00143 template <class P> struct Substitute { 00144 typedef P Type; 00145 }; 00146 00147 enum { 00148 NRows = 1, // Negators are always scalars 00149 NCols = 1, 00150 RowSpacing = 1, 00151 ColSpacing = 1, 00152 NPackedElements = 1, 00153 NActualElements = 1, 00154 NActualScalars = 1, 00155 ImagOffset = NTraits<N>::ImagOffset, 00156 RealStrideFactor = NTraits<N>::RealStrideFactor, 00157 ArgDepth = SCALAR_DEPTH, 00158 IsScalar = 1, 00159 IsULessScalar = 1, 00160 IsNumber = 0, 00161 IsStdNumber = 0, 00162 IsPrecision = 0, 00163 SignInterpretation = -1 // if you cast away the negator, don't forget this! 00164 }; 00165 const negator<N>* getData() const {return this;} 00166 negator<N>* updData() {return this;} 00167 00168 const TReal& real() const {return reinterpret_cast<const TReal&>(NTraits<N>::real(v));} 00169 TReal& real() {return reinterpret_cast< TReal&>(NTraits<N>::real(v));} 00170 const TImag& imag() const {return reinterpret_cast<const TImag&>(NTraits<N>::imag(v));} 00171 TImag& imag() {return reinterpret_cast< TImag&>(NTraits<N>::imag(v));} 00172 00173 ScalarNormSq scalarNormSqr() const {return NTraits<N>::scalarNormSqr(v);} 00174 TSqrt sqrt() const {return NTraits<N>::sqrt(N(v));} 00175 TAbs abs() const {return NTraits<N>::abs(v);} 00176 TStandard standardize() const {return -NTraits<N>::standardize(v);} 00177 TNormalize normalize() const {return -NTraits<N>::normalize(v);} 00178 00179 // Inverse (1/x) of a non-negated type N will return a non-negated type, so we 00180 // can cast it to a negated type here to save a flop. The return type might 00181 // not be N (a negated conjugate comes back as a complex), so there may be 00182 // a flop done in the final conversion to TInvert. 00183 TInvert invert() const {return recast(NTraits<N>::invert(v));} 00184 00185 static negator<N> getNaN() {return recast(NTraits<N>::getNaN());} 00186 static negator<N> getInfinity() {return recast(NTraits<N>::getInfinity());} 00187 00189 inline bool isFinite() const; 00191 inline bool isNaN() const; 00194 inline bool isInf() const; 00195 00196 static double getDefaultTolerance() {return NTraits<N>::getDefaultTolerance();} 00197 00200 template <class T2> bool isNumericallyEqual(const T2& t2) const 00201 { return CNT<T2>::isNumericallyEqual(t2, -v); } // perform negation 00202 00206 template <class N2> bool isNumericallyEqual(const negator<N2>& t2) const 00207 { return SimTK::isNumericallyEqual(v, t2.v); } 00208 00210 template <class T2> bool isNumericallyEqual(const T2& t2, double tol) const 00211 { return CNT<T2>::isNumericallyEqual(t2, -v, tol); } // perform negation 00212 00215 template <class N2> bool isNumericallyEqual(const negator<N2>& t2, double tol) const 00216 { return SimTK::isNumericallyEqual(v, t2.v, tol); } 00217 00218 00219 negator() { 00220 #ifndef NDEBUG 00221 v = NTraits<N>::getNaN(); 00222 #endif 00223 } 00224 negator(const negator& n) : v(n.v) { } 00225 negator& operator=(const negator& n) { v=n.v; return *this; } 00226 00227 // These are implicit conversions from numeric type NN to negator<N>. The 00228 // value must be unchanged, so we must negate. Note that NN==N is a 00229 // certainty for one of these cases. 00230 negator(int t) {v = -N((typename NTraits<N>::Precision)t);} 00231 negator(const float& t) {v = -N((typename NTraits<N>::Precision)t);} 00232 negator(const double& t) {v = -N((typename NTraits<N>::Precision)t);} 00233 negator(const long double& t) {v = -N((typename NTraits<N>::Precision)t);} 00234 00235 // Some of these may not compile if instantiated -- you can't cast a complex 00236 // to a float, for example. 00237 template <class P> negator(const std::complex<P>& t) {v = -N(t);} 00238 template <class P> negator(const conjugate<P>& t) {v = -N(t);} 00239 00240 // This can be used to negate a value of type N at zero cost. It is typically 00241 // used for recasting temporary expressions to apply a final negation. Note that 00242 // this is *not* the same as constructing a negator<N> from an N, which actually 00243 // peforms a floating point negation. 00244 static const negator<N>& recast(const N& val) 00245 { return reinterpret_cast<const negator<N>&>(val); } 00246 00247 const N& operator-() const { return v; } 00248 N& operator-() { return v; } // an lvalue! 00249 N operator+() const { return N(-v); } // performs the actual negation (expensive) 00250 00251 operator N() const { return N(-v); } // implicit conversion to N (expensive) 00252 00253 template <class P> negator& operator =(const P& t) { v = -t; return *this; } 00254 template <class P> negator& operator+=(const P& t) { v -= t; return *this; } //swap sign 00255 template <class P> negator& operator-=(const P& t) { v += t; return *this; } 00256 template <class P> negator& operator*=(const P& t) { v *= t; return *this; } //don't swap! 00257 template <class P> negator& operator/=(const P& t) { v /= t; return *this; } 00258 00259 // If we know we've got a negator as an argument, get rid of its negation 00260 // and change signs as necessary. We're guaranteed to get rid of at least 00261 // one negator<> this way. Nothing to gain for multiplication or division, 00262 // though. 00263 template <class NN> negator& operator =(const negator<NN>& t) 00264 { v = -t; return *this; } 00265 template <class NN> negator& operator+=(const negator<NN>& t) 00266 { v += -t; return *this; } //swap sign 00267 template <class NN> negator& operator-=(const negator<NN>& t) 00268 { v -= -t; return *this; } 00269 00270 private: 00271 N v; 00272 00273 template <class N2> friend class negator; 00274 }; 00275 00276 // isNaN() for real, complex, and conjugate numbers is provided in 00277 // NTraits. Here we add isNaN() for negated scalar types. 00278 00280 00281 inline bool isNaN(const negator<float>& x) {return isNaN(-x);} 00282 inline bool isNaN(const negator<double>& x) {return isNaN(-x);} 00283 inline bool isNaN(const negator<long double>& x) {return isNaN(-x);} 00284 template <class P> inline bool 00285 isNaN(const negator< std::complex<P> >& x) {return isNaN(-x);} 00286 template <class P> inline bool 00287 isNaN(const negator< conjugate<P> >& x) {return isNaN(-x);} 00289 00290 // isFinite() for real, complex, and conjugate numbers is provided in 00291 // NTraits. Here we add isFinite() for negated scalar types. 00292 00294 00295 inline bool isFinite(const negator<float>& x) {return isFinite(-x);} 00296 inline bool isFinite(const negator<double>& x) {return isFinite(-x);} 00297 inline bool isFinite(const negator<long double>& x) {return isFinite(-x);} 00298 template <class P> inline bool 00299 isFinite(const negator< std::complex<P> >& x) {return isFinite(-x);} 00300 template <class P> inline bool 00301 isFinite(const negator< conjugate<P> >& x) {return isFinite(-x);} 00303 00304 // isInf(x) for real, complex, and conjugate numbers is provided in 00305 // NTraits. Here we add isInf() for negated scalar types. 00306 00308 00309 inline bool isInf(const negator<float>& x) {return isInf(-x);} 00310 inline bool isInf(const negator<double>& x) {return isInf(-x);} 00311 inline bool isInf(const negator<long double>& x) {return isInf(-x);} 00312 template <class P> inline bool 00313 isInf(const negator< std::complex<P> >& x) {return isInf(-x);} 00314 template <class P> inline bool 00315 isInf(const negator< conjugate<P> >& x) {return isInf(-x);} 00317 00318 // The member functions call the global ones just defined. 00319 template <class N> inline bool 00320 negator<N>::isFinite() const {return SimTK::isFinite(*this);} 00321 template <class N> inline bool 00322 negator<N>::isNaN() const {return SimTK::isNaN(*this);} 00323 template <class N> inline bool 00324 negator<N>::isInf() const {return SimTK::isInf(*this);} 00325 00326 // Handle all binary numerical operators involving a negator<A> and a B, or negator<A> 00327 // and negator<B>, obtaining results by stripping away the negator<>s and fiddling 00328 // with signs appropriately. 00329 // Careful: don't remove both negators in one step because Result isn't specialized 00330 // for negators so it might not predict the same result type as you actually get. 00331 // Be patient and let it strip one negator at a time -- in Release mode that won't 00332 // add any code since all this stuff drops away. 00333 // 00334 // To appreciate the beauty of these operators, remember that -x is free when x 00335 // is a negator. 00336 00337 template <class DEST, class SRC> static inline const DEST& 00338 negRecast(const SRC& s) { return reinterpret_cast<const DEST&>(s); } 00339 00340 // Binary '+' with a negator as one or both arguments // 00341 template <class A, class B> inline typename negator<A>::template Result<B>::Add 00342 operator+(const negator<A>& l, const B& r) 00343 {return negRecast<typename negator<A>::template Result<B>::Add>(r-(-l));} 00344 template <class A, class B> inline typename CNT<A>::template Result<negator<B> >::Add 00345 operator+(const A& l, const negator<B>& r) 00346 {return negRecast<typename CNT<A>::template Result<negator<B> >::Add>(l-(-r));} 00347 // One step at a time here (see above). 00348 template <class A, class B> inline typename negator<A>::template Result<negator<B> >::Add 00349 operator+(const negator<A>& l, const negator<B>& r) 00350 {return negRecast<typename negator<A>::template Result<negator<B> >::Add>(r-(-l)); } 00351 00352 // Binary '-' with a negator as one or both arguments // 00353 template <class A, class B> inline typename negator<A>::template Result<B>::Sub 00354 operator-(const negator<A>& l, const B& r) 00355 {return negRecast<typename negator<A>::template Result<B>::Sub>(r+(-l));} 00356 template <class A, class B> inline typename CNT<A>::template Result<negator<B> >::Sub 00357 operator-(const A& l, const negator<B>& r) 00358 {return negRecast<typename CNT<A>::template Result<negator<B> >::Sub>(l+(-r));} 00359 // One step at a time here (see above). 00360 template <class A, class B> inline typename negator<A>::template Result<negator<B> >::Sub 00361 operator-(const negator<A>& l, const negator<B>& r) 00362 {return negRecast<typename negator<A>::template Result<negator<B> >::Sub>(r+(-l));} 00363 00364 // Binary '*' with a negator as one or both arguments 00365 template <class A, class B> inline typename negator<A>::template Result<B>::Mul 00366 operator*(const negator<A>& l, const B& r) 00367 {return negRecast<typename negator<A>::template Result<B>::Mul>((-l)*r);} 00368 template <class A, class B> inline typename CNT<A>::template Result<negator<B> >::Mul 00369 operator*(const A& l, const negator<B>& r) 00370 {return negRecast<typename CNT<A>::template Result<negator<B> >::Mul>(l*(-r));} 00371 // One step at a time here (see above). 00372 template <class A, class B> inline typename negator<A>::template Result<negator<B> >::Mul 00373 operator*(const negator<A>& l, const negator<B>& r) 00374 {return negRecast<typename negator<A>::template Result<negator<B> >::Mul>((-l)*r);} 00375 00376 // Binary '/' with a negator as one or both arguments 00377 template <class A, class B> inline typename negator<A>::template Result<B>::Dvd 00378 operator/(const negator<A>& l, const B& r) 00379 {return negRecast<typename negator<A>::template Result<B>::Dvd>((-l)/r);} 00380 template <class A, class B> inline typename CNT<A>::template Result<negator<B> >::Dvd 00381 operator/(const A& l, const negator<B>& r) 00382 {return negRecast<typename CNT<A>::template Result<negator<B> >::Dvd>(l/(-r));} 00383 // One step at a time here (see above). 00384 template <class A, class B> inline typename negator<A>::template Result<negator<B> >::Dvd 00385 operator/(const negator<A>& l, const negator<B>& r) 00386 {return negRecast<typename negator<A>::template Result<negator<B> >::Dvd>((-l)/r);} 00387 00388 // Binary '==' with a negator as one or both arguments 00389 template <class A, class B> inline bool 00390 operator==(const negator<A>& l, const B& r) { return (A)l == r; } 00391 template <class A, class B> inline bool 00392 operator==(const A& l, const negator<B>& r) { return l == (B)r; } 00393 template <class A, class B> inline bool 00394 operator==(const negator<A>& l, const negator<B>& r) { return (-l) == (-r); } // cheap! 00395 00396 // The lazy man's '!=' operator. 00397 template <class A, class B> inline bool 00398 operator!=(const negator<A>& l, const B& r) { return !(l==r); } 00399 template <class A, class B> inline bool 00400 operator!=(const A& l, const negator<B>& r) { return !(l==r); } 00401 template <class A, class B> inline bool 00402 operator!=(const negator<A>& l, const negator<B>& r) { return !(l==r); } 00403 00404 // And a final touch of elegance allowing smooth interoperability with iostream. 00405 template <class NUM, class CHAR, class TRAITS> inline std::basic_istream<CHAR,TRAITS>& 00406 operator>>(std::basic_istream<CHAR,TRAITS>& is, negator<NUM>& nn) { 00407 NUM z; is >> z; nn=z; 00408 return is; 00409 } 00410 template <class NUM, class CHAR, class TRAITS> inline std::basic_ostream<CHAR,TRAITS>& 00411 operator<<(std::basic_ostream<CHAR,TRAITS>& os, const negator<NUM>& nn) { 00412 return os << NUM(nn); 00413 } 00414 00415 } // namespace SimTK 00416 00417 #endif //SimTK_SIMMATRIX_NEGATOR_H_