Simbody 3.7
Loading...
Searching...
No Matches
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
52
53#include <cstddef>
54#include <cassert>
55#include <complex>
56#include <iostream>
57#include <limits>
58
59using std::complex;
60
61namespace 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.
71template <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.
76template <class T> class CNT;
77
78// NTraits provides information like CNT, but for numeric types only.
79template <class N> class NTraits; // allowed only for N=<number>
80template <class R> class NTraits< complex<R> >;
81template <class R> class NTraits< conjugate<R> >;
82template <> class NTraits<float>;
83template <> 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.
93template <class N> class negator; // Only defined for numbers
94
102template <class R1, class R2> struct Widest {/* Only defined for built-ins. */};
103template <> struct Widest<float,float> {typedef float Type; typedef float Precision;};
104template <> struct Widest<float,double> {typedef double Type; typedef double Precision;};
105template <> struct Widest<double,float> {typedef double Type; typedef double Precision;};
106template <> struct Widest<double,double> {typedef double Type; typedef double Precision;};
107template <class R1, class R2> struct Widest< complex<R1>,complex<R2> > {
108 typedef complex< typename Widest<R1,R2>::Type > Type;
110};
111template <class R1, class R2> struct Widest< complex<R1>,R2 > {
112 typedef complex< typename Widest<R1,R2>::Type > Type;
114};
115template <class R1, class R2> struct Widest< R1,complex<R2> > {
116 typedef complex< typename Widest<R1,R2>::Type > Type;
118};
119
129template <class R1, class R2> struct Narrowest {/* Only defined for built-ins. */};
130template <> struct Narrowest<float,float> {typedef float Type; typedef float Precision;};
131template <> struct Narrowest<float,double> {typedef float Type; typedef float Precision;};
132template <> struct Narrowest<double,float> {typedef float Type; typedef float Precision;};
133template <> struct Narrowest<double,double> {typedef double Type; typedef double Precision;};
134template <class R1, class R2> struct Narrowest< complex<R1>,complex<R2> > {
135 typedef complex< typename Narrowest<R1,R2>::Type > Type;
137};
138template <class R1, class R2> struct Narrowest< complex<R1>,R2 > {
139 typedef complex< typename Narrowest<R1,R2>::Type > Type;
141};
142template <class R1, class R2> struct Narrowest< R1,complex<R2> > {
143 typedef complex< typename Narrowest<R1,R2>::Type > Type;
145};
146
148template <class R> class RTraits {/* Only defined for real types */};
149template <> class RTraits<float> {
150public:
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};
158template <> class RTraits<double> {
159public:
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.
183inline bool isNaN(const float& x) {return std::isnan(x);}
184inline bool isNaN(const double& x) {return std::isnan(x);}
185
186template <class P> inline bool
187isNaN(const std::complex<P>& x)
188{ return isNaN(x.real()) || isNaN(x.imag());}
189
190template <class P> inline bool
192{ return isNaN(x.real()) || isNaN(x.negImag());}
194
207// See negator.h for isFinite() applied to negated scalars.
209inline bool isFinite(const float& x) {return std::isfinite(x);}
210inline bool isFinite(const double& x) {return std::isfinite(x);}
211
212template <class P> inline bool
213isFinite(const std::complex<P>& x)
214{ return isFinite(x.real()) && isFinite(x.imag());}
215
216template <class P> inline bool
218{ return isFinite(x.real()) && isFinite(x.negImag());}
220
235// See negator.h for isInf() applied to negated scalars.
237inline bool isInf(const float& x) {return std::isinf(x);}
238inline bool isInf(const double& x) {return std::isinf(x);}
239
240template <class P> inline bool
241isInf(const std::complex<P>& x) {
242 return (isInf(x.real()) && !isNaN(x.imag()))
243 || (isInf(x.imag()) && !isNaN(x.real()));
244}
245
246template <class P> inline bool
248 return (isInf(x.real()) && !isNaN(x.negImag()))
249 || (isInf(x.negImag()) && !isNaN(x.real()));
250}
252
293inline 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; }
299inline 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
306inline bool isNumericallyEqual(const float& a, const double& b,
308{ return isNumericallyEqual((double)a, b, tol); }
310inline bool isNumericallyEqual(const double& a, const float& b,
312{ return isNumericallyEqual(a, (double)b, tol); }
313
315inline bool isNumericallyEqual(const float& a, int b,
317{ return isNumericallyEqual(a, (double)b, tol); }
319inline bool isNumericallyEqual(int a, const float& b,
321{ return isNumericallyEqual((double)a, b, tol); }
323inline bool isNumericallyEqual(const double& a, int b,
325{ return isNumericallyEqual(a, (double)b, tol); }
327inline bool isNumericallyEqual(int a, const double& b,
329{ return isNumericallyEqual((double)a, b, tol); }
330
334template <class P, class Q>
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
344template <class P, class Q>
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
354template <class P, class Q>
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
364template <class P, class Q>
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
372template <class P> inline bool
373isNumericallyEqual(const std::complex<P>& a, const float& b,
375{ return isNumericallyEqual(a.real(),b,tol) && isNumericallyEqual(a.imag(),0.f,tol); }
377template <class P> inline bool
378isNumericallyEqual(const float& a, const std::complex<P>& b,
380{ return isNumericallyEqual(b,a,tol); }
382template <class P> inline bool
383isNumericallyEqual(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); }
387template <class P> inline bool
388isNumericallyEqual(const double& a, const std::complex<P>& b,
389 double tol = RTraits<typename Narrowest<P,double>::Precision>::getDefaultTolerance())
390{ return isNumericallyEqual(b,a,tol); }
392template <class P> inline bool
393isNumericallyEqual(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); }
397template <class P> inline bool
398isNumericallyEqual(int a, const std::complex<P>& b,
399 double tol = RTraits<P>::getDefaultTolerance())
400{ return isNumericallyEqual(b,a,tol); }
401
403template <class P> inline bool
404isNumericallyEqual(const conjugate<P>& a, const float& b,
406{ return isNumericallyEqual(a.real(),b,tol) && isNumericallyEqual(a.imag(),0.f,tol); }
408template <class P> inline bool
409isNumericallyEqual(const float& a, const conjugate<P>& b,
411{ return isNumericallyEqual(b,a,tol); }
413template <class P> inline bool
414isNumericallyEqual(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); }
418template <class P> inline bool
419isNumericallyEqual(const double& a, const conjugate<P>& b,
420 double tol = RTraits<typename Narrowest<P,double>::Precision>::getDefaultTolerance())
421{ return isNumericallyEqual(b,a,tol); }
423template <class P> inline bool
425 double tol = RTraits<P>::getDefaultTolerance())
426{ typedef typename Widest<P,double>::Precision W; return isNumericallyEqual(a,(W)b,tol); }
428template <class P> inline bool
430 double tol = RTraits<P>::getDefaultTolerance())
431{ return isNumericallyEqual(b,a,tol); }
432
434
435
436template <class N> class NTraits {
437 // only the specializations below are allowed
438};
439
442template <class R> class NTraits< complex<R> > {
443 typedef complex<R> C;
444public:
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);}
525 {return reinterpret_cast<TPosTrans&>(t);}
526
527 static const TWithoutNegator& castAwayNegatorIfAny(const T& t)
528 {return reinterpret_cast<const TWithoutNegator&>(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() {
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) \
611template<> 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}; \
615template<> 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}; \
619template<> 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}
623SimTK_BNTCMPLX_SPEC(float,float);SimTK_BNTCMPLX_SPEC(float,double);
624SimTK_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.
629template <class R> class NTraits< conjugate<R> > {
630 typedef complex<R> C;
631public:
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;
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);}
711 {return reinterpret_cast<TPosTrans&>(t);}
712
713 static const TWithoutNegator& castAwayNegatorIfAny(const T& t)
714 {return reinterpret_cast<const TWithoutNegator&>(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() {
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) \
820template<> 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}; \
824template<> 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}; \
828template<> 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}
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) \
845template <> class NTraits<R> { \
846public: \
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}; \
977template<> struct NTraits<R>::Result<float> \
978 {typedef Widest<R,float>::Type Mul;typedef Mul Dvd;typedef Mul Add;typedef Mul Sub;}; \
979template<> struct NTraits<R>::Result<double> \
980 {typedef Widest<R,double>::Type Mul;typedef Mul Dvd;typedef Mul Add;typedef Mul Sub;}; \
981template<> struct NTraits<R>::Result<complex<float> > \
982 {typedef Widest<R,complex<float> >::Type Mul;typedef Mul Dvd;typedef Mul Add;typedef Mul Sub;}; \
983template<> struct NTraits<R>::Result<complex<double> > \
984 {typedef Widest<R,complex<double> >::Type Mul;typedef Mul Dvd;typedef Mul Add;typedef Mul Sub;}; \
985template<> struct NTraits<R>::Result<conjugate<float> > \
986 {typedef conjugate<Widest<R,float>::Type> Mul;typedef Mul Dvd;typedef Mul Add;typedef Mul Sub;}; \
987template<> 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
1004template <class R> class CNT< complex<R> > : public NTraits< complex<R> > { };
1005template <class R> class CNT< conjugate<R> > : public NTraits< conjugate<R> > { };
1006template <> class CNT<float> : public NTraits<float> { };
1007template <> class CNT<double> : public NTraits<double> { };
1008
1009
1010} // namespace SimTK
1011
1012#endif //SimTK_SIMMATRIX_NTRAITS_H_
The purpose of the CNT<T> class is to hide the differences between built-in numerical types and compo...
High precision mathematical and physical constants.
#define SimTK_BNTCMPLX_SPEC(T1, T2)
Definition NTraits.h:610
#define SimTK_NTRAITS_CONJ_SPEC(T1, T2)
Definition NTraits.h:819
#define SimTK_DEFINE_REAL_NTRAITS(R)
Definition NTraits.h:844
Specialized information about Composite Numerical Types which allows us to define appropriate templat...
Definition CompositeNumericalTypes.h:136
static const TPosTrans & positionalTranspose(const T &t)
Definition NTraits.h:522
static TInvert invert(const T &t)
Definition NTraits.h:540
static const T & getSqrt2()
Definition NTraits.h:597
static bool isNumericallyEqual(const T &a, const conjugate< R2 > &b, double tol)
Definition NTraits.h:568
C T
Definition NTraits.h:445
C ULessScalar
Definition NTraits.h:467
static const R & imag(const T &t)
Definition NTraits.h:513
C TNormalize
Definition NTraits.h:464
static R & imag(T &t)
Definition NTraits.h:514
static TAbs abs(const T &t)
Definition NTraits.h:536
static const T & getE()
Definition NTraits.h:594
static const T & getLn2()
Definition NTraits.h:603
R TSqTHerm
Definition NTraits.h:455
static const T & getCubeRoot2()
Definition NTraits.h:601
static bool isNumericallyEqual(const T &a, const complex< R2 > &b)
Definition NTraits.h:562
static const T & getOneThird()
Definition NTraits.h:585
static TNeg & negate(T &t)
Definition NTraits.h:517
static const T & getI()
Definition NTraits.h:551
static const T & getOneOverPi()
Definition NTraits.h:593
C TCol
Definition NTraits.h:458
static const T & getOneSixth()
Definition NTraits.h:588
R ScalarNormSq
Definition NTraits.h:471
static const R & real(const T &t)
Definition NTraits.h:511
static bool isNumericallyEqual(const T &a, const double &b)
Definition NTraits.h:573
static const T & getOneHalf()
Definition NTraits.h:584
static THerm & transpose(T &t)
Definition NTraits.h:520
static bool isNumericallyEqual(const T &a, int b)
Definition NTraits.h:575
static const TStandard & standardize(const T &t)
Definition NTraits.h:538
static const THerm & transpose(const T &t)
Definition NTraits.h:519
static bool isNumericallyEqual(const T &a, const conjugate< R2 > &b)
Definition NTraits.h:566
C Scalar
Definition NTraits.h:466
static bool isFinite(const T &t)
Definition NTraits.h:556
static const T & getMinusOne()
Definition NTraits.h:581
static T * updData(T &t)
Definition NTraits.h:510
static ScalarNormSq scalarNormSqr(const T &t)
Definition NTraits.h:532
static const T & getPi()
Definition NTraits.h:592
static R & real(T &t)
Definition NTraits.h:512
static const T & getLn10()
Definition NTraits.h:604
conjugate< R > THerm
Definition NTraits.h:452
static const T & getThree()
Definition NTraits.h:583
static const T * getData(const T &t)
Definition NTraits.h:509
static bool isInf(const T &t)
Definition NTraits.h:558
static bool isNumericallyEqual(const T &a, const double &b, double tol)
Definition NTraits.h:574
static const TWithoutNegator & castAwayNegatorIfAny(const T &t)
Definition NTraits.h:527
static bool isNumericallyEqual(const T &a, int b, double tol)
Definition NTraits.h:576
static const T & getOneFourth()
Definition NTraits.h:586
R TImag
Definition NTraits.h:450
C StdNumber
Definition NTraits.h:469
C TStandard
Definition NTraits.h:462
static const T & getNaN()
Definition NTraits.h:542
static TNormalize normalize(const T &t)
Definition NTraits.h:539
static TPosTrans & positionalTranspose(T &t)
Definition NTraits.h:524
static const T & getTwo()
Definition NTraits.h:582
static bool isNaN(const T &t)
Definition NTraits.h:557
static const T & getOneOverSqrt3()
Definition NTraits.h:600
negator< C > TNeg
Definition NTraits.h:446
C Number
Definition NTraits.h:468
static const T & getOne()
Definition NTraits.h:580
static const T & getCubeRoot3()
Definition NTraits.h:602
C TComplex
Definition NTraits.h:451
static const T & getLog2E()
Definition NTraits.h:595
C TElement
Definition NTraits.h:456
static const T & getOneFifth()
Definition NTraits.h:587
static TSqrt sqrt(const T &t)
Definition NTraits.h:534
C TSqrt
Definition NTraits.h:460
static const T & getInfinity()
Definition NTraits.h:546
R Precision
Definition NTraits.h:470
C TInvert
Definition NTraits.h:463
static bool isNumericallyEqual(const T &a, const float &b, double tol)
Definition NTraits.h:572
static const TNeg & negate(const T &t)
Definition NTraits.h:516
static const T & getLog10E()
Definition NTraits.h:596
static const T & getOneNinth()
Definition NTraits.h:591
static double getDefaultTolerance()
Definition NTraits.h:560
static const T & getOneOverSqrt2()
Definition NTraits.h:598
C TWithoutNegator
Definition NTraits.h:447
static TWithoutNegator & updCastAwayNegatorIfAny(T &t)
Definition NTraits.h:529
R TAbs
Definition NTraits.h:461
C TPosTrans
Definition NTraits.h:453
static const T & getZero()
Definition NTraits.h:579
R TSqHermT
Definition NTraits.h:454
static const T & getSqrt3()
Definition NTraits.h:599
static const T & getOneSeventh()
Definition NTraits.h:589
static const T & getOneEighth()
Definition NTraits.h:590
static bool isNumericallyEqual(const T &a, const complex< R2 > &b, double tol)
Definition NTraits.h:564
C TRow
Definition NTraits.h:457
static bool isNumericallyEqual(const T &a, const float &b)
Definition NTraits.h:571
R TReal
Definition NTraits.h:449
conjugate< R > TInvert
Definition NTraits.h:649
static ScalarNormSq scalarNormSqr(const T &t)
Definition NTraits.h:718
static bool isNumericallyEqual(const T &a, const float &b)
Definition NTraits.h:767
conjugate< R > T
Definition NTraits.h:632
static const T & getTwo()
Definition NTraits.h:778
static const T & getOneThird()
Definition NTraits.h:781
conjugate< R > Scalar
Definition NTraits.h:652
static bool isFinite(const T &t)
Definition NTraits.h:752
static bool isNumericallyEqual(const T &a, const float &b, double tol)
Definition NTraits.h:768
static TReal & real(T &t)
Definition NTraits.h:698
static const T & getLog2E()
Definition NTraits.h:791
conjugate< R > TCol
Definition NTraits.h:644
static const T & getNaN()
Definition NTraits.h:735
static const TReal & real(const T &t)
Definition NTraits.h:697
conjugate< R > TElement
Definition NTraits.h:642
static const T & getOneFifth()
Definition NTraits.h:783
conjugate< R > TPosTrans
Definition NTraits.h:639
conjugate< R > TNormalize
Definition NTraits.h:650
static const T & getOneSeventh()
Definition NTraits.h:785
static TInvert invert(const T &t)
Definition NTraits.h:729
static const TImag & imag(const T &t)
Definition NTraits.h:699
static const T & getCubeRoot3()
Definition NTraits.h:798
static TPosTrans & positionalTranspose(T &t)
Definition NTraits.h:710
static const T & getOneEighth()
Definition NTraits.h:786
static const T & getOne()
Definition NTraits.h:776
static const T & getZero()
Definition NTraits.h:775
static const T & getOneOverSqrt3()
Definition NTraits.h:796
static const T & getSqrt3()
Definition NTraits.h:795
static const TPosTrans & positionalTranspose(const T &t)
Definition NTraits.h:708
conjugate< R > ULessScalar
Definition NTraits.h:653
static bool isNumericallyEqual(const T &a, const complex< R2 > &b)
Definition NTraits.h:762
static TSqrt sqrt(const T &t)
Definition NTraits.h:720
static TImag & imag(T &t)
Definition NTraits.h:700
static const T & getOneSixth()
Definition NTraits.h:784
conjugate< R > Number
Definition NTraits.h:654
static bool isNumericallyEqual(const T &a, int b)
Definition NTraits.h:771
static const TNeg & negate(const T &t)
Definition NTraits.h:702
static const TWithoutNegator & castAwayNegatorIfAny(const T &t)
Definition NTraits.h:713
static const T & getMinusOne()
Definition NTraits.h:777
R Precision
Definition NTraits.h:656
static const T & getPi()
Definition NTraits.h:788
static const T * getData(const T &t)
Definition NTraits.h:695
static const T & getLn2()
Definition NTraits.h:799
R TAbs
Definition NTraits.h:647
static const T & getOneNinth()
Definition NTraits.h:787
static const T & getInfinity()
Definition NTraits.h:741
static bool isNumericallyEqual(const T &a, const double &b)
Definition NTraits.h:769
static TAbs abs(const T &t)
Definition NTraits.h:722
R ScalarNormSq
Definition NTraits.h:657
static const T & getOneHalf()
Definition NTraits.h:780
complex< R > THerm
Definition NTraits.h:638
conjugate< R > TRow
Definition NTraits.h:643
static T * updData(T &t)
Definition NTraits.h:696
static const T & getLn10()
Definition NTraits.h:800
static bool isNumericallyEqual(const T &a, const conjugate< R2 > &b, double tol)
Definition NTraits.h:760
static const THerm & transpose(const T &t)
Definition NTraits.h:705
R TSqHermT
Definition NTraits.h:640
static TStandard standardize(const T &t)
Definition NTraits.h:724
static const T & getE()
Definition NTraits.h:790
static bool isNaN(const T &t)
Definition NTraits.h:753
static bool isNumericallyEqual(const T &a, const double &b, double tol)
Definition NTraits.h:770
complex< R > TStandard
Definition NTraits.h:648
conjugate< R > TWithoutNegator
Definition NTraits.h:634
static bool isNumericallyEqual(const T &a, const complex< R2 > &b, double tol)
Definition NTraits.h:764
R TSqTHerm
Definition NTraits.h:641
static bool isInf(const T &t)
Definition NTraits.h:754
static const T & getCubeRoot2()
Definition NTraits.h:797
R TReal
Definition NTraits.h:635
static double getDefaultTolerance()
Definition NTraits.h:756
complex< R > TSqrt
Definition NTraits.h:646
static const T & getOneOverPi()
Definition NTraits.h:789
static const T & getSqrt2()
Definition NTraits.h:793
static const T & getI()
Definition NTraits.h:747
static bool isNumericallyEqual(const T &a, int b, double tol)
Definition NTraits.h:772
static TNormalize normalize(const T &t)
Definition NTraits.h:726
static const T & getLog10E()
Definition NTraits.h:792
static TWithoutNegator & updCastAwayNegatorIfAny(T &t)
Definition NTraits.h:715
conjugate< R > TComplex
Definition NTraits.h:637
static const T & getOneFourth()
Definition NTraits.h:782
complex< R > StdNumber
Definition NTraits.h:655
static TNeg & negate(T &t)
Definition NTraits.h:703
static THerm & transpose(T &t)
Definition NTraits.h:706
static const T & getOneOverSqrt2()
Definition NTraits.h:794
negator< R > TImag
Definition NTraits.h:636
negator< T > TNeg
Definition NTraits.h:633
static bool isNumericallyEqual(const T &a, const conjugate< R2 > &b)
Definition NTraits.h:758
static const T & getThree()
Definition NTraits.h:779
Definition NTraits.h:436
static const double & getEps()
Definition NTraits.h:160
static const double & getSignificant()
Definition NTraits.h:161
static double getDefaultTolerance()
Definition NTraits.h:162
static const float & getEps()
Attainable accuracy at this precision.
Definition NTraits.h:152
static const float & getSignificant()
What multiple of attainable accuracy do we consider significant?
Definition NTraits.h:154
static double getDefaultTolerance()
The default numerical error tolerance is always given in double precision.
Definition NTraits.h:156
RTraits is a helper class for NTraits.
Definition NTraits.h:148
SimTK::conjugate<R> should be instantiated only for float, double.
Definition conjugate.h:178
negator<N>, where N is a number type (real, complex, conjugate), is represented in memory identically...
Definition negator.h:75
This is the top-level SimTK namespace into which all SimTK names are placed to avoid collision with o...
Definition Assembler.h:37
RowVectorBase< typename CNT< ELEM >::TAbs > abs(const RowVectorBase< ELEM > &v)
Definition VectorMath.h:120
bool isInf(const negator< float > &x)
Definition negator.h:298
@ SCALAR_DEPTH
Definition CompositeNumericalTypes.h:116
bool isNumericallyEqual(const float &a, const float &b, double tol=RTraits< float >::getDefaultTolerance())
Compare two floats for approximate equality.
Definition NTraits.h:293
bool isNaN(const negator< float > &x)
Definition negator.h:272
bool isFinite(const negator< float > &x)
Definition negator.h:285
CNT< typenameCNT< P >::THerm >::template Result< C >::Mul Dvd
Definition NTraits.h:481
CNT< P >::template Result< C >::Mul Mul
Definition NTraits.h:480
CNT< typenameCNT< P >::TNeg >::template Result< C >::Add Sub
Definition NTraits.h:483
CNT< P >::template Result< C >::Add Add
Definition NTraits.h:482
CNT< P >::template Result< T >::Add Add
Definition NTraits.h:667
CNT< typenameCNT< P >::TNeg >::template Result< T >::Add Sub
Definition NTraits.h:668
CNT< P >::template Result< T >::Mul Mul
Definition NTraits.h:665
CNT< typenameCNT< P >::THerm >::template Result< T >::Mul Dvd
Definition NTraits.h:666
Narrowest< R1, R2 >::Precision Precision
Definition NTraits.h:144
complex< typename Narrowest< R1, R2 >::Type > Type
Definition NTraits.h:143
complex< typename Narrowest< R1, R2 >::Type > Type
Definition NTraits.h:139
Narrowest< R1, R2 >::Precision Precision
Definition NTraits.h:140
Narrowest< R1, R2 >::Precision Precision
Definition NTraits.h:136
complex< typename Narrowest< R1, R2 >::Type > Type
Definition NTraits.h:135
double Type
Definition NTraits.h:133
double Precision
Definition NTraits.h:133
float Type
Definition NTraits.h:132
float Precision
Definition NTraits.h:132
float Type
Definition NTraits.h:131
float Precision
Definition NTraits.h:131
float Precision
Definition NTraits.h:130
float Type
Definition NTraits.h:130
This class is specialized for all 16 combinations of standard types (that is, real and complex types ...
Definition NTraits.h:129
Widest< R1, R2 >::Precision Precision
Definition NTraits.h:117
complex< typename Widest< R1, R2 >::Type > Type
Definition NTraits.h:116
complex< typename Widest< R1, R2 >::Type > Type
Definition NTraits.h:112
Widest< R1, R2 >::Precision Precision
Definition NTraits.h:113
complex< typename Widest< R1, R2 >::Type > Type
Definition NTraits.h:108
Widest< R1, R2 >::Precision Precision
Definition NTraits.h:109
double Precision
Definition NTraits.h:106
double Type
Definition NTraits.h:106
double Precision
Definition NTraits.h:105
double Type
Definition NTraits.h:105
double Precision
Definition NTraits.h:104
double Type
Definition NTraits.h:104
float Type
Definition NTraits.h:103
float Precision
Definition NTraits.h:103
This class is specialized for all 16 combinations of standard types (that is, real and complex types ...
Definition NTraits.h:102