Simbody
3.4 (development)
|
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_