Simbody

negator.h

Go to the documentation of this file.
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_
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines