Simbody  3.6
NTraits.h
Go to the documentation of this file.
1 #ifndef SimTK_SIMMATRIX_NTRAITS_H_
2 #define SimTK_SIMMATRIX_NTRAITS_H_
3 
4 /* -------------------------------------------------------------------------- *
5  * Simbody(tm): SimTKcommon *
6  * -------------------------------------------------------------------------- *
7  * This is part of the SimTK biosimulation toolkit originating from *
8  * Simbios, the NIH National Center for Physics-Based Simulation of *
9  * Biological Structures at Stanford, funded under the NIH Roadmap for *
10  * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. *
11  * *
12  * Portions copyright (c) 2005-12 Stanford University and the Authors. *
13  * Authors: Michael Sherman *
14  * Contributors: *
15  * *
16  * Licensed under the Apache License, Version 2.0 (the "License"); you may *
17  * not use this file except in compliance with the License. You may obtain a *
18  * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. *
19  * *
20  * Unless required by applicable law or agreed to in writing, software *
21  * distributed under the License is distributed on an "AS IS" BASIS, *
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
23  * See the License for the specific language governing permissions and *
24  * limitations under the License. *
25  * -------------------------------------------------------------------------- */
26 
50 #include "SimTKcommon/Constants.h"
52 
53 #include <cstddef>
54 #include <cassert>
55 #include <complex>
56 #include <iostream>
57 #include <limits>
58 
59 using std::complex;
60 
61 namespace SimTK {
62 
63 // This is the 3rd type of number, conjugate. It is like complex except that
64 // the represented value is the conjugate of the value represented by a complex
65 // number containing the same bit pattern. That is, complex and conjugate both
66 // contain two real numbers, re and im, with complex(re,im) meaning
67 // (re + im*i) while conjugate(re,im) means (re - im*i). It is guaranteed that
68 // our conjugate type and complex type have identical sizes and representations.
69 // Together, these defininitions and guarantees permit conjugation
70 // to be done by reinterpretation rather than be computation.
71 template <class R> class conjugate; // Only defined for float, double
72 
73 // Specializations of this class provide information about Composite Numerical
74 // Types in the style of std::numeric_limits<T>. It is specialized for the
75 // numeric types but can be invoked on any composite numerical type as well.
76 template <class T> class CNT;
77 
78 // NTraits provides information like CNT, but for numeric types only.
79 template <class N> class NTraits; // allowed only for N=<number>
80 template <class R> class NTraits< complex<R> >;
81 template <class R> class NTraits< conjugate<R> >;
82 template <> class NTraits<float>;
83 template <> class NTraits<double>;
84 
85 // This is an adaptor for numeric types which negates the apparent values. A
86 // negator<N> has exactly the same internal representation as a numeric value N,
87 // but it is to be interpreted has having the negative of the value it would
88 // have if interpreted as an N. This permits negation to be done by
89 // reinterpretation rather than computation. A full set of arithmetic operators
90 // are provided involving negator<N>'s and N's. Sometimes we can save an op or
91 // two this way. For example negator<N>*negator<N> can be performed as an N*N
92 // since the negations cancel, and we saved two floating point negations.
93 template <class N> class negator; // Only defined for numbers
94 
102 template <class R1, class R2> struct Widest {/* Only defined for built-ins. */};
103 template <> struct Widest<float,float> {typedef float Type; typedef float Precision;};
104 template <> struct Widest<float,double> {typedef double Type; typedef double Precision;};
105 template <> struct Widest<double,float> {typedef double Type; typedef double Precision;};
106 template <> struct Widest<double,double> {typedef double Type; typedef double Precision;};
107 template <class R1, class R2> struct Widest< complex<R1>,complex<R2> > {
108  typedef complex< typename Widest<R1,R2>::Type > Type;
110 };
111 template <class R1, class R2> struct Widest< complex<R1>,R2 > {
112  typedef complex< typename Widest<R1,R2>::Type > Type;
114 };
115 template <class R1, class R2> struct Widest< R1,complex<R2> > {
116  typedef complex< typename Widest<R1,R2>::Type > Type;
118 };
119 
129 template <class R1, class R2> struct Narrowest {/* Only defined for built-ins. */};
130 template <> struct Narrowest<float,float> {typedef float Type; typedef float Precision;};
131 template <> struct Narrowest<float,double> {typedef float Type; typedef float Precision;};
132 template <> struct Narrowest<double,float> {typedef float Type; typedef float Precision;};
133 template <> struct Narrowest<double,double> {typedef double Type; typedef double Precision;};
134 template <class R1, class R2> struct Narrowest< complex<R1>,complex<R2> > {
135  typedef complex< typename Narrowest<R1,R2>::Type > Type;
137 };
138 template <class R1, class R2> struct Narrowest< complex<R1>,R2 > {
139  typedef complex< typename Narrowest<R1,R2>::Type > Type;
141 };
142 template <class R1, class R2> struct Narrowest< R1,complex<R2> > {
143  typedef complex< typename Narrowest<R1,R2>::Type > Type;
145 };
146 
148 template <class R> class RTraits {/* Only defined for real types */};
149 template <> class RTraits<float> {
150 public:
152  static const float& getEps() {static const float c=std::numeric_limits<float>::epsilon(); return c;}
154  static const float& getSignificant() {static const float c=std::pow(getEps(), 0.875f); return c;}
156  static double getDefaultTolerance() {return (double)getSignificant();}
157 };
158 template <> class RTraits<double> {
159 public:
160  static const double& getEps() {static const double c=std::numeric_limits<double>::epsilon(); return c;}
161  static const double& getSignificant() {static const double c=std::pow(getEps(), 0.875); return c;}
162  static double getDefaultTolerance() {return getSignificant();}
163 };
164 
181 // See negator.h for isNaN() applied to negated scalars.
183 inline bool isNaN(const float& x) {return std::isnan(x);}
184 inline bool isNaN(const double& x) {return std::isnan(x);}
185 
186 template <class P> inline bool
187 isNaN(const std::complex<P>& x)
188 { return isNaN(x.real()) || isNaN(x.imag());}
189 
190 template <class P> inline bool
192 { return isNaN(x.real()) || isNaN(x.negImag());}
194 
207 // See negator.h for isFinite() applied to negated scalars.
209 inline bool isFinite(const float& x) {return std::isfinite(x);}
210 inline bool isFinite(const double& x) {return std::isfinite(x);}
211 
212 template <class P> inline bool
213 isFinite(const std::complex<P>& x)
214 { return isFinite(x.real()) && isFinite(x.imag());}
215 
216 template <class P> inline bool
218 { return isFinite(x.real()) && isFinite(x.negImag());}
220 
235 // See negator.h for isInf() applied to negated scalars.
237 inline bool isInf(const float& x) {return std::isinf(x);}
238 inline bool isInf(const double& x) {return std::isinf(x);}
239 
240 template <class P> inline bool
241 isInf(const std::complex<P>& x) {
242  return (isInf(x.real()) && !isNaN(x.imag()))
243  || (isInf(x.imag()) && !isNaN(x.real()));
244 }
245 
246 template <class P> inline bool
247 isInf(const conjugate<P>& x) {
248  return (isInf(x.real()) && !isNaN(x.negImag()))
249  || (isInf(x.negImag()) && !isNaN(x.real()));
250 }
252 
292 inline bool isNumericallyEqual(const float& a, const float& b,
295 { if (isNaN(a)) return isNaN(b); else if (isNaN(b)) return false;
296  const float scale = std::max(std::max(std::abs(a),std::abs(b)), 1.f);
297  return std::abs(a-b) <= scale*(float)tol; }
299 inline bool isNumericallyEqual(const double& a, const double& b,
301 { if (isNaN(a)) return isNaN(b); else if (isNaN(b)) return false;
302  const double scale = std::max(std::max(std::abs(a),std::abs(b)), 1.);
303  return std::abs(a-b) <= scale*tol; }
304 
306 inline bool isNumericallyEqual(const float& a, const double& b,
308 { return isNumericallyEqual((double)a, b, tol); }
310 inline bool isNumericallyEqual(const double& a, const float& b,
312 { return isNumericallyEqual(a, (double)b, tol); }
313 
315 inline bool isNumericallyEqual(const float& a, int b,
317 { return isNumericallyEqual(a, (double)b, tol); }
319 inline bool isNumericallyEqual(int a, const float& b,
321 { return isNumericallyEqual((double)a, b, tol); }
323 inline bool isNumericallyEqual(const double& a, int b,
325 { return isNumericallyEqual(a, (double)b, tol); }
327 inline bool isNumericallyEqual(int a, const double& b,
329 { return isNumericallyEqual((double)a, b, tol); }
330 
334 template <class P, class Q>
335 inline bool isNumericallyEqual
336  ( const std::complex<P>& a, const std::complex<Q>& b,
337  double tol = RTraits<typename Narrowest<P,Q>::Precision>::getDefaultTolerance())
338 { return isNumericallyEqual(a.real(),b.real(),tol)
339  && isNumericallyEqual(a.imag(),b.imag(),tol); }
340 
344 template <class P, class Q>
345 inline bool isNumericallyEqual
346  ( const conjugate<P>& a, const conjugate<Q>& b,
347  double tol = RTraits<typename Narrowest<P,Q>::Precision>::getDefaultTolerance())
348 { return isNumericallyEqual(a.real(),b.real(),tol)
349  && isNumericallyEqual(a.imag(),b.imag(),tol); }
350 
354 template <class P, class Q>
355 inline bool isNumericallyEqual
356  ( const std::complex<P>& a, const conjugate<Q>& b,
357  double tol = RTraits<typename Narrowest<P,Q>::Precision>::getDefaultTolerance())
358 { return isNumericallyEqual(a.real(),b.real(),tol)
359  && isNumericallyEqual(a.imag(),b.imag(),tol); }
360 
364 template <class P, class Q>
365 inline bool isNumericallyEqual
366  ( const conjugate<P>& a, const std::complex<Q>& b,
367  double tol = RTraits<typename Narrowest<P,Q>::Precision>::getDefaultTolerance())
368 { return isNumericallyEqual(a.real(),b.real(),tol)
369  && isNumericallyEqual(a.imag(),b.imag(),tol); }
370 
372 template <class P> inline bool
373 isNumericallyEqual(const std::complex<P>& a, const float& b,
375 { return isNumericallyEqual(a.real(),b,tol) && isNumericallyEqual(a.imag(),0.f,tol); }
377 template <class P> inline bool
378 isNumericallyEqual(const float& a, const std::complex<P>& b,
380 { return isNumericallyEqual(b,a,tol); }
382 template <class P> inline bool
383 isNumericallyEqual(const std::complex<P>& a, const double& b,
384  double tol = RTraits<typename Narrowest<P,double>::Precision>::getDefaultTolerance())
385 { return isNumericallyEqual(a.real(),b,tol) && isNumericallyEqual(a.imag(),0.,tol); }
387 template <class P> inline bool
388 isNumericallyEqual(const double& a, const std::complex<P>& b,
389  double tol = RTraits<typename Narrowest<P,double>::Precision>::getDefaultTolerance())
390 { return isNumericallyEqual(b,a,tol); }
392 template <class P> inline bool
393 isNumericallyEqual(const std::complex<P>& a, int b,
394  double tol = RTraits<P>::getDefaultTolerance())
395 { typedef typename Widest<P,double>::Precision W; return isNumericallyEqual(a,(W)b,tol); }
397 template <class P> inline bool
398 isNumericallyEqual(int a, const std::complex<P>& b,
399  double tol = RTraits<P>::getDefaultTolerance())
400 { return isNumericallyEqual(b,a,tol); }
401 
403 template <class P> inline bool
404 isNumericallyEqual(const conjugate<P>& a, const float& b,
406 { return isNumericallyEqual(a.real(),b,tol) && isNumericallyEqual(a.imag(),0.f,tol); }
408 template <class P> inline bool
409 isNumericallyEqual(const float& a, const conjugate<P>& b,
411 { return isNumericallyEqual(b,a,tol); }
413 template <class P> inline bool
414 isNumericallyEqual(const conjugate<P>& a, const double& b,
415  double tol = RTraits<typename Narrowest<P,double>::Precision>::getDefaultTolerance())
416 { return isNumericallyEqual(a.real(),b,tol) && isNumericallyEqual(a.imag(),0.,tol); }
418 template <class P> inline bool
419 isNumericallyEqual(const double& a, const conjugate<P>& b,
420  double tol = RTraits<typename Narrowest<P,double>::Precision>::getDefaultTolerance())
421 { return isNumericallyEqual(b,a,tol); }
423 template <class P> inline bool
425  double tol = RTraits<P>::getDefaultTolerance())
426 { typedef typename Widest<P,double>::Precision W; return isNumericallyEqual(a,(W)b,tol); }
428 template <class P> inline bool
430  double tol = RTraits<P>::getDefaultTolerance())
431 { return isNumericallyEqual(b,a,tol); }
432 
434 
435 
436 template <class N> class NTraits {
437  // only the specializations below are allowed
438 };
439 
442 template <class R> class NTraits< complex<R> > {
443  typedef complex<R> C;
444 public:
445  typedef C T;
446  typedef negator<C> TNeg; // type of this after *cast* to its negative
447  typedef C TWithoutNegator; // type of this ignoring negator (there isn't one!)
448 
449  typedef R TReal;
450  typedef R TImag;
451  typedef C TComplex;
452  typedef conjugate<R> THerm; // this is a recast
453  typedef C TPosTrans;
454  typedef R TSqHermT; // ~C*C
455  typedef R TSqTHerm; // C*~C (same)
456  typedef C TElement;
457  typedef C TRow;
458  typedef C TCol;
459 
460  typedef C TSqrt;
461  typedef R TAbs;
462  typedef C TStandard; // complex is a standard type
463  typedef C TInvert; // this is a calculation, so use standard number
464  typedef C TNormalize;
465 
466  typedef C Scalar;
467  typedef C ULessScalar;
468  typedef C Number;
469  typedef C StdNumber;
470  typedef R Precision;
471  typedef R ScalarNormSq;
472 
473  // For complex scalar C, op result types are:
474  // Typeof(C*P) = Typeof(P*C)
475  // Typeof(C/P) = Typeof(inv(P)*C)
476  // Typeof(C+P) = Typeof(P+C)
477  // typeof(C-P) = Typeof(P::TNeg + C)
478  // These must be specialized for P=real, complex, conjugate.
479  template <class P> struct Result {
481  typedef typename CNT< typename CNT<P>::THerm >::template Result<C>::Mul Dvd;
483  typedef typename CNT< typename CNT<P>::TNeg >::template Result<C>::Add Sub;
484  };
485 
486  // Shape-preserving element substitution (easy for scalars!)
487  template <class P> struct Substitute {
488  typedef P Type;
489  };
490 
491  enum {
492  NRows = 1,
493  NCols = 1,
494  RowSpacing = 1,
495  ColSpacing = 1,
496  NPackedElements = 1, // not two!
497  NActualElements = 1,
498  NActualScalars = 1,
499  ImagOffset = 1,
500  RealStrideFactor = 2, // double stride when casting to real or imaginary
501  ArgDepth = SCALAR_DEPTH,
502  IsScalar = 1,
503  IsULessScalar = 1,
504  IsNumber = 1,
505  IsStdNumber = 1,
506  IsPrecision = 0,
507  SignInterpretation = 1 // after cast to Number, what is the sign?
508  };
509  static const T* getData(const T& t) { return &t; }
510  static T* updData(T& t) { return &t; }
511  static const R& real(const T& t) { return (reinterpret_cast<const R*>(&t))[0]; }
512  static R& real(T& t) { return (reinterpret_cast<R*>(&t))[0]; }
513  static const R& imag(const T& t) { return (reinterpret_cast<const R*>(&t))[1]; }
514  static R& imag(T& t) { return (reinterpret_cast<R*>(&t))[1]; }
515 
516  static const TNeg& negate(const T& t) {return reinterpret_cast<const TNeg&>(t);}
517  static TNeg& negate(T& t) {return reinterpret_cast<TNeg&>(t);}
518 
519  static const THerm& transpose(const T& t) {return reinterpret_cast<const THerm&>(t);}
520  static THerm& transpose(T& t) {return reinterpret_cast<THerm&>(t);}
521 
522  static const TPosTrans& positionalTranspose(const T& t)
523  {return reinterpret_cast<const TPosTrans&>(t);}
524  static TPosTrans& positionalTranspose(T& t)
525  {return reinterpret_cast<TPosTrans&>(t);}
526 
527  static const TWithoutNegator& castAwayNegatorIfAny(const T& t)
528  {return reinterpret_cast<const TWithoutNegator&>(t);}
529  static TWithoutNegator& updCastAwayNegatorIfAny(T& t)
530  {return reinterpret_cast<TWithoutNegator&>(t);}
531 
532  static ScalarNormSq scalarNormSqr(const T& t)
533  { return t.real()*t.real() + t.imag()*t.imag(); }
534  static TSqrt sqrt(const T& t)
535  { return std::sqrt(t); }
536  static TAbs abs(const T& t)
537  { return std::abs(t); } // no, not just sqrt of scalarNormSqr()!
538  static const TStandard& standardize(const T& t) {return t;} // already standard
539  static TNormalize normalize(const T& t) {return t/abs(t);}
540  static TInvert invert(const T& t) {return TReal(1)/t;}
541 
542  static const T& getNaN() {
543  static const T c=T(NTraits<R>::getNaN(), NTraits<R>::getNaN());
544  return c;
545  }
546  static const T& getInfinity() {
547  static const T c=T(NTraits<R>::getInfinity(),NTraits<R>::getInfinity());
548  return c;
549  }
550 
551  static const T& getI() {
552  static const T c = T(0,1);
553  return c;
554  }
555 
556  static bool isFinite(const T& t) {return SimTK::isFinite(t);}
557  static bool isNaN(const T& t) {return SimTK::isNaN(t);}
558  static bool isInf(const T& t) {return SimTK::isInf(t);}
559 
561 
562  template <class R2> static bool isNumericallyEqual(const T& a, const complex<R2>& b)
563  { return SimTK::isNumericallyEqual(a,b); }
564  template <class R2> static bool isNumericallyEqual(const T& a, const complex<R2>& b, double tol)
565  { return SimTK::isNumericallyEqual(a,b,tol); }
566  template <class R2> static bool isNumericallyEqual(const T& a, const conjugate<R2>& b)
567  { return SimTK::isNumericallyEqual(a,b); }
568  template <class R2> static bool isNumericallyEqual(const T& a, const conjugate<R2>& b, double tol)
569  { return SimTK::isNumericallyEqual(a,b,tol); }
570 
571  static bool isNumericallyEqual(const T& a, const float& b) {return SimTK::isNumericallyEqual(a,b);}
572  static bool isNumericallyEqual(const T& a, const float& b, double tol) {return SimTK::isNumericallyEqual(a,b,tol);}
573  static bool isNumericallyEqual(const T& a, const double& b) {return SimTK::isNumericallyEqual(a,b);}
574  static bool isNumericallyEqual(const T& a, const double& b, double tol) {return SimTK::isNumericallyEqual(a,b,tol);}
575  static bool isNumericallyEqual(const T& a, int b) {return SimTK::isNumericallyEqual(a,b);}
576  static bool isNumericallyEqual(const T& a, int b, double tol) {return SimTK::isNumericallyEqual(a,b,tol);}
577 
578  // The rest are the same as the real equivalents, with zero imaginary part.
579  static const T& getZero() {static const T c(NTraits<R>::getZero()); return c;}
580  static const T& getOne() {static const T c(NTraits<R>::getOne()); return c;}
581  static const T& getMinusOne() {static const T c(NTraits<R>::getMinusOne()); return c;}
582  static const T& getTwo() {static const T c(NTraits<R>::getTwo()); return c;}
583  static const T& getThree() {static const T c(NTraits<R>::getThree()); return c;}
584  static const T& getOneHalf() {static const T c(NTraits<R>::getOneHalf()); return c;}
585  static const T& getOneThird() {static const T c(NTraits<R>::getOneThird()); return c;}
586  static const T& getOneFourth() {static const T c(NTraits<R>::getOneFourth()); return c;}
587  static const T& getOneFifth() {static const T c(NTraits<R>::getOneFifth()); return c;}
588  static const T& getOneSixth() {static const T c(NTraits<R>::getOneSixth()); return c;}
589  static const T& getOneSeventh() {static const T c(NTraits<R>::getOneSeventh()); return c;}
590  static const T& getOneEighth() {static const T c(NTraits<R>::getOneEighth()); return c;}
591  static const T& getOneNinth() {static const T c(NTraits<R>::getOneNinth()); return c;}
592  static const T& getPi() {static const T c(NTraits<R>::getPi()); return c;}
593  static const T& getOneOverPi() {static const T c(NTraits<R>::getOneOverPi()); return c;}
594  static const T& getE() {static const T c(NTraits<R>::getE()); return c;}
595  static const T& getLog2E() {static const T c(NTraits<R>::getLog2E()); return c;}
596  static const T& getLog10E() {static const T c(NTraits<R>::getLog10E()); return c;}
597  static const T& getSqrt2() {static const T c(NTraits<R>::getSqrt2()); return c;}
598  static const T& getOneOverSqrt2() {static const T c(NTraits<R>::getOneOverSqrt2()); return c;}
599  static const T& getSqrt3() {static const T c(NTraits<R>::getSqrt3()); return c;}
600  static const T& getOneOverSqrt3() {static const T c(NTraits<R>::getOneOverSqrt3()); return c;}
601  static const T& getCubeRoot2() {static const T c(NTraits<R>::getCubeRoot2()); return c;}
602  static const T& getCubeRoot3() {static const T c(NTraits<R>::getCubeRoot3()); return c;}
603  static const T& getLn2() {static const T c(NTraits<R>::getLn2()); return c;}
604  static const T& getLn10() {static const T c(NTraits<R>::getLn10()); return c;}
605 };
606 
607 
608 // Specialize NTraits<complex>::Results for <complex> OP <scalar>. Result type is
609 // always just the complex type of sufficient precision.
610 #define SimTK_BNTCMPLX_SPEC(T1,T2) \
611 template<> template<> struct NTraits< complex<T1> >::Result<T2> { \
612  typedef Widest< complex<T1>,T2 >::Type W; \
613  typedef W Mul; typedef W Dvd; typedef W Add; typedef W Sub; \
614 }; \
615 template<> template<> struct NTraits< complex<T1> >::Result< complex<T2> > { \
616  typedef Widest< complex<T1>,complex<T2> >::Type W; \
617  typedef W Mul; typedef W Dvd; typedef W Add; typedef W Sub; \
618 }; \
619 template<> template<> struct NTraits< complex<T1> >::Result< conjugate<T2> > { \
620  typedef Widest< complex<T1>,complex<T2> >::Type W; \
621  typedef W Mul; typedef W Dvd; typedef W Add; typedef W Sub; \
622 }
623 SimTK_BNTCMPLX_SPEC(float,float);SimTK_BNTCMPLX_SPEC(float,double);
624 SimTK_BNTCMPLX_SPEC(double,float);SimTK_BNTCMPLX_SPEC(double,double);
625 #undef SimTK_BNTCMPLX_SPEC
626 
627 
628 // conjugate -- should be instantiated only for float, double.
629 template <class R> class NTraits< conjugate<R> > {
630  typedef complex<R> C;
631 public:
632  typedef conjugate<R> T;
633  typedef negator<T> TNeg; // type of this after *cast* to its negative
634  typedef conjugate<R> TWithoutNegator; // type of this ignoring negator (there isn't one!)
635  typedef R TReal;
636  typedef negator<R> TImag;
638  typedef complex<R> THerm; // conjugate evaporates
639  typedef conjugate<R> TPosTrans; // Positional transpose of scalar does nothing
640  typedef R TSqHermT; // C*C~
641  typedef R TSqTHerm; // ~C*C (same)
645 
646  typedef complex<R> TSqrt;
647  typedef R TAbs;
648  typedef complex<R> TStandard;
651 
655  typedef complex<R> StdNumber;
656  typedef R Precision;
657  typedef R ScalarNormSq;
658 
659  // Typeof( Conj<S>*P ) is Typeof(P*Conj<S>)
660  // Typeof( Conj<S>/P ) is Typeof(inv(P)*Conj<S>)
661  // Typeof( Conj<S>+P ) is Typeof(P+Conj<S>)
662  // Typeof( Conj<S>-P ) is Typeof(P::TNeg+Conj<S>)
663  // Must specialize for P=real or P=complex or P=conjugate
664  template <class P> struct Result {
666  typedef typename CNT<typename CNT<P>::THerm>::template Result<T>::Mul Dvd;
668  typedef typename CNT<typename CNT<P>::TNeg>::template Result<T>::Add Sub;
669  };
670 
671  // Shape-preserving element substitution (easy for scalars!)
672  template <class P> struct Substitute {
673  typedef P Type;
674  };
675 
676  enum {
677  NRows = 1,
678  NCols = 1,
679  RowSpacing = 1,
680  ColSpacing = 1,
681  NPackedElements = 1, // not two!
682  NActualElements = 1,
683  NActualScalars = 1,
684  ImagOffset = 1,
685  RealStrideFactor = 2, // double stride when casting to real or imaginary
686  ArgDepth = SCALAR_DEPTH,
687  IsScalar = 1,
688  IsULessScalar = 1,
689  IsNumber = 1,
690  IsStdNumber = 0,
691  IsPrecision = 0,
692  SignInterpretation = 1 // after cast to Number, what is the sign?
693  };
694 
695  static const T* getData(const T& t) { return &t; }
696  static T* updData(T& t) { return &t; }
697  static const TReal& real(const T& t) { return t.real(); }
698  static TReal& real(T& t) { return t.real(); }
699  static const TImag& imag(const T& t) { return t.imag(); }
700  static TImag& imag(T& t) { return t.imag(); }
701 
702  static const TNeg& negate(const T& t) {return reinterpret_cast<const TNeg&>(t);}
703  static TNeg& negate(T& t) {return reinterpret_cast<TNeg&>(t);}
704 
705  static const THerm& transpose(const T& t) {return t.conj();}
706  static THerm& transpose(T& t) {return t.conj();}
707 
708  static const TPosTrans& positionalTranspose(const T& t)
709  {return reinterpret_cast<const TPosTrans&>(t);}
710  static TPosTrans& positionalTranspose(T& t)
711  {return reinterpret_cast<TPosTrans&>(t);}
712 
713  static const TWithoutNegator& castAwayNegatorIfAny(const T& t)
714  {return reinterpret_cast<const TWithoutNegator&>(t);}
715  static TWithoutNegator& updCastAwayNegatorIfAny(T& t)
716  {return reinterpret_cast<TWithoutNegator&>(t);}
717 
718  static ScalarNormSq scalarNormSqr(const T& t)
719  { return t.real()*t.real() + t.negImag()*t.negImag(); }
720  static TSqrt sqrt(const T& t)
721  { return std::sqrt(C(t)); } // cast to complex (one negation)
722  static TAbs abs(const T& t)
723  { return std::abs(t.conj()); } // no, not just sqrt of scalarNormSqr()!
724  static TStandard standardize(const T& t)
725  { return TStandard(t); } // i.e., convert to complex
726  static TNormalize normalize(const T& t) {return TNormalize(t/abs(t));}
727 
728  // 1/conj(z) = conj(1/z), for complex z.
729  static TInvert invert(const T& t)
730  { const typename NTraits<THerm>::TInvert cmplx(NTraits<THerm>::invert(t.conj()));
731  return reinterpret_cast<const TInvert&>(cmplx); } // recast complex to conjugate it
732 
733  // We want a "conjugate NaN", NaN - NaN*i, meaning both reals should
734  // be positive NaN.
735  static const T& getNaN() {
736  static const T c=T(NTraits<R>::getNaN(),NTraits<R>::getNaN());
737  return c;
738  }
739  // We want a "conjugate infinity", Inf - Inf*i, meaning both stored reals
740  // are positive Inf.
741  static const T& getInfinity() {
742  static const T c=T(NTraits<R>::getInfinity(),NTraits<R>::getInfinity());
743  return c;
744  }
745  // But we want the constant i (=sqrt(-1)) to be the same however we represent it,
746  // so for conjugate i = 0 - (-1)i.
747  static const T& getI() {
748  static const T c = T(0,-1);
749  return c;
750  }
751 
752  static bool isFinite(const T& t) {return SimTK::isFinite(t);}
753  static bool isNaN(const T& t) {return SimTK::isNaN(t);}
754  static bool isInf(const T& t) {return SimTK::isInf(t);}
755 
757 
758  template <class R2> static bool isNumericallyEqual(const T& a, const conjugate<R2>& b)
759  { return SimTK::isNumericallyEqual(a,b); }
760  template <class R2> static bool isNumericallyEqual(const T& a, const conjugate<R2>& b, double tol)
761  { return SimTK::isNumericallyEqual(a,b,tol); }
762  template <class R2> static bool isNumericallyEqual(const T& a, const complex<R2>& b)
763  { return SimTK::isNumericallyEqual(a,b); }
764  template <class R2> static bool isNumericallyEqual(const T& a, const complex<R2>& b, double tol)
765  { return SimTK::isNumericallyEqual(a,b,tol); }
766 
767  static bool isNumericallyEqual(const T& a, const float& b) {return SimTK::isNumericallyEqual(a,b);}
768  static bool isNumericallyEqual(const T& a, const float& b, double tol) {return SimTK::isNumericallyEqual(a,b,tol);}
769  static bool isNumericallyEqual(const T& a, const double& b) {return SimTK::isNumericallyEqual(a,b);}
770  static bool isNumericallyEqual(const T& a, const double& b, double tol) {return SimTK::isNumericallyEqual(a,b,tol);}
771  static bool isNumericallyEqual(const T& a, int b) {return SimTK::isNumericallyEqual(a,b);}
772  static bool isNumericallyEqual(const T& a, int b, double tol) {return SimTK::isNumericallyEqual(a,b,tol);}
773 
774  // The rest are the same as the real equivalents, with zero imaginary part.
775  static const T& getZero() {static const T c(NTraits<R>::getZero()); return c;}
776  static const T& getOne() {static const T c(NTraits<R>::getOne()); return c;}
777  static const T& getMinusOne() {static const T c(NTraits<R>::getMinusOne()); return c;}
778  static const T& getTwo() {static const T c(NTraits<R>::getTwo()); return c;}
779  static const T& getThree() {static const T c(NTraits<R>::getThree()); return c;}
780  static const T& getOneHalf() {static const T c(NTraits<R>::getOneHalf()); return c;}
781  static const T& getOneThird() {static const T c(NTraits<R>::getOneThird()); return c;}
782  static const T& getOneFourth() {static const T c(NTraits<R>::getOneFourth()); return c;}
783  static const T& getOneFifth() {static const T c(NTraits<R>::getOneFifth()); return c;}
784  static const T& getOneSixth() {static const T c(NTraits<R>::getOneSixth()); return c;}
785  static const T& getOneSeventh() {static const T c(NTraits<R>::getOneSeventh()); return c;}
786  static const T& getOneEighth() {static const T c(NTraits<R>::getOneEighth()); return c;}
787  static const T& getOneNinth() {static const T c(NTraits<R>::getOneNinth()); return c;}
788  static const T& getPi() {static const T c(NTraits<R>::getPi()); return c;}
789  static const T& getOneOverPi() {static const T c(NTraits<R>::getOneOverPi()); return c;}
790  static const T& getE() {static const T c(NTraits<R>::getE()); return c;}
791  static const T& getLog2E() {static const T c(NTraits<R>::getLog2E()); return c;}
792  static const T& getLog10E() {static const T c(NTraits<R>::getLog10E()); return c;}
793  static const T& getSqrt2() {static const T c(NTraits<R>::getSqrt2()); return c;}
794  static const T& getOneOverSqrt2() {static const T c(NTraits<R>::getOneOverSqrt2()); return c;}
795  static const T& getSqrt3() {static const T c(NTraits<R>::getSqrt3()); return c;}
796  static const T& getOneOverSqrt3() {static const T c(NTraits<R>::getOneOverSqrt3()); return c;}
797  static const T& getCubeRoot2() {static const T c(NTraits<R>::getCubeRoot2()); return c;}
798  static const T& getCubeRoot3() {static const T c(NTraits<R>::getCubeRoot3()); return c;}
799  static const T& getLn2() {static const T c(NTraits<R>::getLn2()); return c;}
800  static const T& getLn10() {static const T c(NTraits<R>::getLn10()); return c;}
801 };
802 
803 // Any op involving conjugate & a real is best left as a conjugate. However,
804 // an op involving conjugate & a complex or conjugate can lose the conjugate at zero cost
805 // and return just a complex in some cases. Also, we prefer negator<complex> to conjugate.
806 //
807 // Conj op complex
808 // a-bi * r+si = (ar+bs) + (as-br)i (complex)
809 // a-bi / r+si = hairy and slow anyway; we'll convert to complex
810 // a-bi + r+si = (a+r) + (s-b)i (complex)
811 // a-bi - r+si = (a-r) - (b+s)i = -[(r-a)+(b+s)i] (negator<complex>)
812 //
813 // Conj op Conj
814 // a-bi * r-si = (ar-bs) - (as+br)i = -[(bs-ar)+(as+br)i] (negator<complex>)
815 // a-bi / r-si = hairy and slow anyway; we'll convert to complex
816 // a-bi + r-si = (a+r) - (b+s)i (conjugate)
817 // a-bi - r-si = (a-r) + (s-b)i (complex)
818 
819 #define SimTK_NTRAITS_CONJ_SPEC(T1,T2) \
820 template<> template<> struct NTraits< conjugate<T1> >::Result<T2> { \
821  typedef conjugate<Widest<T1,T2>::Type> W; \
822  typedef W Mul; typedef W Dvd; typedef W Add; typedef W Sub; \
823 }; \
824 template<> template<> struct NTraits< conjugate<T1> >::Result<complex<T2> >{\
825  typedef Widest<complex<T1>,complex<T2> >::Type W; \
826  typedef W Mul; typedef W Dvd; typedef W Add; typedef negator<W> Sub; \
827 }; \
828 template<> template<> struct NTraits< conjugate<T1> >::Result<conjugate<T2> >{\
829  typedef Widest<T1,T2>::Type W; typedef complex<W> WC; \
830  typedef negator<WC> Mul; typedef WC Dvd; typedef conjugate<W> Add; typedef WC Sub;\
831 }
832 SimTK_NTRAITS_CONJ_SPEC(float,float);SimTK_NTRAITS_CONJ_SPEC(float,double);
833 SimTK_NTRAITS_CONJ_SPEC(double,float);SimTK_NTRAITS_CONJ_SPEC(double,double);
834 #undef SimTK_NTRAITS_CONJ_SPEC
835 
836 
837 // Specializations for real numbers.
838 // For real scalar R, op result types are:
839 // Typeof(R*P) = Typeof(P*R)
840 // Typeof(R/P) = Typeof(inv(P)*R)
841 // Typeof(R+P) = Typeof(P+R)
842 // typeof(R-P) = Typeof(P::TNeg + R)
843 // These must be specialized for P=Real and P=Complex.
844 #define SimTK_DEFINE_REAL_NTRAITS(R) \
845 template <> class NTraits<R> { \
846 public: \
847  typedef R T; \
848  typedef negator<T> TNeg; \
849  typedef T TWithoutNegator; \
850  typedef T TReal; \
851  typedef T TImag; \
852  typedef complex<T> TComplex; \
853  typedef T THerm; \
854  typedef T TPosTrans; \
855  typedef T TSqHermT; \
856  typedef T TSqTHerm; \
857  typedef T TElement; \
858  typedef T TRow; \
859  typedef T TCol; \
860  typedef T TSqrt; \
861  typedef T TAbs; \
862  typedef T TStandard; \
863  typedef T TInvert; \
864  typedef T TNormalize; \
865  typedef T Scalar; \
866  typedef T ULessScalar; \
867  typedef T Number; \
868  typedef T StdNumber; \
869  typedef T Precision; \
870  typedef T ScalarNormSq; \
871  template <class P> struct Result { \
872  typedef typename CNT<P>::template Result<R>::Mul Mul; \
873  typedef typename CNT< typename CNT<P>::THerm >::template Result<R>::Mul Dvd; \
874  typedef typename CNT<P>::template Result<R>::Add Add; \
875  typedef typename CNT< typename CNT<P>::TNeg >::template Result<R>::Add Sub; \
876  }; \
877  template <class P> struct Substitute { \
878  typedef P Type; \
879  }; \
880  enum { \
881  NRows = 1, \
882  NCols = 1, \
883  RowSpacing = 1, \
884  ColSpacing = 1, \
885  NPackedElements = 1, \
886  NActualElements = 1, \
887  NActualScalars = 1, \
888  ImagOffset = 0, \
889  RealStrideFactor = 1, \
890  ArgDepth = SCALAR_DEPTH, \
891  IsScalar = 1, \
892  IsULessScalar = 1, \
893  IsNumber = 1, \
894  IsStdNumber = 1, \
895  IsPrecision = 1, \
896  SignInterpretation = 1 \
897  }; \
898  static const T* getData(const T& t) { return &t; } \
899  static T* updData(T& t) { return &t; } \
900  static const T& real(const T& t) { return t; } \
901  static T& real(T& t) { return t; } \
902  static const T& imag(const T&) { return getZero(); } \
903  static T& imag(T&) { assert(false); return *reinterpret_cast<T*>(0); } \
904  static const TNeg& negate(const T& t) {return reinterpret_cast<const TNeg&>(t);} \
905  static TNeg& negate(T& t) {return reinterpret_cast<TNeg&>(t);} \
906  static const THerm& transpose(const T& t) {return reinterpret_cast<const THerm&>(t);} \
907  static THerm& transpose(T& t) {return reinterpret_cast<THerm&>(t);} \
908  static const TPosTrans& positionalTranspose(const T& t) \
909  {return reinterpret_cast<const TPosTrans&>(t);} \
910  static TPosTrans& positionalTranspose(T& t) \
911  {return reinterpret_cast<TPosTrans&>(t);} \
912  static const TWithoutNegator& castAwayNegatorIfAny(const T& t) \
913  {return reinterpret_cast<const TWithoutNegator&>(t);} \
914  static TWithoutNegator& updCastAwayNegatorIfAny(T& t) \
915  {return reinterpret_cast<TWithoutNegator&>(t);} \
916  static ScalarNormSq scalarNormSqr(const T& t) {return t*t;} \
917  static TSqrt sqrt(const T& t) {return std::sqrt(t);} \
918  static TAbs abs(const T& t) {return std::abs(t);} \
919  static const TStandard& standardize(const T& t) {return t;} \
920  static TNormalize normalize(const T& t) {return (t>0?T(1):(t<0?T(-1):getNaN()));} \
921  static TInvert invert(const T& t) {return T(1)/t;} \
922  /* properties of this floating point representation, with memory addresses */ \
923  static const T& getEps() {return RTraits<T>::getEps();} \
924  static const T& getSignificant() {return RTraits<T>::getSignificant();} \
925  static const T& getNaN() {static const T c=std::numeric_limits<T>::quiet_NaN(); return c;} \
926  static const T& getInfinity() {static const T c=std::numeric_limits<T>::infinity(); return c;} \
927  static const T& getLeastPositive(){static const T c=std::numeric_limits<T>::min(); return c;} \
928  static const T& getMostPositive() {static const T c=std::numeric_limits<T>::max(); return c;} \
929  static const T& getLeastNegative(){static const T c=-std::numeric_limits<T>::min(); return c;} \
930  static const T& getMostNegative() {static const T c=-std::numeric_limits<T>::max(); return c;} \
931  static const T& getSqrtEps() {static const T c=std::sqrt(getEps()); return c;} \
932  static const T& getTiny() {static const T c=std::pow(getEps(), (T)1.25L); return c;} \
933  static bool isFinite(const T& t) {return SimTK::isFinite(t);} \
934  static bool isNaN (const T& t) {return SimTK::isNaN(t);} \
935  static bool isInf (const T& t) {return SimTK::isInf(t);} \
936  /* Methods to use for approximate comparisons. Perform comparison in the wider of the two */ \
937  /* precisions, using the default tolerance from the narrower of the two precisions. */ \
938  static double getDefaultTolerance() {return RTraits<T>::getDefaultTolerance();} \
939  static bool isNumericallyEqual(const T& t, const float& f) {return SimTK::isNumericallyEqual(t,f);} \
940  static bool isNumericallyEqual(const T& t, const double& d) {return SimTK::isNumericallyEqual(t,d);} \
941  static bool isNumericallyEqual(const T& t, int i) {return SimTK::isNumericallyEqual(t,i);} \
942  /* Here the tolerance is given so we don't have to figure it out. */ \
943  static bool isNumericallyEqual(const T& t, const float& f, double tol){return SimTK::isNumericallyEqual(t,f,tol);} \
944  static bool isNumericallyEqual(const T& t, const double& d, double tol){return SimTK::isNumericallyEqual(t,d,tol);} \
945  static bool isNumericallyEqual(const T& t, int i, double tol){return SimTK::isNumericallyEqual(t,i,tol);} \
946  /* Carefully calculated constants with convenient memory addresses. */ \
947  static const T& getZero() {static const T c=(T)(0); return c;} \
948  static const T& getOne() {static const T c=(T)(1); return c;} \
949  static const T& getMinusOne() {static const T c=(T)(-1); return c;} \
950  static const T& getTwo() {static const T c=(T)(2); return c;} \
951  static const T& getThree() {static const T c=(T)(3); return c;} \
952  static const T& getOneHalf() {static const T c=(T)(0.5L); return c;} \
953  static const T& getOneThird() {static const T c=(T)(1.L/3.L); return c;} \
954  static const T& getOneFourth() {static const T c=(T)(0.25L); return c;} \
955  static const T& getOneFifth() {static const T c=(T)(0.2L); return c;} \
956  static const T& getOneSixth() {static const T c=(T)(1.L/6.L); return c;} \
957  static const T& getOneSeventh() {static const T c=(T)(1.L/7.L); return c;} \
958  static const T& getOneEighth() {static const T c=(T)(0.125L); return c;} \
959  static const T& getOneNinth() {static const T c=(T)(1.L/9.L); return c;} \
960  static const T& getPi() {static const T c=(T)(SimTK_PI); return c;} \
961  static const T& getOneOverPi() {static const T c=(T)(1.L/SimTK_PI); return c;} \
962  static const T& getE() {static const T c=(T)(SimTK_E); return c;} \
963  static const T& getLog2E() {static const T c=(T)(SimTK_LOG2E); return c;} \
964  static const T& getLog10E() {static const T c=(T)(SimTK_LOG10E); return c;} \
965  static const T& getSqrt2() {static const T c=(T)(SimTK_SQRT2); return c;} \
966  static const T& getOneOverSqrt2() {static const T c=(T)(1.L/SimTK_SQRT2); return c;} \
967  static const T& getSqrt3() {static const T c=(T)(SimTK_SQRT3); return c;} \
968  static const T& getOneOverSqrt3() {static const T c=(T)(1.L/SimTK_SQRT3); return c;} \
969  static const T& getCubeRoot2() {static const T c=(T)(SimTK_CBRT2); return c;} \
970  static const T& getCubeRoot3() {static const T c=(T)(SimTK_CBRT3); return c;} \
971  static const T& getLn2() {static const T c=(T)(SimTK_LN2); return c;} \
972  static const T& getLn10() {static const T c=(T)(SimTK_LN10); return c;} \
973  /* integer digit counts useful for formatted input and output */ \
974  static int getNumDigits() {static const int c=(int)(std::log10(1/getEps()) -0.5); return c;} \
975  static int getLosslessNumDigits() {static const int c=(int)(std::log10(1/getTiny())+0.5); return c;} \
976 }; \
977 template<> struct NTraits<R>::Result<float> \
978  {typedef Widest<R,float>::Type Mul;typedef Mul Dvd;typedef Mul Add;typedef Mul Sub;}; \
979 template<> struct NTraits<R>::Result<double> \
980  {typedef Widest<R,double>::Type Mul;typedef Mul Dvd;typedef Mul Add;typedef Mul Sub;}; \
981 template<> struct NTraits<R>::Result<complex<float> > \
982  {typedef Widest<R,complex<float> >::Type Mul;typedef Mul Dvd;typedef Mul Add;typedef Mul Sub;}; \
983 template<> struct NTraits<R>::Result<complex<double> > \
984  {typedef Widest<R,complex<double> >::Type Mul;typedef Mul Dvd;typedef Mul Add;typedef Mul Sub;}; \
985 template<> struct NTraits<R>::Result<conjugate<float> > \
986  {typedef conjugate<Widest<R,float>::Type> Mul;typedef Mul Dvd;typedef Mul Add;typedef Mul Sub;}; \
987 template<> struct NTraits<R>::Result<conjugate<double> > \
988  {typedef conjugate<Widest<R,double>::Type> Mul;typedef Mul Dvd;typedef Mul Add;typedef Mul Sub;}
989 
990 #if defined(__clang__)
991 #pragma clang diagnostic push
992 // The function `T& imag(T&)` generates a null-dereference warning.
993 #pragma clang diagnostic ignored "-Wnull-dereference"
994 #endif
997 #if defined(__clang__)
998 #pragma clang diagnostic pop
999 #endif
1000 
1001 #undef SimTK_DEFINE_REAL_NTRAITS
1002 
1004 template <class R> class CNT< complex<R> > : public NTraits< complex<R> > { };
1005 template <class R> class CNT< conjugate<R> > : public NTraits< conjugate<R> > { };
1006 template <> class CNT<float> : public NTraits<float> { };
1007 template <> class CNT<double> : public NTraits<double> { };
1008 
1009 
1010 } // namespace SimTK
1011 
1012 #endif //SimTK_SIMMATRIX_NTRAITS_H_
static TNormalize normalize(const T &t)
Definition: NTraits.h:539
static TImag & imag(T &t)
Definition: NTraits.h:700
static bool isNumericallyEqual(const T &a, int b)
Definition: NTraits.h:575
static const T & getOneFourth()
Definition: NTraits.h:782
CNT< P >::template Result< C >::Mul Mul
Definition: NTraits.h:480
C ULessScalar
Definition: NTraits.h:467
C TStandard
Definition: NTraits.h:462
static const T & getInfinity()
Definition: NTraits.h:546
R TReal
Definition: NTraits.h:635
static const T & getOneEighth()
Definition: NTraits.h:590
static bool isNumericallyEqual(const T &a, const double &b)
Definition: NTraits.h:573
static const T & getOneOverSqrt3()
Definition: NTraits.h:600
C TInvert
Definition: NTraits.h:463
double Type
Definition: NTraits.h:133
static const T & getLn10()
Definition: NTraits.h:604
static const T & getOne()
Definition: NTraits.h:776
static const T & getMinusOne()
Definition: NTraits.h:581
static const T & getSqrt3()
Definition: NTraits.h:599
static const T & getOneSixth()
Definition: NTraits.h:588
conjugate< R > TCol
Definition: NTraits.h:644
complex< typename Widest< R1, R2 >::Type > Type
Definition: NTraits.h:116
static const T & getLog10E()
Definition: NTraits.h:792
conjugate< R > TComplex
Definition: NTraits.h:637
static bool isNumericallyEqual(const T &a, const double &b, double tol)
Definition: NTraits.h:574
RTraits is a helper class for NTraits.
Definition: NTraits.h:148
SimTK_DEFINE_REAL_NTRAITS(float)
static const T & getOneSeventh()
Definition: NTraits.h:785
R TSqTHerm
Definition: NTraits.h:641
static const T & getThree()
Definition: NTraits.h:779
static TPosTrans & positionalTranspose(T &t)
Definition: NTraits.h:710
complex< R > TSqrt
Definition: NTraits.h:646
R ScalarNormSq
Definition: NTraits.h:657
static const T & getCubeRoot3()
Definition: NTraits.h:602
R TReal
Definition: NTraits.h:449
CNT< typename CNT< P >::TNeg >::template Result< C >::Add Sub
Definition: NTraits.h:483
static const T & getZero()
Definition: NTraits.h:579
static bool isFinite(const T &t)
Definition: NTraits.h:556
static const T & getOneThird()
Definition: NTraits.h:781
C TRow
Definition: NTraits.h:457
static const THerm & transpose(const T &t)
Definition: NTraits.h:705
This is the top-level SimTK namespace into which all SimTK names are placed to avoid collision with o...
Definition: Assembler.h:37
SimTK::conjugate<R> should be instantiated only for float, double.
Definition: String.h:45
static const THerm & transpose(const T &t)
Definition: NTraits.h:519
static bool isNumericallyEqual(const T &a, const float &b)
Definition: NTraits.h:571
static const T & getSqrt2()
Definition: NTraits.h:793
double Type
Definition: NTraits.h:104
static bool isNumericallyEqual(const T &a, const complex< R2 > &b, double tol)
Definition: NTraits.h:764
static const T & getOneSixth()
Definition: NTraits.h:784
conjugate< R > TInvert
Definition: NTraits.h:649
static const T & getOneNinth()
Definition: NTraits.h:591
static bool isNaN(const T &t)
Definition: NTraits.h:753
static const double & getSignificant()
Definition: NTraits.h:161
complex< R > THerm
Definition: NTraits.h:638
static const T & getOneFifth()
Definition: NTraits.h:587
static const TPosTrans & positionalTranspose(const T &t)
Definition: NTraits.h:522
static const T & getThree()
Definition: NTraits.h:583
static bool isNaN(const T &t)
Definition: NTraits.h:557
static const T & getSqrt2()
Definition: NTraits.h:597
C TNormalize
Definition: NTraits.h:464
conjugate< R > ULessScalar
Definition: NTraits.h:653
static TInvert invert(const T &t)
Definition: NTraits.h:729
static bool isNumericallyEqual(const T &a, int b, double tol)
Definition: NTraits.h:772
static const T & getOneOverSqrt2()
Definition: NTraits.h:794
static const T & getOneNinth()
Definition: NTraits.h:787
static const T & getMinusOne()
Definition: NTraits.h:777
static const T & getOneOverSqrt2()
Definition: NTraits.h:598
static const T & getLog2E()
Definition: NTraits.h:595
CNT< P >::template Result< T >::Mul Mul
Definition: NTraits.h:665
float Type
Definition: NTraits.h:131
static const TNeg & negate(const T &t)
Definition: NTraits.h:702
static const TPosTrans & positionalTranspose(const T &t)
Definition: NTraits.h:708
static const float & getEps()
Attainable accuracy at this precision.
Definition: NTraits.h:152
static const T & getE()
Definition: NTraits.h:790
conjugate< R > T
Definition: NTraits.h:632
C TWithoutNegator
Definition: NTraits.h:447
negator<N>, where N is a number type (real, complex, conjugate), is represented in memory identically...
Definition: String.h:44
C T
Definition: NTraits.h:445
conjugate< R > Number
Definition: NTraits.h:654
Widest< R1, R2 >::Precision Precision
Definition: NTraits.h:117
static const T & getCubeRoot2()
Definition: NTraits.h:601
Widest< R1, R2 >::Precision Precision
Definition: NTraits.h:109
static const T & getNaN()
Definition: NTraits.h:735
CNT< P >::template Result< T >::Add Add
Definition: NTraits.h:667
static const TNeg & negate(const T &t)
Definition: NTraits.h:516
static bool isNumericallyEqual(const T &a, const conjugate< R2 > &b)
Definition: NTraits.h:566
static THerm & transpose(T &t)
Definition: NTraits.h:520
static const T & getLn2()
Definition: NTraits.h:603
static const T & getCubeRoot2()
Definition: NTraits.h:797
C Scalar
Definition: NTraits.h:466
negator< R > TImag
Definition: NTraits.h:636
static TSqrt sqrt(const T &t)
Definition: NTraits.h:720
static const T & getPi()
Definition: NTraits.h:592
static TInvert invert(const T &t)
Definition: NTraits.h:540
static const T & getPi()
Definition: NTraits.h:788
static TReal & real(T &t)
Definition: NTraits.h:698
float Precision
Definition: NTraits.h:130
SimTK_BNTCMPLX_SPEC(float, float)
float Type
Definition: NTraits.h:130
R TImag
Definition: NTraits.h:450
C TComplex
Definition: NTraits.h:451
static TAbs abs(const T &t)
Definition: NTraits.h:536
static TNeg & negate(T &t)
Definition: NTraits.h:517
complex< typename Widest< R1, R2 >::Type > Type
Definition: NTraits.h:112
static TSqrt sqrt(const T &t)
Definition: NTraits.h:534
R Precision
Definition: NTraits.h:656
CNT< typename CNT< P >::TNeg >::template Result< T >::Add Sub
Definition: NTraits.h:668
static bool isNumericallyEqual(const T &a, const conjugate< R2 > &b, double tol)
Definition: NTraits.h:760
bool isFinite(const negator< float > &x)
Definition: negator.h:285
R TAbs
Definition: NTraits.h:647
static R & real(T &t)
Definition: NTraits.h:512
conjugate< R > TNormalize
Definition: NTraits.h:650
Definition: CompositeNumericalTypes.h:116
static const R & imag(const T &t)
Definition: NTraits.h:513
static bool isFinite(const T &t)
Definition: NTraits.h:752
Narrowest< R1, R2 >::Precision Precision
Definition: NTraits.h:140
conjugate< R > TWithoutNegator
Definition: NTraits.h:634
CNT< typename CNT< P >::THerm >::template Result< T >::Mul Dvd
Definition: NTraits.h:666
conjugate< R > TPosTrans
Definition: NTraits.h:639
static bool isNumericallyEqual(const T &a, int b)
Definition: NTraits.h:771
static TAbs abs(const T &t)
Definition: NTraits.h:722
float Precision
Definition: NTraits.h:131
double Type
Definition: NTraits.h:105
static TNormalize normalize(const T &t)
Definition: NTraits.h:726
static const T & getTwo()
Definition: NTraits.h:778
static const double & getEps()
Definition: NTraits.h:160
C TCol
Definition: NTraits.h:458
static const TWithoutNegator & castAwayNegatorIfAny(const T &t)
Definition: NTraits.h:713
static TStandard standardize(const T &t)
Definition: NTraits.h:724
static TWithoutNegator & updCastAwayNegatorIfAny(T &t)
Definition: NTraits.h:529
static const T & getTwo()
Definition: NTraits.h:582
float Type
Definition: NTraits.h:132
R TAbs
Definition: NTraits.h:461
This class is specialized for all 16 combinations of standard types (that is, real and complex types ...
Definition: NTraits.h:102
static TWithoutNegator & updCastAwayNegatorIfAny(T &t)
Definition: NTraits.h:715
static bool isNumericallyEqual(const T &a, const conjugate< R2 > &b)
Definition: NTraits.h:758
static double getDefaultTolerance()
Definition: NTraits.h:162
High precision mathematical and physical constants.
The purpose of the CNT<T> class is to hide the differences between built-in numerical types and compo...
static ScalarNormSq scalarNormSqr(const T &t)
Definition: NTraits.h:532
static const T & getOneThird()
Definition: NTraits.h:585
static bool isNumericallyEqual(const T &a, const double &b, double tol)
Definition: NTraits.h:770
complex< typename Widest< R1, R2 >::Type > Type
Definition: NTraits.h:108
double Precision
Definition: NTraits.h:133
conjugate< R > TRow
Definition: NTraits.h:643
static const T & getOneSeventh()
Definition: NTraits.h:589
static bool isNumericallyEqual(const T &a, const float &b, double tol)
Definition: NTraits.h:768
ELEM max(const VectorBase< ELEM > &v)
Definition: VectorMath.h:251
R ScalarNormSq
Definition: NTraits.h:471
static const TReal & real(const T &t)
Definition: NTraits.h:697
conjugate< R > THerm
Definition: NTraits.h:452
static TNeg & negate(T &t)
Definition: NTraits.h:703
static const T & getOne()
Definition: NTraits.h:580
static double getDefaultTolerance()
Definition: NTraits.h:560
static bool isNumericallyEqual(const T &a, int b, double tol)
Definition: NTraits.h:576
double Precision
Definition: NTraits.h:105
static const TImag & imag(const T &t)
Definition: NTraits.h:699
static const T & getInfinity()
Definition: NTraits.h:741
This class is specialized for all 16 combinations of standard types (that is, real and complex types ...
Definition: NTraits.h:129
static const T & getOneHalf()
Definition: NTraits.h:780
Widest< R1, R2 >::Precision Precision
Definition: NTraits.h:113
static const T & getE()
Definition: NTraits.h:594
static const float & getSignificant()
What multiple of attainable accuracy do we consider significant?
Definition: NTraits.h:154
complex< typename Narrowest< R1, R2 >::Type > Type
Definition: NTraits.h:139
static R & imag(T &t)
Definition: NTraits.h:514
RowVectorBase< typename CNT< ELEM >::TAbs > abs(const RowVectorBase< ELEM > &v)
Definition: VectorMath.h:120
bool isNaN(const negator< float > &x)
Definition: negator.h:272
Narrowest< R1, R2 >::Precision Precision
Definition: NTraits.h:136
static const T & getOneFourth()
Definition: NTraits.h:586
static T * updData(T &t)
Definition: NTraits.h:696
Specialized information about Composite Numerical Types which allows us to define appropriate templat...
Definition: CompositeNumericalTypes.h:136
static const T & getNaN()
Definition: NTraits.h:542
static const TStandard & standardize(const T &t)
Definition: NTraits.h:538
conjugate< R > TElement
Definition: NTraits.h:642
SimTK_NTRAITS_CONJ_SPEC(float, float)
static bool isInf(const T &t)
Definition: NTraits.h:558
static const T & getCubeRoot3()
Definition: NTraits.h:798
static double getDefaultTolerance()
Definition: NTraits.h:756
bool isInf(const negator< float > &x)
Definition: negator.h:298
double Type
Definition: NTraits.h:106
static ScalarNormSq scalarNormSqr(const T &t)
Definition: NTraits.h:718
static bool isNumericallyEqual(const T &a, const complex< R2 > &b)
Definition: NTraits.h:762
static const T & getSqrt3()
Definition: NTraits.h:795
static const T & getLog10E()
Definition: NTraits.h:596
static const T & getOneEighth()
Definition: NTraits.h:786
static const T & getLog2E()
Definition: NTraits.h:791
Narrowest< R1, R2 >::Precision Precision
Definition: NTraits.h:144
static T * updData(T &t)
Definition: NTraits.h:510
C StdNumber
Definition: NTraits.h:469
negator< T > TNeg
Definition: NTraits.h:633
complex< typename Narrowest< R1, R2 >::Type > Type
Definition: NTraits.h:143
CNT< typename CNT< P >::THerm >::template Result< C >::Mul Dvd
Definition: NTraits.h:481
static bool isNumericallyEqual(const T &a, const float &b, double tol)
Definition: NTraits.h:572
R Precision
Definition: NTraits.h:470
static bool isInf(const T &t)
Definition: NTraits.h:754
static const T & getOneOverPi()
Definition: NTraits.h:789
double Precision
Definition: NTraits.h:104
static const T & getOneOverPi()
Definition: NTraits.h:593
conjugate< R > Scalar
Definition: NTraits.h:652
C TPosTrans
Definition: NTraits.h:453
static const T * getData(const T &t)
Definition: NTraits.h:509
C TSqrt
Definition: NTraits.h:460
static const T & getI()
Definition: NTraits.h:747
static const T & getOneHalf()
Definition: NTraits.h:584
R TSqTHerm
Definition: NTraits.h:455
R TSqHermT
Definition: NTraits.h:640
static bool isNumericallyEqual(const T &a, const complex< R2 > &b)
Definition: NTraits.h:562
static bool isNumericallyEqual(const T &a, const conjugate< R2 > &b, double tol)
Definition: NTraits.h:568
C TElement
Definition: NTraits.h:456
static const T & getLn10()
Definition: NTraits.h:800
double Precision
Definition: NTraits.h:106
static double getDefaultTolerance()
The default numerical error tolerance is always given in double precision.
Definition: NTraits.h:156
static const T * getData(const T &t)
Definition: NTraits.h:695
complex< typename Narrowest< R1, R2 >::Type > Type
Definition: NTraits.h:135
complex< R > TStandard
Definition: NTraits.h:648
static const T & getZero()
Definition: NTraits.h:775
static bool isNumericallyEqual(const T &a, const double &b)
Definition: NTraits.h:769
static const TWithoutNegator & castAwayNegatorIfAny(const T &t)
Definition: NTraits.h:527
negator< C > TNeg
Definition: NTraits.h:446
float Precision
Definition: NTraits.h:103
static bool isNumericallyEqual(const T &a, const complex< R2 > &b, double tol)
Definition: NTraits.h:564
static TPosTrans & positionalTranspose(T &t)
Definition: NTraits.h:524
static const T & getOneOverSqrt3()
Definition: NTraits.h:796
R TSqHermT
Definition: NTraits.h:454
static const R & real(const T &t)
Definition: NTraits.h:511
CNT< P >::template Result< C >::Add Add
Definition: NTraits.h:482
float Type
Definition: NTraits.h:103
complex< R > StdNumber
Definition: NTraits.h:655
Definition: negator.h:64
static const T & getLn2()
Definition: NTraits.h:799
static const T & getOneFifth()
Definition: NTraits.h:783
static const T & getI()
Definition: NTraits.h:551
float Precision
Definition: NTraits.h:132
bool isNumericallyEqual(const float &a, const float &b, double tol=RTraits< float >::getDefaultTolerance())
Compare two floats for approximate equality.
Definition: NTraits.h:293
C Number
Definition: NTraits.h:468
static bool isNumericallyEqual(const T &a, const float &b)
Definition: NTraits.h:767
static THerm & transpose(T &t)
Definition: NTraits.h:706