Simbody
3.4 (development)
|
00001 #ifndef SimTK_SIMMATRIX_COMPOSITE_NUMERICAL_TYPES_H_ 00002 #define SimTK_SIMMATRIX_COMPOSITE_NUMERICAL_TYPES_H_ 00003 00004 /* -------------------------------------------------------------------------- * 00005 * Simbody(tm): SimTKcommon * 00006 * -------------------------------------------------------------------------- * 00007 * This is part of the SimTK biosimulation toolkit originating from * 00008 * Simbios, the NIH National Center for Physics-Based Simulation of * 00009 * Biological Structures at Stanford, funded under the NIH Roadmap for * 00010 * Medical Research, grant U54 GM072970. See https://simtk.org/home/simbody. * 00011 * * 00012 * Portions copyright (c) 2005-12 Stanford University and the Authors. * 00013 * Authors: Michael Sherman * 00014 * Contributors: * 00015 * * 00016 * Licensed under the Apache License, Version 2.0 (the "License"); you may * 00017 * not use this file except in compliance with the License. You may obtain a * 00018 * copy of the License at http://www.apache.org/licenses/LICENSE-2.0. * 00019 * * 00020 * Unless required by applicable law or agreed to in writing, software * 00021 * distributed under the License is distributed on an "AS IS" BASIS, * 00022 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 00023 * See the License for the specific language governing permissions and * 00024 * limitations under the License. * 00025 * -------------------------------------------------------------------------- */ 00026 00106 #include "SimTKcommon/internal/common.h" 00107 00108 namespace SimTK { 00109 00110 // These are CNT "depths". 0 means the corresponding CNT is a scalar, 00111 // 1 means it is a composite with scalar elements, 2 means a composite 00112 // with composite elements, and 3 means a composite with depth-2 00113 // composite elements. Beyond that the user will have to diambiguate 00114 // operations by using named routines rather than operators. 00115 enum { 00116 SCALAR_DEPTH = 0, 00117 SCALAR_COMPOSITE_DEPTH = 1, 00118 COMPOSITE_COMPOSITE_DEPTH = 2, 00119 COMPOSITE_3_DEPTH = 3, 00120 MAX_RESOLVED_DEPTH = COMPOSITE_3_DEPTH 00121 }; 00122 00136 template <class K> class CNT : private K { 00137 public: 00138 typedef K T; 00139 typedef typename K::TNeg TNeg; 00140 typedef typename K::TWithoutNegator TWithoutNegator; 00141 typedef typename K::TReal TReal; 00142 typedef typename K::TImag TImag; 00143 typedef typename K::TComplex TComplex; 00144 typedef typename K::THerm THerm; 00145 typedef typename K::TPosTrans TPosTrans; 00146 typedef typename K::TSqHermT TSqHermT; 00147 typedef typename K::TSqTHerm TSqTHerm; 00148 typedef typename K::TElement TElement; 00149 typedef typename K::TRow TRow; // type of a row or column 00150 typedef typename K::TCol TCol; 00151 00152 // These are the results of calculations and should be packed regardless 00153 // of the spacing of this CNT. 00154 typedef typename K::TSqrt TSqrt; // also turns unit^2 to unit 00155 typedef typename K::TAbs TAbs; 00156 typedef typename K::TStandard TStandard; // packed, StdNumbers 00157 typedef typename K::TInvert TInvert; // also turns units into 1/units 00158 typedef typename K::TNormalize TNormalize; // TODO: what effect on units? 00159 00160 typedef typename K::Scalar Scalar; // quantity< units, <unitlessScalar> > 00161 typedef typename K::ULessScalar ULessScalar; // <number> or negator<number> 00162 typedef typename K::Number Number; // <real>, <complex> or <conjugate> 00163 typedef typename K::StdNumber StdNumber; // <real>, <complex> 00164 typedef typename K::Precision Precision; // float, double, long double 00165 00166 typedef typename K::ScalarNormSq ScalarNormSq; // type of conjugate square of underlying scalar or 00167 // numeric value (squares the units too) 00168 00169 template <class P> struct Result { 00170 typedef typename K::template Result<P>::Mul Mul; 00171 typedef typename K::template Result<P>::Dvd Dvd; 00172 typedef typename K::template Result<P>::Add Add; 00173 typedef typename K::template Result<P>::Sub Sub; 00174 }; 00175 00176 // Shape-preserving element substitution 00177 template <class P> struct Substitute { 00178 typedef typename K::template Substitute<P>::Type Type; 00179 }; 00180 00181 enum { 00182 NRows = K::NRows, 00183 NCols = K::NCols, 00184 RowSpacing = K::RowSpacing, 00185 ColSpacing = K::ColSpacing, 00186 NPackedElements = K::NPackedElements, 00187 NActualElements = K::NActualElements, 00188 NActualScalars = K::NActualScalars, 00189 ImagOffset = K::ImagOffset, 00190 RealStrideFactor = K::RealStrideFactor, 00191 ArgDepth = K::ArgDepth, 00192 IsScalar = K::IsScalar, // scalar with units, real, complex, conjugate, negator 00193 IsULessScalar = K::IsULessScalar, // real, complex, conjugate, negator 00194 IsNumber = K::IsNumber, // real, complex, conjugate 00195 IsStdNumber = K::IsStdNumber, // real, complex 00196 IsPrecision = K::IsPrecision, // real (float, double, long double) 00197 SignInterpretation = K::SignInterpretation // 1 normally, -1 if elements are negated 00198 }; 00199 00200 static const Scalar* getData(const T& t) { return t.getData(); } 00201 static Scalar* updData(T& t) { return t.updData(); } 00202 00203 static const TReal& real(const T& t) { return t.real(); } 00204 static TReal& real(T& t) { return t.real(); } 00205 static const TImag& imag(const T& t) { return t.imag(); } 00206 static TImag& imag(T& t) { return t.imag(); } 00207 00208 // We expect to be able to negate and transpose (hermitian or 00209 // positional) with just type casting; no need for help from class 00210 // K except to tell us the appropriate types. 00211 static const TNeg& negate(const T& t) 00212 { return reinterpret_cast<const TNeg&>(t); } 00213 static TNeg& negate(T& t) 00214 { return reinterpret_cast<TNeg&>(t); } 00215 00216 static const THerm& transpose(const K& t) 00217 { return reinterpret_cast<const THerm&>(t); } 00218 static THerm& transpose(K& t) 00219 { return reinterpret_cast<THerm&>(t); } 00220 00221 static const TPosTrans& positionalTranspose(const K& t) 00222 { return reinterpret_cast<const TPosTrans&>(t); } 00223 static TPosTrans& positionalTranspose(K& t) 00224 { return reinterpret_cast<TPosTrans&>(t); } 00225 00226 // If the underlying scalars of this CNT are negator<N> for some numeric type N, 00227 // this method removes the negator<>, effectively negating the entire CNT. You 00228 // can still deal with the sign correctly by using the above enum SignInterpretation 00229 // which will be -1 in that case, 1 if there was no negator<> to remove. Note: 00230 // I'm not talking about TWithoutNegator::SignInterpretation -- that one is guaranteed 00231 // to be 1! T::SignInterpretation is the one you want. 00232 static const TWithoutNegator& castAwayNegatorIfAny(const T& t) 00233 {return reinterpret_cast<const TWithoutNegator&>(t);} 00234 static TWithoutNegator& updCastAwayNegatorIfAny(T& t) 00235 {return reinterpret_cast<TWithoutNegator&>(t);} 00236 00237 static ScalarNormSq scalarNormSqr(const K& t) {return t.scalarNormSqr();} 00238 00239 static TSqrt sqrt(const K& t) {return t.sqrt();} 00240 static TAbs abs(const K& t) {return t.abs();} 00241 static TStandard standardize(const K& t) {return t.standardize();} 00242 static TNormalize normalize(const K& t) {return t.normalize();} 00243 static TInvert invert(const K& t) {return t.invert();} 00244 00245 static K getInfinity() {return K::getInfinity();} 00246 static K getNaN() {return K::getNaN();} 00247 00249 static bool isNaN(const K& t) {return t.isNaN();} 00252 static bool isInf(const K& t) {return t.isInf();} 00254 static bool isFinite(const K& t) {return t.isFinite();} 00255 00263 template <class K2> static bool 00264 isNumericallyEqual(const K& t1, const K2& t2) 00265 { return t1.isNumericallyEqual(t2);} 00266 template <class K2> static bool 00267 isNumericallyEqual(const K& t1, const K2& t2, double tol) 00268 { return t1.isNumericallyEqual(t2,tol);} 00269 static double getDefaultTolerance() {return K::getDefaultTolerance();} 00270 00271 }; 00272 00273 } // namespace SimTK 00274 00275 #endif // SimTK_SIMMATRIX_COMPOSITE_NUMERICAL_TYPES_H_