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