Simbody 3.9
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 <bit>
54#include <cassert>
55#include <cmath>
56#include <complex>
57#include <cstddef>
58#include <cstdint>
59#include <limits>
60
61using std::complex;
62
63namespace SimTK::detail {
64// Consteval square root. Uses `std::sqrt` when `__cpp_lib_constexpr_cmath` is
65// available (C++23). Otherwise uses a Newton-Raphson solver, which may be
66// off by 1 ULP due to differences in rounding.
67consteval double consteval_sqrt(double x) noexcept {
68#if defined(__cpp_lib_constexpr_cmath) && __cpp_lib_constexpr_cmath >= 202202L
69 return std::sqrt(x); // In new C++es, just call `std::sqrt`.
70#else
71 static_assert(std::numeric_limits<double>::is_iec559);
72
73 constexpr double max_double = std::numeric_limits<double>::max();
74 constexpr double nan = std::numeric_limits<double>::quiet_NaN();
75
76 // Trivial/edge cases.
77 if (x != x) return x; // forward NaNs
78 if (x < 0.0) return nan; // sqrt(negative_number) -> NaN
79 if (x == 0.0) return x; // preserve -0 and +0
80 if (x > max_double) return x; // +inf
81
82 // Subnormal scaling.
83 double scale = 1.0;
84 if (x < std::numeric_limits<double>::min()) {
85 x *= 4503599627370496.0; // 2^52
86 scale = 1.0 / 67108864.0; // 2^-26
87 }
88
89 auto b = std::bit_cast<std::uint64_t>(x);
90 b = (b + (1023ULL << 52)) >> 1;
91 auto g = std::bit_cast<double>(b);
92
93 // Newton-Raphson solver: might be off by 1ULP
94 for (;;) {
95 const auto next = (g + x / g) * 0.5;
96 if (next >= g) break;
97 g = next;
98 }
99
100 return g * scale;
101#endif
102}
103}
104
105namespace SimTK {
106
107// This is the 3rd type of number, conjugate. It is like complex except that
108// the represented value is the conjugate of the value represented by a complex
109// number containing the same bit pattern. That is, complex and conjugate both
110// contain two real numbers, re and im, with complex(re,im) meaning
111// (re + im*i) while conjugate(re,im) means (re - im*i). It is guaranteed that
112// our conjugate type and complex type have identical sizes and representations.
113// Together, these defininitions and guarantees permit conjugation
114// to be done by reinterpretation rather than be computation.
115template <class R> class conjugate; // Only defined for float, double
116
117// Specializations of this class provide information about Composite Numerical
118// Types in the style of std::numeric_limits<T>. It is specialized for the
119// numeric types but can be invoked on any composite numerical type as well.
120template <class T> class CNT;
121
122// NTraits provides information like CNT, but for numeric types only.
123template <class N> class NTraits; // allowed only for N=<number>
124template <class R> class NTraits< complex<R> >;
125template <class R> class NTraits< conjugate<R> >;
126template <> class NTraits<float>;
127template <> class NTraits<double>;
128
129// This is an adaptor for numeric types which negates the apparent values. A
130// negator<N> has exactly the same internal representation as a numeric value N,
131// but it is to be interpreted has having the negative of the value it would
132// have if interpreted as an N. This permits negation to be done by
133// reinterpretation rather than computation. A full set of arithmetic operators
134// are provided involving negator<N>'s and N's. Sometimes we can save an op or
135// two this way. For example negator<N>*negator<N> can be performed as an N*N
136// since the negations cancel, and we saved two floating point negations.
137template <class N> class negator; // Only defined for numbers
138
146template <class R1, class R2> struct Widest {/* Only defined for built-ins. */};
147template <> struct Widest<float,float> {typedef float Type; typedef float Precision;};
148template <> struct Widest<float,double> {typedef double Type; typedef double Precision;};
149template <> struct Widest<double,float> {typedef double Type; typedef double Precision;};
150template <> struct Widest<double,double> {typedef double Type; typedef double Precision;};
151template <class R1, class R2> struct Widest< complex<R1>,complex<R2> > {
152 typedef complex< typename Widest<R1,R2>::Type > Type;
154};
155template <class R1, class R2> struct Widest< complex<R1>,R2 > {
156 typedef complex< typename Widest<R1,R2>::Type > Type;
158};
159template <class R1, class R2> struct Widest< R1,complex<R2> > {
160 typedef complex< typename Widest<R1,R2>::Type > Type;
162};
163
173template <class R1, class R2> struct Narrowest {/* Only defined for built-ins. */};
174template <> struct Narrowest<float,float> {typedef float Type; typedef float Precision;};
175template <> struct Narrowest<float,double> {typedef float Type; typedef float Precision;};
176template <> struct Narrowest<double,float> {typedef float Type; typedef float Precision;};
177template <> struct Narrowest<double,double> {typedef double Type; typedef double Precision;};
178template <class R1, class R2> struct Narrowest< complex<R1>,complex<R2> > {
179 typedef complex< typename Narrowest<R1,R2>::Type > Type;
181};
182template <class R1, class R2> struct Narrowest< complex<R1>,R2 > {
183 typedef complex< typename Narrowest<R1,R2>::Type > Type;
185};
186template <class R1, class R2> struct Narrowest< R1,complex<R2> > {
187 typedef complex< typename Narrowest<R1,R2>::Type > Type;
189};
190
192template <class R> class RTraits {/* Only defined for real types */};
193template <> class RTraits<float> {
194public:
196 static constexpr float getEps() {return std::numeric_limits<float>::epsilon();}
198 static constexpr float getSignificant() {
199 // Three nested square roots compute x / x^(1/8) = x^(7/8) = x^0.875
201 }
203 static constexpr double getDefaultTolerance() {return static_cast<double>(getSignificant());}
204};
205template <> class RTraits<double> {
206public:
207 static constexpr double getEps() {return std::numeric_limits<double>::epsilon();}
208 static constexpr double getSignificant() {
209 // Three nested square roots compute x / x^(1/8) = x^(7/8) = x^0.875
211 }
212 static constexpr double getDefaultTolerance() {return getSignificant();}
213};
214
231// See negator.h for isNaN() applied to negated scalars.
233inline bool isNaN(const float& x) {return std::isnan(x);}
234inline bool isNaN(const double& x) {return std::isnan(x);}
235
236template <class P> inline bool
237isNaN(const std::complex<P>& x)
238{ return isNaN(x.real()) || isNaN(x.imag());}
239
240template <class P> inline bool
242{ return isNaN(x.real()) || isNaN(x.negImag());}
244
257// See negator.h for isFinite() applied to negated scalars.
259inline bool isFinite(const float& x) {return std::isfinite(x);}
260inline bool isFinite(const double& x) {return std::isfinite(x);}
261
262template <class P> inline bool
263isFinite(const std::complex<P>& x)
264{ return isFinite(x.real()) && isFinite(x.imag());}
265
266template <class P> inline bool
268{ return isFinite(x.real()) && isFinite(x.negImag());}
270
285// See negator.h for isInf() applied to negated scalars.
287inline bool isInf(const float& x) {return std::isinf(x);}
288inline bool isInf(const double& x) {return std::isinf(x);}
289
290template <class P> inline bool
291isInf(const std::complex<P>& x) {
292 return (isInf(x.real()) && !isNaN(x.imag()))
293 || (isInf(x.imag()) && !isNaN(x.real()));
294}
295
296template <class P> inline bool
298 return (isInf(x.real()) && !isNaN(x.negImag()))
299 || (isInf(x.negImag()) && !isNaN(x.real()));
300}
302
343inline bool isNumericallyEqual(const float& a, const float& b,
345{ if (isNaN(a)) return isNaN(b); else if (isNaN(b)) return false;
346 const float scale = std::max(std::max(std::abs(a),std::abs(b)), 1.f);
347 return std::abs(a-b) <= scale*(float)tol; }
349inline bool isNumericallyEqual(const double& a, const double& b,
351{ if (isNaN(a)) return isNaN(b); else if (isNaN(b)) return false;
352 const double scale = std::max(std::max(std::abs(a),std::abs(b)), 1.);
353 return std::abs(a-b) <= scale*tol; }
354
356inline bool isNumericallyEqual(const float& a, const double& b,
358{ return isNumericallyEqual((double)a, b, tol); }
360inline bool isNumericallyEqual(const double& a, const float& b,
362{ return isNumericallyEqual(a, (double)b, tol); }
363
365inline bool isNumericallyEqual(const float& a, int b,
367{ return isNumericallyEqual(a, (double)b, tol); }
369inline bool isNumericallyEqual(int a, const float& b,
371{ return isNumericallyEqual((double)a, b, tol); }
373inline bool isNumericallyEqual(const double& a, int b,
375{ return isNumericallyEqual(a, (double)b, tol); }
377inline bool isNumericallyEqual(int a, const double& b,
379{ return isNumericallyEqual((double)a, b, tol); }
380
384template <class P, class Q>
386 ( const std::complex<P>& a, const std::complex<Q>& b,
387 double tol = RTraits<typename Narrowest<P,Q>::Precision>::getDefaultTolerance())
388{ return isNumericallyEqual(a.real(),b.real(),tol)
389 && isNumericallyEqual(a.imag(),b.imag(),tol); }
390
394template <class P, class Q>
396 ( const conjugate<P>& a, const conjugate<Q>& b,
397 double tol = RTraits<typename Narrowest<P,Q>::Precision>::getDefaultTolerance())
398{ return isNumericallyEqual(a.real(),b.real(),tol)
399 && isNumericallyEqual(a.imag(),b.imag(),tol); }
400
404template <class P, class Q>
406 ( const std::complex<P>& a, const conjugate<Q>& b,
407 double tol = RTraits<typename Narrowest<P,Q>::Precision>::getDefaultTolerance())
408{ return isNumericallyEqual(a.real(),b.real(),tol)
409 && isNumericallyEqual(a.imag(),b.imag(),tol); }
410
414template <class P, class Q>
416 ( const conjugate<P>& a, const std::complex<Q>& b,
417 double tol = RTraits<typename Narrowest<P,Q>::Precision>::getDefaultTolerance())
418{ return isNumericallyEqual(a.real(),b.real(),tol)
419 && isNumericallyEqual(a.imag(),b.imag(),tol); }
420
422template <class P> inline bool
423isNumericallyEqual(const std::complex<P>& a, const float& b,
425{ return isNumericallyEqual(a.real(),b,tol) && isNumericallyEqual(a.imag(),0.f,tol); }
427template <class P> inline bool
428isNumericallyEqual(const float& a, const std::complex<P>& b,
430{ return isNumericallyEqual(b,a,tol); }
432template <class P> inline bool
433isNumericallyEqual(const std::complex<P>& a, const double& b,
434 double tol = RTraits<typename Narrowest<P,double>::Precision>::getDefaultTolerance())
435{ return isNumericallyEqual(a.real(),b,tol) && isNumericallyEqual(a.imag(),0.,tol); }
437template <class P> inline bool
438isNumericallyEqual(const double& a, const std::complex<P>& b,
439 double tol = RTraits<typename Narrowest<P,double>::Precision>::getDefaultTolerance())
440{ return isNumericallyEqual(b,a,tol); }
442template <class P> inline bool
443isNumericallyEqual(const std::complex<P>& a, int b,
444 double tol = RTraits<P>::getDefaultTolerance())
445{ typedef typename Widest<P,double>::Precision W; return isNumericallyEqual(a,(W)b,tol); }
447template <class P> inline bool
448isNumericallyEqual(int a, const std::complex<P>& b,
449 double tol = RTraits<P>::getDefaultTolerance())
450{ return isNumericallyEqual(b,a,tol); }
451
453template <class P> inline bool
454isNumericallyEqual(const conjugate<P>& a, const float& b,
456{ return isNumericallyEqual(a.real(),b,tol) && isNumericallyEqual(a.imag(),0.f,tol); }
458template <class P> inline bool
459isNumericallyEqual(const float& a, const conjugate<P>& b,
461{ return isNumericallyEqual(b,a,tol); }
463template <class P> inline bool
464isNumericallyEqual(const conjugate<P>& a, const double& b,
465 double tol = RTraits<typename Narrowest<P,double>::Precision>::getDefaultTolerance())
466{ return isNumericallyEqual(a.real(),b,tol) && isNumericallyEqual(a.imag(),0.,tol); }
468template <class P> inline bool
469isNumericallyEqual(const double& a, const conjugate<P>& b,
470 double tol = RTraits<typename Narrowest<P,double>::Precision>::getDefaultTolerance())
471{ return isNumericallyEqual(b,a,tol); }
473template <class P> inline bool
475 double tol = RTraits<P>::getDefaultTolerance())
476{ typedef typename Widest<P,double>::Precision W; return isNumericallyEqual(a,(W)b,tol); }
478template <class P> inline bool
480 double tol = RTraits<P>::getDefaultTolerance())
481{ return isNumericallyEqual(b,a,tol); }
482
484
485
486template <class N> class NTraits {
487 // only the specializations below are allowed
488};
489
492template <class R> class NTraits< complex<R> > {
493 typedef complex<R> C;
494public:
495 typedef C T;
496 typedef negator<C> TNeg; // type of this after *cast* to its negative
497 typedef C TWithoutNegator; // type of this ignoring negator (there isn't one!)
498
499 typedef R TReal;
500 typedef R TImag;
501 typedef C TComplex;
502 typedef conjugate<R> THerm; // this is a recast
503 typedef C TPosTrans;
504 typedef R TSqHermT; // ~C*C
505 typedef R TSqTHerm; // C*~C (same)
506 typedef C TElement;
507 typedef C TRow;
508 typedef C TCol;
509
510 typedef C TSqrt;
511 typedef R TAbs;
512 typedef C TStandard; // complex is a standard type
513 typedef C TInvert; // this is a calculation, so use standard number
514 typedef C TNormalize;
515
516 typedef C Scalar;
517 typedef C ULessScalar;
518 typedef C Number;
519 typedef C StdNumber;
520 typedef R Precision;
521 typedef R ScalarNormSq;
522
523 // For complex scalar C, op result types are:
524 // Typeof(C*P) = Typeof(P*C)
525 // Typeof(C/P) = Typeof(inv(P)*C)
526 // Typeof(C+P) = Typeof(P+C)
527 // typeof(C-P) = Typeof(P::TNeg + C)
528 // These must be specialized for P=real, complex, conjugate.
529 template <class P> struct Result {
531 typedef typename CNT< typename CNT<P>::THerm >::template Result<C>::Mul Dvd;
533 typedef typename CNT< typename CNT<P>::TNeg >::template Result<C>::Add Sub;
534 };
535
536 // Shape-preserving element substitution (easy for scalars!)
537 template <class P> struct Substitute {
538 typedef P Type;
539 };
540
541 enum {
542 NRows = 1,
543 NCols = 1,
544 RowSpacing = 1,
545 ColSpacing = 1,
546 NPackedElements = 1, // not two!
547 NActualElements = 1,
548 NActualScalars = 1,
549 ImagOffset = 1,
550 RealStrideFactor = 2, // double stride when casting to real or imaginary
551 ArgDepth = SCALAR_DEPTH,
552 IsScalar = 1,
553 IsULessScalar = 1,
554 IsNumber = 1,
555 IsStdNumber = 1,
556 IsPrecision = 0,
557 SignInterpretation = 1 // after cast to Number, what is the sign?
558 };
559 static const T* getData(const T& t) { return &t; }
560 static T* updData(T& t) { return &t; }
561 static const R& real(const T& t) { return (reinterpret_cast<const R*>(&t))[0]; }
562 static R& real(T& t) { return (reinterpret_cast<R*>(&t))[0]; }
563 static const R& imag(const T& t) { return (reinterpret_cast<const R*>(&t))[1]; }
564 static R& imag(T& t) { return (reinterpret_cast<R*>(&t))[1]; }
565
566 static const TNeg& negate(const T& t) {return reinterpret_cast<const TNeg&>(t);}
567 static TNeg& negate(T& t) {return reinterpret_cast<TNeg&>(t);}
568
569 static const THerm& transpose(const T& t) {return reinterpret_cast<const THerm&>(t);}
570 static THerm& transpose(T& t) {return reinterpret_cast<THerm&>(t);}
571
572 static const TPosTrans& positionalTranspose(const T& t)
573 {return reinterpret_cast<const TPosTrans&>(t);}
575 {return reinterpret_cast<TPosTrans&>(t);}
576
577 static const TWithoutNegator& castAwayNegatorIfAny(const T& t)
578 {return reinterpret_cast<const TWithoutNegator&>(t);}
580 {return reinterpret_cast<TWithoutNegator&>(t);}
581
582 static ScalarNormSq scalarNormSqr(const T& t)
583 { return t.real()*t.real() + t.imag()*t.imag(); }
584 static TSqrt sqrt(const T& t)
585 { return std::sqrt(t); }
586 static TAbs abs(const T& t)
587 { return std::abs(t); } // no, not just sqrt of scalarNormSqr()!
588 static const TStandard& standardize(const T& t) {return t;} // already standard
589 static TNormalize normalize(const T& t) {return t/abs(t);}
590 static TInvert invert(const T& t) {return TReal(1)/t;}
591
592 static constexpr T getNaN() {return T(NTraits<R>::getNaN(), NTraits<R>::getNaN());}
594
595 static constexpr T getI() {return T(0,1);}
596
597 static bool isFinite(const T& t) {return SimTK::isFinite(t);}
598 static bool isNaN(const T& t) {return SimTK::isNaN(t);}
599 static bool isInf(const T& t) {return SimTK::isInf(t);}
600
602
603 template <class R2> static bool isNumericallyEqual(const T& a, const complex<R2>& b)
604 { return SimTK::isNumericallyEqual(a,b); }
605 template <class R2> static bool isNumericallyEqual(const T& a, const complex<R2>& b, double tol)
606 { return SimTK::isNumericallyEqual(a,b,tol); }
607 template <class R2> static bool isNumericallyEqual(const T& a, const conjugate<R2>& b)
608 { return SimTK::isNumericallyEqual(a,b); }
609 template <class R2> static bool isNumericallyEqual(const T& a, const conjugate<R2>& b, double tol)
610 { return SimTK::isNumericallyEqual(a,b,tol); }
611
612 static bool isNumericallyEqual(const T& a, const float& b) {return SimTK::isNumericallyEqual(a,b);}
613 static bool isNumericallyEqual(const T& a, const float& b, double tol) {return SimTK::isNumericallyEqual(a,b,tol);}
614 static bool isNumericallyEqual(const T& a, const double& b) {return SimTK::isNumericallyEqual(a,b);}
615 static bool isNumericallyEqual(const T& a, const double& b, double tol) {return SimTK::isNumericallyEqual(a,b,tol);}
616 static bool isNumericallyEqual(const T& a, int b) {return SimTK::isNumericallyEqual(a,b);}
617 static bool isNumericallyEqual(const T& a, int b, double tol) {return SimTK::isNumericallyEqual(a,b,tol);}
618
619 // The rest are the same as the real equivalents, with zero imaginary part.
620 static constexpr T getZero() {return T(NTraits<R>::getZero()); }
621 static constexpr T getOne() {return T(NTraits<R>::getOne()); }
622 static constexpr T getMinusOne() {return T(NTraits<R>::getMinusOne()); }
623 static constexpr T getTwo() {return T(NTraits<R>::getTwo()); }
624 static constexpr T getThree() {return T(NTraits<R>::getThree()); }
625 static constexpr T getOneHalf() {return T(NTraits<R>::getOneHalf()); }
626 static constexpr T getOneThird() {return T(NTraits<R>::getOneThird()); }
627 static constexpr T getOneFourth() {return T(NTraits<R>::getOneFourth()); }
628 static constexpr T getOneFifth() {return T(NTraits<R>::getOneFifth()); }
629 static constexpr T getOneSixth() {return T(NTraits<R>::getOneSixth()); }
630 static constexpr T getOneSeventh() {return T(NTraits<R>::getOneSeventh()); }
631 static constexpr T getOneEighth() {return T(NTraits<R>::getOneEighth()); }
632 static constexpr T getOneNinth() {return T(NTraits<R>::getOneNinth()); }
633 static constexpr T getPi() {return T(NTraits<R>::getPi()); }
634 static constexpr T getOneOverPi() {return T(NTraits<R>::getOneOverPi()); }
635 static constexpr T getE() {return T(NTraits<R>::getE()); }
636 static constexpr T getLog2E() {return T(NTraits<R>::getLog2E()); }
637 static constexpr T getLog10E() {return T(NTraits<R>::getLog10E()); }
638 static constexpr T getSqrt2() {return T(NTraits<R>::getSqrt2()); }
639 static constexpr T getOneOverSqrt2() {return T(NTraits<R>::getOneOverSqrt2()); }
640 static constexpr T getSqrt3() {return T(NTraits<R>::getSqrt3()); }
641 static constexpr T getOneOverSqrt3() {return T(NTraits<R>::getOneOverSqrt3()); }
642 static constexpr T getCubeRoot2() {return T(NTraits<R>::getCubeRoot2()); }
643 static constexpr T getCubeRoot3() {return T(NTraits<R>::getCubeRoot3()); }
644 static constexpr T getLn2() {return T(NTraits<R>::getLn2()); }
645 static constexpr T getLn10() {return T(NTraits<R>::getLn10()); }
646};
647
648
649// Specialize NTraits<complex>::Results for <complex> OP <scalar>. Result type is
650// always just the complex type of sufficient precision.
651#define SimTK_BNTCMPLX_SPEC(T1,T2) \
652template<> template<> struct NTraits< complex<T1> >::Result<T2> { \
653 typedef Widest< complex<T1>,T2 >::Type W; \
654 typedef W Mul; typedef W Dvd; typedef W Add; typedef W Sub; \
655}; \
656template<> template<> struct NTraits< complex<T1> >::Result< complex<T2> > { \
657 typedef Widest< complex<T1>,complex<T2> >::Type W; \
658 typedef W Mul; typedef W Dvd; typedef W Add; typedef W Sub; \
659}; \
660template<> template<> struct NTraits< complex<T1> >::Result< conjugate<T2> > { \
661 typedef Widest< complex<T1>,complex<T2> >::Type W; \
662 typedef W Mul; typedef W Dvd; typedef W Add; typedef W Sub; \
663}
664SimTK_BNTCMPLX_SPEC(float,float);SimTK_BNTCMPLX_SPEC(float,double);
665SimTK_BNTCMPLX_SPEC(double,float);SimTK_BNTCMPLX_SPEC(double,double);
666#undef SimTK_BNTCMPLX_SPEC
667
668
669// conjugate -- should be instantiated only for float, double.
670template <class R> class NTraits< conjugate<R> > {
671 typedef complex<R> C;
672public:
674 typedef negator<T> TNeg; // type of this after *cast* to its negative
675 typedef conjugate<R> TWithoutNegator; // type of this ignoring negator (there isn't one!)
676 typedef R TReal;
679 typedef complex<R> THerm; // conjugate evaporates
680 typedef conjugate<R> TPosTrans; // Positional transpose of scalar does nothing
681 typedef R TSqHermT; // C*C~
682 typedef R TSqTHerm; // ~C*C (same)
686
687 typedef complex<R> TSqrt;
688 typedef R TAbs;
689 typedef complex<R> TStandard;
692
696 typedef complex<R> StdNumber;
697 typedef R Precision;
698 typedef R ScalarNormSq;
699
700 // Typeof( Conj<S>*P ) is Typeof(P*Conj<S>)
701 // Typeof( Conj<S>/P ) is Typeof(inv(P)*Conj<S>)
702 // Typeof( Conj<S>+P ) is Typeof(P+Conj<S>)
703 // Typeof( Conj<S>-P ) is Typeof(P::TNeg+Conj<S>)
704 // Must specialize for P=real or P=complex or P=conjugate
705 template <class P> struct Result {
707 typedef typename CNT<typename CNT<P>::THerm>::template Result<T>::Mul Dvd;
709 typedef typename CNT<typename CNT<P>::TNeg>::template Result<T>::Add Sub;
710 };
711
712 // Shape-preserving element substitution (easy for scalars!)
713 template <class P> struct Substitute {
714 typedef P Type;
715 };
716
717 enum {
718 NRows = 1,
719 NCols = 1,
720 RowSpacing = 1,
721 ColSpacing = 1,
722 NPackedElements = 1, // not two!
723 NActualElements = 1,
724 NActualScalars = 1,
725 ImagOffset = 1,
726 RealStrideFactor = 2, // double stride when casting to real or imaginary
727 ArgDepth = SCALAR_DEPTH,
728 IsScalar = 1,
729 IsULessScalar = 1,
730 IsNumber = 1,
731 IsStdNumber = 0,
732 IsPrecision = 0,
733 SignInterpretation = 1 // after cast to Number, what is the sign?
734 };
735
736 static const T* getData(const T& t) { return &t; }
737 static T* updData(T& t) { return &t; }
738 static const TReal& real(const T& t) { return t.real(); }
739 static TReal& real(T& t) { return t.real(); }
740 static const TImag& imag(const T& t) { return t.imag(); }
741 static TImag& imag(T& t) { return t.imag(); }
742
743 static const TNeg& negate(const T& t) {return reinterpret_cast<const TNeg&>(t);}
744 static TNeg& negate(T& t) {return reinterpret_cast<TNeg&>(t);}
745
746 static const THerm& transpose(const T& t) {return t.conj();}
747 static THerm& transpose(T& t) {return t.conj();}
748
749 static const TPosTrans& positionalTranspose(const T& t)
750 {return reinterpret_cast<const TPosTrans&>(t);}
752 {return reinterpret_cast<TPosTrans&>(t);}
753
754 static const TWithoutNegator& castAwayNegatorIfAny(const T& t)
755 {return reinterpret_cast<const TWithoutNegator&>(t);}
757 {return reinterpret_cast<TWithoutNegator&>(t);}
758
759 static ScalarNormSq scalarNormSqr(const T& t)
760 { return t.real()*t.real() + t.negImag()*t.negImag(); }
761 static TSqrt sqrt(const T& t)
762 { return std::sqrt(C(t)); } // cast to complex (one negation)
763 static TAbs abs(const T& t)
764 { return std::abs(t.conj()); } // no, not just sqrt of scalarNormSqr()!
765 static TStandard standardize(const T& t)
766 { return TStandard(t); } // i.e., convert to complex
767 static TNormalize normalize(const T& t) {return TNormalize(t/abs(t));}
768
769 // 1/conj(z) = conj(1/z), for complex z.
770 static TInvert invert(const T& t)
771 { const typename NTraits<THerm>::TInvert cmplx(NTraits<THerm>::invert(t.conj()));
772 return reinterpret_cast<const TInvert&>(cmplx); } // recast complex to conjugate it
773
774 // We want a "conjugate NaN", NaN - NaN*i, meaning both reals should
775 // be positive NaN.
776 static constexpr T getNaN() {return T(NTraits<R>::getNaN(),NTraits<R>::getNaN());}
777 // We want a "conjugate infinity", Inf - Inf*i, meaning both stored reals
778 // are positive Inf.
780 // But we want the constant i (=sqrt(-1)) to be the same however we represent it,
781 // so for conjugate i = 0 - (-1)i.
782 static constexpr T getI() {return T(0,-1);}
783
784 static bool isFinite(const T& t) {return SimTK::isFinite(t);}
785 static bool isNaN(const T& t) {return SimTK::isNaN(t);}
786 static bool isInf(const T& t) {return SimTK::isInf(t);}
787
789
790 template <class R2> static bool isNumericallyEqual(const T& a, const conjugate<R2>& b)
791 { return SimTK::isNumericallyEqual(a,b); }
792 template <class R2> static bool isNumericallyEqual(const T& a, const conjugate<R2>& b, double tol)
793 { return SimTK::isNumericallyEqual(a,b,tol); }
794 template <class R2> static bool isNumericallyEqual(const T& a, const complex<R2>& b)
795 { return SimTK::isNumericallyEqual(a,b); }
796 template <class R2> static bool isNumericallyEqual(const T& a, const complex<R2>& b, double tol)
797 { return SimTK::isNumericallyEqual(a,b,tol); }
798
799 static bool isNumericallyEqual(const T& a, const float& b) {return SimTK::isNumericallyEqual(a,b);}
800 static bool isNumericallyEqual(const T& a, const float& b, double tol) {return SimTK::isNumericallyEqual(a,b,tol);}
801 static bool isNumericallyEqual(const T& a, const double& b) {return SimTK::isNumericallyEqual(a,b);}
802 static bool isNumericallyEqual(const T& a, const double& b, double tol) {return SimTK::isNumericallyEqual(a,b,tol);}
803 static bool isNumericallyEqual(const T& a, int b) {return SimTK::isNumericallyEqual(a,b);}
804 static bool isNumericallyEqual(const T& a, int b, double tol) {return SimTK::isNumericallyEqual(a,b,tol);}
805
806 // The rest are the same as the real equivalents, with zero imaginary part.
807 static constexpr T getZero() {return T(NTraits<R>::getZero()); }
808 static constexpr T getOne() {return T(NTraits<R>::getOne()); }
809 static constexpr T getMinusOne() {return T(NTraits<R>::getMinusOne()); }
810 static constexpr T getTwo() {return T(NTraits<R>::getTwo()); }
811 static constexpr T getThree() {return T(NTraits<R>::getThree()); }
812 static constexpr T getOneHalf() {return T(NTraits<R>::getOneHalf()); }
813 static constexpr T getOneThird() {return T(NTraits<R>::getOneThird()); }
814 static constexpr T getOneFourth() {return T(NTraits<R>::getOneFourth()); }
815 static constexpr T getOneFifth() {return T(NTraits<R>::getOneFifth()); }
816 static constexpr T getOneSixth() {return T(NTraits<R>::getOneSixth()); }
817 static constexpr T getOneSeventh() {return T(NTraits<R>::getOneSeventh()); }
818 static constexpr T getOneEighth() {return T(NTraits<R>::getOneEighth()); }
819 static constexpr T getOneNinth() {return T(NTraits<R>::getOneNinth()); }
820 static constexpr T getPi() {return T(NTraits<R>::getPi()); }
821 static constexpr T getOneOverPi() {return T(NTraits<R>::getOneOverPi()); }
822 static constexpr T getE() {return T(NTraits<R>::getE()); }
823 static constexpr T getLog2E() {return T(NTraits<R>::getLog2E()); }
824 static constexpr T getLog10E() {return T(NTraits<R>::getLog10E()); }
825 static constexpr T getSqrt2() {return T(NTraits<R>::getSqrt2()); }
826 static constexpr T getOneOverSqrt2() {return T(NTraits<R>::getOneOverSqrt2()); }
827 static constexpr T getSqrt3() {return T(NTraits<R>::getSqrt3()); }
828 static constexpr T getOneOverSqrt3() {return T(NTraits<R>::getOneOverSqrt3()); }
829 static constexpr T getCubeRoot2() {return T(NTraits<R>::getCubeRoot2()); }
830 static constexpr T getCubeRoot3() {return T(NTraits<R>::getCubeRoot3()); }
831 static constexpr T getLn2() {return T(NTraits<R>::getLn2()); }
832 static constexpr T getLn10() {return T(NTraits<R>::getLn10()); }
833};
834
835// Any op involving conjugate & a real is best left as a conjugate. However,
836// an op involving conjugate & a complex or conjugate can lose the conjugate at zero cost
837// and return just a complex in some cases. Also, we prefer negator<complex> to conjugate.
838//
839// Conj op complex
840// a-bi * r+si = (ar+bs) + (as-br)i (complex)
841// a-bi / r+si = hairy and slow anyway; we'll convert to complex
842// a-bi + r+si = (a+r) + (s-b)i (complex)
843// a-bi - r+si = (a-r) - (b+s)i = -[(r-a)+(b+s)i] (negator<complex>)
844//
845// Conj op Conj
846// a-bi * r-si = (ar-bs) - (as+br)i = -[(bs-ar)+(as+br)i] (negator<complex>)
847// a-bi / r-si = hairy and slow anyway; we'll convert to complex
848// a-bi + r-si = (a+r) - (b+s)i (conjugate)
849// a-bi - r-si = (a-r) + (s-b)i (complex)
850
851#define SimTK_NTRAITS_CONJ_SPEC(T1,T2) \
852template<> template<> struct NTraits< conjugate<T1> >::Result<T2> { \
853 typedef conjugate<Widest<T1,T2>::Type> W; \
854 typedef W Mul; typedef W Dvd; typedef W Add; typedef W Sub; \
855}; \
856template<> template<> struct NTraits< conjugate<T1> >::Result<complex<T2> >{\
857 typedef Widest<complex<T1>,complex<T2> >::Type W; \
858 typedef W Mul; typedef W Dvd; typedef W Add; typedef negator<W> Sub; \
859}; \
860template<> template<> struct NTraits< conjugate<T1> >::Result<conjugate<T2> >{\
861 typedef Widest<T1,T2>::Type W; typedef complex<W> WC; \
862 typedef negator<WC> Mul; typedef WC Dvd; typedef conjugate<W> Add; typedef WC Sub;\
863}
866#undef SimTK_NTRAITS_CONJ_SPEC
867
868// Specializations for real numbers.
869// For real scalar R, op result types are:
870// Typeof(R*P) = Typeof(P*R)
871// Typeof(R/P) = Typeof(inv(P)*R)
872// Typeof(R+P) = Typeof(P+R)
873// typeof(R-P) = Typeof(P::TNeg + R)
874// These must be specialized for P=Real and P=Complex.
875#define SimTK_DEFINE_REAL_NTRAITS(R) \
876template <> class NTraits<R> { \
877public: \
878 typedef R T; \
879 typedef negator<T> TNeg; \
880 typedef T TWithoutNegator; \
881 typedef T TReal; \
882 typedef T TImag; \
883 typedef complex<T> TComplex; \
884 typedef T THerm; \
885 typedef T TPosTrans; \
886 typedef T TSqHermT; \
887 typedef T TSqTHerm; \
888 typedef T TElement; \
889 typedef T TRow; \
890 typedef T TCol; \
891 typedef T TSqrt; \
892 typedef T TAbs; \
893 typedef T TStandard; \
894 typedef T TInvert; \
895 typedef T TNormalize; \
896 typedef T Scalar; \
897 typedef T ULessScalar; \
898 typedef T Number; \
899 typedef T StdNumber; \
900 typedef T Precision; \
901 typedef T ScalarNormSq; \
902 template <class P> struct Result { \
903 typedef typename CNT<P>::template Result<R>::Mul Mul; \
904 typedef typename CNT< typename CNT<P>::THerm >::template Result<R>::Mul Dvd; \
905 typedef typename CNT<P>::template Result<R>::Add Add; \
906 typedef typename CNT< typename CNT<P>::TNeg >::template Result<R>::Add Sub; \
907 }; \
908 template <class P> struct Substitute { \
909 typedef P Type; \
910 }; \
911 enum { \
912 NRows = 1, \
913 NCols = 1, \
914 RowSpacing = 1, \
915 ColSpacing = 1, \
916 NPackedElements = 1, \
917 NActualElements = 1, \
918 NActualScalars = 1, \
919 ImagOffset = 0, \
920 RealStrideFactor = 1, \
921 ArgDepth = SCALAR_DEPTH, \
922 IsScalar = 1, \
923 IsULessScalar = 1, \
924 IsNumber = 1, \
925 IsStdNumber = 1, \
926 IsPrecision = 1, \
927 SignInterpretation = 1 \
928 }; \
929 static const T* getData(const T& t) { return &t; } \
930 static T* updData(T& t) { return &t; } \
931 static const T& real(const T& t) { return t; } \
932 static T& real(T& t) { return t; } \
933 static const T& imag(const T&) { static const T v{}; return v; } \
934 static T& imag(T&) { static T v{}; assert(false); return v; } \
935 static const TNeg& negate(const T& t) {return reinterpret_cast<const TNeg&>(t);} \
936 static TNeg& negate(T& t) {return reinterpret_cast<TNeg&>(t);} \
937 static const THerm& transpose(const T& t) {return reinterpret_cast<const THerm&>(t);} \
938 static THerm& transpose(T& t) {return reinterpret_cast<THerm&>(t);} \
939 static const TPosTrans& positionalTranspose(const T& t) \
940 {return reinterpret_cast<const TPosTrans&>(t);} \
941 static TPosTrans& positionalTranspose(T& t) \
942 {return reinterpret_cast<TPosTrans&>(t);} \
943 static const TWithoutNegator& castAwayNegatorIfAny(const T& t) \
944 {return reinterpret_cast<const TWithoutNegator&>(t);} \
945 static TWithoutNegator& updCastAwayNegatorIfAny(T& t) \
946 {return reinterpret_cast<TWithoutNegator&>(t);} \
947 static ScalarNormSq scalarNormSqr(const T& t) {return t*t;} \
948 static TSqrt sqrt(const T& t) {return std::sqrt(t);} \
949 static TAbs abs(const T& t) {return std::abs(t);} \
950 static const TStandard& standardize(const T& t) {return t;} \
951 static TNormalize normalize(const T& t) {return (t>0?T(1):(t<0?T(-1):getNaN()));} \
952 static TInvert invert(const T& t) {return T(1)/t;} \
953 /* properties of this floating point representation */ \
954 static constexpr T getEps() {return RTraits<T>::getEps();} \
955 static constexpr T getSignificant() {return RTraits<T>::getSignificant();} \
956 static constexpr T getNaN() {return std::numeric_limits<T>::quiet_NaN();} \
957 static constexpr T getInfinity() {return std::numeric_limits<T>::infinity();} \
958 static constexpr T getLeastPositive() {return std::numeric_limits<T>::min();} \
959 static constexpr T getMostPositive() {return std::numeric_limits<T>::max();} \
960 static constexpr T getLeastNegative() {return -std::numeric_limits<T>::min();} \
961 static constexpr T getMostNegative() {return -std::numeric_limits<T>::max();} \
962 static constexpr T getSqrtEps() {return detail::consteval_sqrt(getEps());} \
963 static constexpr T getTiny() {constexpr auto s=detail::consteval_sqrt(getEps()); return getEps()*detail::consteval_sqrt(s);} \
964 static bool isFinite(const T& t) {return SimTK::isFinite(t);} \
965 static bool isNaN (const T& t) {return SimTK::isNaN(t);} \
966 static bool isInf (const T& t) {return SimTK::isInf(t);} \
967 /* Methods to use for approximate comparisons. Perform comparison in the wider of the two */ \
968 /* precisions, using the default tolerance from the narrower of the two precisions. */ \
969 static double getDefaultTolerance() {return RTraits<T>::getDefaultTolerance();} \
970 static bool isNumericallyEqual(const T& t, const float& f) {return SimTK::isNumericallyEqual(t,f);} \
971 static bool isNumericallyEqual(const T& t, const double& d) {return SimTK::isNumericallyEqual(t,d);} \
972 static bool isNumericallyEqual(const T& t, int i) {return SimTK::isNumericallyEqual(t,i);} \
973 /* Here the tolerance is given so we don't have to figure it out. */ \
974 static bool isNumericallyEqual(const T& t, const float& f, double tol){return SimTK::isNumericallyEqual(t,f,tol);} \
975 static bool isNumericallyEqual(const T& t, const double& d, double tol){return SimTK::isNumericallyEqual(t,d,tol);} \
976 static bool isNumericallyEqual(const T& t, int i, double tol){return SimTK::isNumericallyEqual(t,i,tol);} \
977 /* Carefully calculated constants. */ \
978 static constexpr T getZero() {return T(0);} \
979 static constexpr T getOne() {return T(1);} \
980 static constexpr T getMinusOne() {return T(-1);} \
981 static constexpr T getTwo() {return T(2);} \
982 static constexpr T getThree() {return T(3);} \
983 static constexpr T getOneHalf() {return T(0.5L);} \
984 static constexpr T getOneThird() {return T(1.L/3.L);} \
985 static constexpr T getOneFourth() {return T(0.25L);} \
986 static constexpr T getOneFifth() {return T(0.2L);} \
987 static constexpr T getOneSixth() {return T(1.L/6.L);} \
988 static constexpr T getOneSeventh() {return T(1.L/7.L);} \
989 static constexpr T getOneEighth() {return T(0.125L);} \
990 static constexpr T getOneNinth() {return T(1.L/9.L);} \
991 static constexpr T getPi() {return T(SimTK_PI);} \
992 static constexpr T getOneOverPi() {return T(1.L/SimTK_PI);} \
993 static constexpr T getE() {return T(SimTK_E);} \
994 static constexpr T getLog2E() {return T(SimTK_LOG2E);} \
995 static constexpr T getLog10E() {return T(SimTK_LOG10E);} \
996 static constexpr T getSqrt2() {return T(SimTK_SQRT2);} \
997 static constexpr T getOneOverSqrt2() {return T(1.L/SimTK_SQRT2);} \
998 static constexpr T getSqrt3() {return T(SimTK_SQRT3);} \
999 static constexpr T getOneOverSqrt3() {return T(1.L/SimTK_SQRT3);} \
1000 static constexpr T getCubeRoot2() {return T(SimTK_CBRT2);} \
1001 static constexpr T getCubeRoot3() {return T(SimTK_CBRT3);} \
1002 static constexpr T getLn2() {return T(SimTK_LN2);} \
1003 static constexpr T getLn10() {return T(SimTK_LN10);} \
1004 /* integer digit counts useful for formatted input and output */ \
1005 static constexpr int getNumDigits() {return std::numeric_limits<T>::digits10;} \
1006 static constexpr int getLosslessNumDigits() {return (int)(5.0L*(std::numeric_limits<T>::digits-1)/4.0L*(SimTK_LN2/SimTK_LN10)+0.5L);} \
1007}; \
1008template<> struct NTraits<R>::Result<float> \
1009 {typedef Widest<R,float>::Type Mul;typedef Mul Dvd;typedef Mul Add;typedef Mul Sub;}; \
1010template<> struct NTraits<R>::Result<double> \
1011 {typedef Widest<R,double>::Type Mul;typedef Mul Dvd;typedef Mul Add;typedef Mul Sub;}; \
1012template<> struct NTraits<R>::Result<complex<float> > \
1013 {typedef Widest<R,complex<float> >::Type Mul;typedef Mul Dvd;typedef Mul Add;typedef Mul Sub;}; \
1014template<> struct NTraits<R>::Result<complex<double> > \
1015 {typedef Widest<R,complex<double> >::Type Mul;typedef Mul Dvd;typedef Mul Add;typedef Mul Sub;}; \
1016template<> struct NTraits<R>::Result<conjugate<float> > \
1017 {typedef conjugate<Widest<R,float>::Type> Mul;typedef Mul Dvd;typedef Mul Add;typedef Mul Sub;}; \
1018template<> struct NTraits<R>::Result<conjugate<double> > \
1019 {typedef conjugate<Widest<R,double>::Type> Mul;typedef Mul Dvd;typedef Mul Add;typedef Mul Sub;}
1020
1021#if defined(__clang__)
1022#pragma clang diagnostic push
1023// The function `T& imag(T&)` generates a null-dereference warning.
1024#pragma clang diagnostic ignored "-Wnull-dereference"
1025#endif
1028#if defined(__clang__)
1029#pragma clang diagnostic pop
1030#endif
1031
1032#undef SimTK_DEFINE_REAL_NTRAITS
1033
1035template <class R> class CNT< complex<R> > : public NTraits< complex<R> > { };
1036template <class R> class CNT< conjugate<R> > : public NTraits< conjugate<R> > { };
1037template <> class CNT<float> : public NTraits<float> { };
1038template <> class CNT<double> : public NTraits<double> { };
1039
1040
1041} // namespace SimTK
1042
1043#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:651
#define SimTK_NTRAITS_CONJ_SPEC(T1, T2)
Definition NTraits.h:851
#define SimTK_DEFINE_REAL_NTRAITS(R)
Definition NTraits.h:875
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:572
static constexpr T getOneNinth()
Definition NTraits.h:632
static TInvert invert(const T &t)
Definition NTraits.h:590
static bool isNumericallyEqual(const T &a, const conjugate< R2 > &b, double tol)
Definition NTraits.h:609
C T
Definition NTraits.h:495
C ULessScalar
Definition NTraits.h:517
static const R & imag(const T &t)
Definition NTraits.h:563
C TNormalize
Definition NTraits.h:514
static constexpr T getOneEighth()
Definition NTraits.h:631
static R & imag(T &t)
Definition NTraits.h:564
static TAbs abs(const T &t)
Definition NTraits.h:586
R TSqTHerm
Definition NTraits.h:505
static bool isNumericallyEqual(const T &a, const complex< R2 > &b)
Definition NTraits.h:603
static constexpr T getSqrt2()
Definition NTraits.h:638
static TNeg & negate(T &t)
Definition NTraits.h:567
static constexpr T getLn10()
Definition NTraits.h:645
C TCol
Definition NTraits.h:508
static constexpr T getE()
Definition NTraits.h:635
static constexpr T getOneOverPi()
Definition NTraits.h:634
R ScalarNormSq
Definition NTraits.h:521
static constexpr T getOneOverSqrt3()
Definition NTraits.h:641
static const R & real(const T &t)
Definition NTraits.h:561
static bool isNumericallyEqual(const T &a, const double &b)
Definition NTraits.h:614
static THerm & transpose(T &t)
Definition NTraits.h:570
static bool isNumericallyEqual(const T &a, int b)
Definition NTraits.h:616
static const TStandard & standardize(const T &t)
Definition NTraits.h:588
static const THerm & transpose(const T &t)
Definition NTraits.h:569
static bool isNumericallyEqual(const T &a, const conjugate< R2 > &b)
Definition NTraits.h:607
C Scalar
Definition NTraits.h:516
static bool isFinite(const T &t)
Definition NTraits.h:597
static T * updData(T &t)
Definition NTraits.h:560
static ScalarNormSq scalarNormSqr(const T &t)
Definition NTraits.h:582
static R & real(T &t)
Definition NTraits.h:562
static constexpr T getOneSeventh()
Definition NTraits.h:630
static constexpr T getSqrt3()
Definition NTraits.h:640
static constexpr T getZero()
Definition NTraits.h:620
conjugate< R > THerm
Definition NTraits.h:502
static const T * getData(const T &t)
Definition NTraits.h:559
static constexpr T getLn2()
Definition NTraits.h:644
static bool isInf(const T &t)
Definition NTraits.h:599
static constexpr T getCubeRoot2()
Definition NTraits.h:642
static bool isNumericallyEqual(const T &a, const double &b, double tol)
Definition NTraits.h:615
static constexpr T getNaN()
Definition NTraits.h:592
static const TWithoutNegator & castAwayNegatorIfAny(const T &t)
Definition NTraits.h:577
static bool isNumericallyEqual(const T &a, int b, double tol)
Definition NTraits.h:617
static constexpr T getOneHalf()
Definition NTraits.h:625
static constexpr T getInfinity()
Definition NTraits.h:593
R TImag
Definition NTraits.h:500
C StdNumber
Definition NTraits.h:519
C TStandard
Definition NTraits.h:512
static TNormalize normalize(const T &t)
Definition NTraits.h:589
static TPosTrans & positionalTranspose(T &t)
Definition NTraits.h:574
static bool isNaN(const T &t)
Definition NTraits.h:598
negator< C > TNeg
Definition NTraits.h:496
C Number
Definition NTraits.h:518
static constexpr T getOneFifth()
Definition NTraits.h:628
static constexpr T getTwo()
Definition NTraits.h:623
static constexpr T getOneFourth()
Definition NTraits.h:627
static constexpr T getLog10E()
Definition NTraits.h:637
C TComplex
Definition NTraits.h:501
C TElement
Definition NTraits.h:506
static constexpr T getMinusOne()
Definition NTraits.h:622
static constexpr T getOneSixth()
Definition NTraits.h:629
static constexpr T getLog2E()
Definition NTraits.h:636
static TSqrt sqrt(const T &t)
Definition NTraits.h:584
C TSqrt
Definition NTraits.h:510
R Precision
Definition NTraits.h:520
C TInvert
Definition NTraits.h:513
static bool isNumericallyEqual(const T &a, const float &b, double tol)
Definition NTraits.h:613
static const TNeg & negate(const T &t)
Definition NTraits.h:566
static constexpr T getPi()
Definition NTraits.h:633
static constexpr T getOne()
Definition NTraits.h:621
static double getDefaultTolerance()
Definition NTraits.h:601
C TWithoutNegator
Definition NTraits.h:497
static TWithoutNegator & updCastAwayNegatorIfAny(T &t)
Definition NTraits.h:579
static constexpr T getOneThird()
Definition NTraits.h:626
R TAbs
Definition NTraits.h:511
C TPosTrans
Definition NTraits.h:503
static constexpr T getOneOverSqrt2()
Definition NTraits.h:639
R TSqHermT
Definition NTraits.h:504
static constexpr T getI()
Definition NTraits.h:595
static constexpr T getCubeRoot3()
Definition NTraits.h:643
static bool isNumericallyEqual(const T &a, const complex< R2 > &b, double tol)
Definition NTraits.h:605
C TRow
Definition NTraits.h:507
static bool isNumericallyEqual(const T &a, const float &b)
Definition NTraits.h:612
R TReal
Definition NTraits.h:499
static constexpr T getThree()
Definition NTraits.h:624
static constexpr T getOneOverPi()
Definition NTraits.h:821
conjugate< R > TInvert
Definition NTraits.h:690
static constexpr T getMinusOne()
Definition NTraits.h:809
static ScalarNormSq scalarNormSqr(const T &t)
Definition NTraits.h:759
static constexpr T getCubeRoot2()
Definition NTraits.h:829
static constexpr T getInfinity()
Definition NTraits.h:779
static bool isNumericallyEqual(const T &a, const float &b)
Definition NTraits.h:799
conjugate< R > T
Definition NTraits.h:673
conjugate< R > Scalar
Definition NTraits.h:693
static bool isFinite(const T &t)
Definition NTraits.h:784
static bool isNumericallyEqual(const T &a, const float &b, double tol)
Definition NTraits.h:800
static TReal & real(T &t)
Definition NTraits.h:739
conjugate< R > TCol
Definition NTraits.h:685
static const TReal & real(const T &t)
Definition NTraits.h:738
conjugate< R > TElement
Definition NTraits.h:683
conjugate< R > TPosTrans
Definition NTraits.h:680
conjugate< R > TNormalize
Definition NTraits.h:691
static constexpr T getOneThird()
Definition NTraits.h:813
static constexpr T getOneNinth()
Definition NTraits.h:819
static TInvert invert(const T &t)
Definition NTraits.h:770
static constexpr T getOneHalf()
Definition NTraits.h:812
static const TImag & imag(const T &t)
Definition NTraits.h:740
static constexpr T getE()
Definition NTraits.h:822
static TPosTrans & positionalTranspose(T &t)
Definition NTraits.h:751
static constexpr T getLn2()
Definition NTraits.h:831
static const TPosTrans & positionalTranspose(const T &t)
Definition NTraits.h:749
conjugate< R > ULessScalar
Definition NTraits.h:694
static constexpr T getCubeRoot3()
Definition NTraits.h:830
static bool isNumericallyEqual(const T &a, const complex< R2 > &b)
Definition NTraits.h:794
static TSqrt sqrt(const T &t)
Definition NTraits.h:761
static TImag & imag(T &t)
Definition NTraits.h:741
conjugate< R > Number
Definition NTraits.h:695
static bool isNumericallyEqual(const T &a, int b)
Definition NTraits.h:803
static const TNeg & negate(const T &t)
Definition NTraits.h:743
static const TWithoutNegator & castAwayNegatorIfAny(const T &t)
Definition NTraits.h:754
R Precision
Definition NTraits.h:697
static const T * getData(const T &t)
Definition NTraits.h:736
static constexpr T getSqrt2()
Definition NTraits.h:825
R TAbs
Definition NTraits.h:688
static constexpr T getOneEighth()
Definition NTraits.h:818
static constexpr T getOneFifth()
Definition NTraits.h:815
static constexpr T getLog2E()
Definition NTraits.h:823
static bool isNumericallyEqual(const T &a, const double &b)
Definition NTraits.h:801
static constexpr T getOneSixth()
Definition NTraits.h:816
static constexpr T getLog10E()
Definition NTraits.h:824
static TAbs abs(const T &t)
Definition NTraits.h:763
R ScalarNormSq
Definition NTraits.h:698
static constexpr T getZero()
Definition NTraits.h:807
static constexpr T getSqrt3()
Definition NTraits.h:827
static constexpr T getOneOverSqrt3()
Definition NTraits.h:828
complex< R > THerm
Definition NTraits.h:679
conjugate< R > TRow
Definition NTraits.h:684
static constexpr T getNaN()
Definition NTraits.h:776
static T * updData(T &t)
Definition NTraits.h:737
static constexpr T getOneOverSqrt2()
Definition NTraits.h:826
static bool isNumericallyEqual(const T &a, const conjugate< R2 > &b, double tol)
Definition NTraits.h:792
static const THerm & transpose(const T &t)
Definition NTraits.h:746
R TSqHermT
Definition NTraits.h:681
static TStandard standardize(const T &t)
Definition NTraits.h:765
static constexpr T getPi()
Definition NTraits.h:820
static bool isNaN(const T &t)
Definition NTraits.h:785
static bool isNumericallyEqual(const T &a, const double &b, double tol)
Definition NTraits.h:802
complex< R > TStandard
Definition NTraits.h:689
static constexpr T getOneFourth()
Definition NTraits.h:814
static constexpr T getTwo()
Definition NTraits.h:810
conjugate< R > TWithoutNegator
Definition NTraits.h:675
static bool isNumericallyEqual(const T &a, const complex< R2 > &b, double tol)
Definition NTraits.h:796
R TSqTHerm
Definition NTraits.h:682
static bool isInf(const T &t)
Definition NTraits.h:786
static constexpr T getOne()
Definition NTraits.h:808
R TReal
Definition NTraits.h:676
static constexpr T getI()
Definition NTraits.h:782
static double getDefaultTolerance()
Definition NTraits.h:788
static constexpr T getLn10()
Definition NTraits.h:832
complex< R > TSqrt
Definition NTraits.h:687
static bool isNumericallyEqual(const T &a, int b, double tol)
Definition NTraits.h:804
static constexpr T getOneSeventh()
Definition NTraits.h:817
static constexpr T getThree()
Definition NTraits.h:811
static TNormalize normalize(const T &t)
Definition NTraits.h:767
static TWithoutNegator & updCastAwayNegatorIfAny(T &t)
Definition NTraits.h:756
conjugate< R > TComplex
Definition NTraits.h:678
complex< R > StdNumber
Definition NTraits.h:696
static TNeg & negate(T &t)
Definition NTraits.h:744
static THerm & transpose(T &t)
Definition NTraits.h:747
negator< R > TImag
Definition NTraits.h:677
negator< T > TNeg
Definition NTraits.h:674
static bool isNumericallyEqual(const T &a, const conjugate< R2 > &b)
Definition NTraits.h:790
Definition NTraits.h:486
static constexpr double getEps()
Definition NTraits.h:207
static constexpr double getSignificant()
Definition NTraits.h:208
static constexpr double getDefaultTolerance()
Definition NTraits.h:212
static constexpr float getSignificant()
What multiple of attainable accuracy do we consider significant?
Definition NTraits.h:198
static constexpr double getDefaultTolerance()
The default numerical error tolerance is always given in double precision.
Definition NTraits.h:203
static constexpr float getEps()
Attainable accuracy at this precision.
Definition NTraits.h:196
RTraits is a helper class for NTraits.
Definition NTraits.h:192
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
Definition NTraits.h:63
consteval double consteval_sqrt(double x) noexcept
Definition NTraits.h:67
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:343
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:531
CNT< P >::template Result< C >::Mul Mul
Definition NTraits.h:530
CNT< typenameCNT< P >::TNeg >::template Result< C >::Add Sub
Definition NTraits.h:533
CNT< P >::template Result< C >::Add Add
Definition NTraits.h:532
CNT< P >::template Result< T >::Add Add
Definition NTraits.h:708
CNT< typenameCNT< P >::TNeg >::template Result< T >::Add Sub
Definition NTraits.h:709
CNT< P >::template Result< T >::Mul Mul
Definition NTraits.h:706
CNT< typenameCNT< P >::THerm >::template Result< T >::Mul Dvd
Definition NTraits.h:707
Narrowest< R1, R2 >::Precision Precision
Definition NTraits.h:188
complex< typename Narrowest< R1, R2 >::Type > Type
Definition NTraits.h:187
complex< typename Narrowest< R1, R2 >::Type > Type
Definition NTraits.h:183
Narrowest< R1, R2 >::Precision Precision
Definition NTraits.h:184
Narrowest< R1, R2 >::Precision Precision
Definition NTraits.h:180
complex< typename Narrowest< R1, R2 >::Type > Type
Definition NTraits.h:179
double Type
Definition NTraits.h:177
double Precision
Definition NTraits.h:177
float Type
Definition NTraits.h:176
float Precision
Definition NTraits.h:176
float Type
Definition NTraits.h:175
float Precision
Definition NTraits.h:175
float Precision
Definition NTraits.h:174
float Type
Definition NTraits.h:174
This class is specialized for all 16 combinations of standard types (that is, real and complex types ...
Definition NTraits.h:173
Widest< R1, R2 >::Precision Precision
Definition NTraits.h:161
complex< typename Widest< R1, R2 >::Type > Type
Definition NTraits.h:160
complex< typename Widest< R1, R2 >::Type > Type
Definition NTraits.h:156
Widest< R1, R2 >::Precision Precision
Definition NTraits.h:157
complex< typename Widest< R1, R2 >::Type > Type
Definition NTraits.h:152
Widest< R1, R2 >::Precision Precision
Definition NTraits.h:153
double Precision
Definition NTraits.h:150
double Type
Definition NTraits.h:150
double Precision
Definition NTraits.h:149
double Type
Definition NTraits.h:149
double Precision
Definition NTraits.h:148
double Type
Definition NTraits.h:148
float Type
Definition NTraits.h:147
float Precision
Definition NTraits.h:147
This class is specialized for all 16 combinations of standard types (that is, real and complex types ...
Definition NTraits.h:146