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 public:
00090     typedef negator<N>                                          T;
00091     typedef NUMBER                                              TNeg;   // negator evaporates
00092     typedef NUMBER                                              TWithoutNegator; // "
00093     typedef typename CNT<NReal>::TNeg                           TReal;
00094     typedef typename CNT<NImag>::TNeg                           TImag;
00095     typedef typename CNT<NComplex>::TNeg                        TComplex;
00096     typedef typename CNT<NHerm>::TNeg                           THerm;
00097     typedef negator<N>                                          TPosTrans;
00098     typedef typename NTraits<N>::TSqHermT                       TSqHermT;
00099     typedef typename NTraits<N>::TSqTHerm                       TSqTHerm;
00100     typedef negator<N>                                          TElement;
00101     typedef negator<N>                                          TRow;
00102     typedef negator<N>                                          TCol;
00103 
00104     typedef typename NTraits<N>::TAbs                           TAbs;
00105     typedef typename NTraits<N>::TStandard                      TStandard;
00106     typedef typename NTraits<N>::TInvert                        TInvert;
00107     typedef typename NTraits<N>::TStandard                      TNormalize; // neg<conj> -> complex
00108 
00109 
00110     typedef negator<N>                                          Scalar;
00111     typedef NUMBER                                              Number;
00112     typedef typename NTraits<N>::StdNumber                      StdNumber;
00113     typedef typename NTraits<N>::Precision                      Precision;
00114     typedef typename NTraits<N>::ScalarSq                       ScalarSq;
00115 
00116     // negator may be used in combination with any composite numerical type, not just
00117     // numbers. Hence we must use CNT<P> here rather than NTraits<P> (they are 
00118     // the same when P turns out to be a numeric type).
00119     //      Typeof( Neg<N>*P ) is Typeof(P*N)::TNeg
00120     //      Typeof( Neg<N>/P ) is Typeof(N/P)::TNeg
00121     //      Typeof( Neg<N>+P ) is Typeof(P-N)
00122     //      Typeof( Neg<N>-P ) is Typeof(P+N)::TNeg
00123     // No need to specialize because we strip off the "negator" here.
00124     template <class P> struct Result {
00125     private:
00126         // These are the type of the calculations we actually perform.
00127         typedef typename CNT<P>::template Result<N>::Mul     PMul;
00128         typedef typename NTraits<N>::template Result<P>::Dvd PDvd;
00129         typedef typename CNT<P>::template Result<N>::Sub     PAdd;
00130         typedef typename CNT<P>::template Result<N>::Add     PSub;
00131     public:
00132         // These are the types to which we must recast the results.
00133         typedef typename CNT<PMul>::TNeg    Mul;
00134         typedef typename CNT<PDvd>::TNeg    Dvd;
00135         typedef PAdd                        Add;
00136         typedef typename CNT<PSub>::TNeg    Sub;
00137     };
00138 
00139     // Shape-preserving element substitution (easy for scalars!)
00140     template <class P> struct Substitute {
00141         typedef P Type;
00142     };
00143 
00144     enum {
00145         NRows               = 1, // Negators are always scalars
00146         NCols               = 1,
00147         RowSpacing          = 1,
00148         ColSpacing          = 1,
00149         NPackedElements     = 1,
00150         NActualElements     = 1,
00151         NActualScalars      = 1,
00152         ImagOffset          = NTraits<N>::ImagOffset,
00153         RealStrideFactor    = NTraits<N>::RealStrideFactor,
00154         ArgDepth            = SCALAR_DEPTH,
00155         IsScalar            = 1,
00156         IsNumber            = 0,
00157         IsStdNumber         = 0,
00158         IsPrecision         = 0,
00159         SignInterpretation  = -1 // if you cast away the negator, don't forget this!
00160     };
00161     static negator<N> getNaN()      {return recast(NTraits<N>::getNaN());}
00162     static negator<N> getInfinity() {return recast(NTraits<N>::getInfinity());}
00163 
00164     const negator<N>* getData() const {return this;}
00165     negator<N>*       updData()       {return this;}
00166 
00167     const TReal& real() const {return reinterpret_cast<const TReal&>(NTraits<N>::real(v));}
00168     TReal&       real()       {return reinterpret_cast<      TReal&>(NTraits<N>::real(v));}
00169     const TImag& imag() const {return reinterpret_cast<const TImag&>(NTraits<N>::imag(v));}
00170     TImag&       imag()       {return reinterpret_cast<      TImag&>(NTraits<N>::imag(v));}
00171 
00172     ScalarSq   scalarNormSqr() const {return NTraits<N>::scalarNormSqr(v);}
00173     TAbs       abs()           const {return NTraits<N>::abs(v);}
00174     TStandard  standardize()   const {return -NTraits<N>::standardize(v);}
00175     TNormalize normalize()     const {return -NTraits<N>::normalize(v);}
00176     TInvert    invert()        const {return -NTraits<N>::invert(v);}
00177 
00178     negator() {
00179     #ifndef NDEBUG
00180         v = NTraits<N>::getNaN();
00181     #endif
00182     }
00183     negator(const negator& n) : v(n.v) { }
00184     negator& operator=(const negator& n) { v=n.v; return *this; }
00185 
00186     // These are explicit conversion from numeric type NN to negator<N>. The value must
00187     // be unchanged, so we must negate. Note that NN==N is a certainty for one of these cases.
00188 
00189     explicit negator(int t) {v = -N((typename NTraits<N>::Precision)t);}
00190     explicit negator(const float& t) {v = -N(t);}
00191     explicit negator(const double& t) {v = -N(t);}
00192     explicit negator(const long double& t) {v = -N(t);}
00193     explicit negator(const std::complex<float>& t) {v = -N(t);}
00194     explicit negator(const std::complex<double>& t) {v = -N(t);}
00195     explicit negator(const std::complex<long double>& t) {v = -N(t);}
00196     explicit negator(const conjugate<float>& t) {v = -N(t);}
00197     explicit negator(const conjugate<double>& t) {v = -N(t);}
00198     explicit negator(const conjugate<long double>& t) {v = -N(t);}
00199 
00200     // This can be used to negate a value of type N at zero cost. It is typically
00201     // used for recasting temporary expressions to apply a final negation. Note that
00202     // this is *not* the same as constructing a negator<N> from an N, which actually
00203     // peforms a floating point negation.
00204     static const negator<N>& recast(const N& val)
00205         { return reinterpret_cast<const negator<N>&>(val); }
00206 
00207     const N& operator-() const { return v;  }
00208     N&       operator-()       { return v;  } // an lvalue!
00209     N        operator+() const { return N(-v); } // performs the actual negation (expensive)
00210 
00211     operator N() const { return N(-v); } // implicit conversion to N (expensive)
00212 
00213     template <class P> negator& operator =(const P& t) { v = -t; return *this; }
00214     template <class P> negator& operator+=(const P& t) { v -= t; return *this; } //swap sign
00215     template <class P> negator& operator-=(const P& t) { v += t; return *this; }
00216     template <class P> negator& operator*=(const P& t) { v *= t; return *this; } //don't swap!
00217     template <class P> negator& operator/=(const P& t) { v /= t; return *this; }
00218 
00219     // If we know we've got a negator as an argument, get rid of its negation and change
00220     // signs as necessary. We're guaranteed to get rid of at least one negator<> this way.
00221     // Nothing to gain for multiplication or division, though.
00222     template <class NN> negator& operator =(const negator<NN>& t) { v =  -t; return *this; }
00223     template <class NN> negator& operator+=(const negator<NN>& t) { v += -t; return *this; } //swap sign
00224     template <class NN> negator& operator-=(const negator<NN>& t) { v -= -t; return *this; }
00225 
00226 private:
00227     N v;
00228 };
00229 
00230 
00231 // Handle all binary numerical operators involving a negator<A> and a B, or negator<A>
00232 // and negator<B>, obtaining results by stripping away the negator<>s and fiddling
00233 // with signs appropriately.
00234 // To appreciate the beauty of these operators, remember that -x is free when x
00235 // is a negator.
00236 
00237 template <class DEST, class SRC> static inline const DEST&
00238 negRecast(const SRC& s) { return reinterpret_cast<const DEST&>(s); }
00239 
00240 // Binary '+' with a negator as one or both arguments
00241 template <class A, class B> inline typename negator<A>::template Result<B>::Add
00242 operator+(const negator<A>& l, const B& r)
00243   {return negRecast<typename negator<A>::template Result<B>::Add>(r-(-l));}
00244 template <class A, class B> inline typename CNT<A>::template Result<negator<B> >::Add
00245 operator+(const A& l, const negator<B>& r)
00246   {return negRecast<typename CNT<A>::template Result<negator<B> >::Add>(l-(-r));}
00247 template <class A, class B> inline typename negator<A>::template Result<negator<B> >::Add
00248 operator+(const negator<A>& l, const negator<B>& r) 
00249   {return negRecast<typename negator<A>::template Result<negator<B> >::Add>((-l)+(-r)); }
00250 
00251 // Binary '-' with a negator as one or both arguments
00252 template <class A, class B> inline typename negator<A>::template Result<B>::Sub
00253 operator-(const negator<A>& l, const B& r)
00254   {return negRecast<typename negator<A>::template Result<B>::Sub>((-l)+r);}
00255 template <class A, class B> inline typename CNT<A>::template Result<negator<B> >::Sub
00256 operator-(const A& l, const negator<B>& r)
00257   {return negRecast<typename CNT<A>::template Result<negator<B> >::Sub>(l+(-r));}
00258 template <class A, class B> inline typename negator<A>::template Result<negator<B> >::Sub
00259 operator-(const negator<A>& l, const negator<B>& r) 
00260   {return negRecast<typename negator<A>::template Result<negator<B> >::Sub>((-r)-(-l));}
00261 
00262 // Binary '*' with a negator as one or both arguments
00263 template <class A, class B> inline typename negator<A>::template Result<B>::Mul
00264 operator*(const negator<A>& l, const B& r) 
00265   {return negRecast<typename negator<A>::template Result<B>::Mul>((-l)*r);}
00266 template <class A, class B> inline typename CNT<A>::template Result<negator<B> >::Mul
00267 operator*(const A& l, const negator<B>& r)
00268   {return negRecast<typename CNT<A>::template Result<negator<B> >::Mul>(l*(-r));}
00269 template <class A, class B> inline typename negator<A>::template Result<negator<B> >::Mul
00270 operator*(const negator<A>& l, const negator<B>& r)
00271   {return negRecast<typename negator<A>::template Result<negator<B> >::Mul>((-l)*(-r));}
00272 
00273 // Binary '/' with a negator as one or both arguments
00274 template <class A, class B> inline typename negator<A>::template Result<B>::Dvd
00275 operator/(const negator<A>& l, const B& r) 
00276   {return negRecast<typename negator<A>::template Result<B>::Dvd>((-l)/r);}
00277 template <class A, class B> inline typename CNT<A>::template Result<negator<B> >::Dvd
00278 operator/(const A& l, const negator<B>& r)
00279   {return negRecast<typename CNT<A>::template Result<negator<B> >::Dvd>(l/(-r));}
00280 template <class A, class B> inline typename negator<A>::template Result<negator<B> >::Dvd
00281 operator/(const negator<A>& l, const negator<B>& r)
00282   {return negRecast<typename negator<A>::template Result<negator<B> >::Dvd>((-l)/(-r));}
00283 
00284 // Binary '==' with a negator as one or both arguments
00285 template <class A, class B> inline bool
00286 operator==(const negator<A>& l, const B& r) { return (A)l == r; }
00287 template <class A, class B> inline bool
00288 operator==(const A& l, const negator<B>& r) { return l == (B)r; }
00289 template <class A, class B> inline bool
00290 operator==(const negator<A>& l, const negator<B>& r) { return (-l) == (-r); }   // cheap!
00291 
00292 // The lazy man's '!=' operator.
00293 template <class A, class B> inline bool
00294 operator!=(const negator<A>& l, const B& r) { return !(l==r); }
00295 template <class A, class B> inline bool
00296 operator!=(const A& l, const negator<B>& r) { return !(l==r); }
00297 template <class A, class B> inline bool
00298 operator!=(const negator<A>& l, const negator<B>& r) { return !(l==r); }
00299 
00300 // And a final touch of elegance allowing smooth interoperability with iostream.
00301 template <class NUM, class CHAR, class TRAITS> inline std::basic_istream<CHAR,TRAITS>&
00302 operator>>(std::basic_istream<CHAR,TRAITS>& is, negator<NUM>& nn) {
00303     NUM z; is >> z; nn=z;
00304     return is;
00305 }
00306 template <class NUM, class CHAR, class TRAITS> inline std::basic_ostream<CHAR,TRAITS>&
00307 operator<<(std::basic_ostream<CHAR,TRAITS>& os, const negator<NUM>& nn) {
00308     return os << NUM(nn);
00309 }
00310 
00311 } // namespace SimTK
00312 
00313 #endif //SimTK_SIMMATRIX_NEGATOR_H_

Generated on Thu Feb 28 01:34:30 2008 for SimTKcommon by  doxygen 1.4.7