00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #ifndef _TEUCHOS_SCALARTRAITS_HPP_
00038 #define _TEUCHOS_SCALARTRAITS_HPP_
00039
00044 #include "Teuchos_ConfigDefs.hpp"
00045
00046 #ifndef HAVE_NUMERIC_LIMITS
00047 #include "Teuchos_LAPACK.hpp"
00048 #endif
00049
00050 #ifdef HAVE_TEUCHOS_ARPREC
00051 #include "mp/mpreal.h"
00052 #endif
00053
00054 #ifdef HAVE_TEUCHOS_GNU_MP
00055 #include "gmp.h"
00056 #include "gmpxx.h"
00057 #endif
00058
00081
00082
00083
00084 namespace Teuchos {
00085 template<class T>
00086 struct UndefinedScalarTraits
00087 {
00089 static inline T notDefined() { return T::this_type_is_missing_a_specialization(); };
00090 };
00091
00092 template<class T>
00093 struct ScalarTraits
00094 {
00096 typedef T magnitudeType;
00098 static const bool isComplex = false;
00100 static const bool isComparable = false;
00102 static const bool hasMachineParameters = false;
00104 static inline magnitudeType eps() { return UndefinedScalarTraits<T>::notDefined(); };
00106 static inline magnitudeType sfmin() { return UndefinedScalarTraits<T>::notDefined(); };
00108 static inline magnitudeType base() { return UndefinedScalarTraits<T>::notDefined(); };
00110 static inline magnitudeType prec() { return UndefinedScalarTraits<T>::notDefined(); };
00112 static inline magnitudeType t() { return UndefinedScalarTraits<T>::notDefined(); };
00114 static inline magnitudeType rnd() { return UndefinedScalarTraits<T>::notDefined(); };
00116 static inline magnitudeType emin() { return UndefinedScalarTraits<T>::notDefined(); };
00118 static inline magnitudeType rmin() { return UndefinedScalarTraits<T>::notDefined(); };
00120 static inline magnitudeType emax() { return UndefinedScalarTraits<T>::notDefined(); };
00122 static inline magnitudeType rmax() { return UndefinedScalarTraits<T>::notDefined(); };
00124 static inline magnitudeType magnitude(T a) { return UndefinedScalarTraits<T>::notDefined(); };
00126 static inline T zero() { return UndefinedScalarTraits<T>::notDefined(); };
00128 static inline T one() { return UndefinedScalarTraits<T>::notDefined(); };
00130 static inline T conjugate(T a) { return UndefinedScalarTraits<T>::notDefined(); };
00132 static inline T nan() { return UndefinedScalarTraits<T>::notDefined(); };
00134 static inline bool isnaninf(const T& x) { return UndefinedScalarTraits<T>::notDefined(); };
00136 static inline void seedrandom(unsigned int s) { int i; T t = &i; };
00138 static inline T random() { return UndefinedScalarTraits<T>::notDefined(); };
00140 static inline std::string name() { (void)UndefinedScalarTraits<T>::notDefined(); return 0; };
00142 static inline magnitudeType squareroot(T x) { return UndefinedScalarTraits<T>::notDefined(); };
00143 };
00144
00145 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00146
00147 template<>
00148 struct ScalarTraits<int>
00149 {
00150 typedef int magnitudeType;
00151 static const bool isComplex = false;
00152 static const bool isComparable = true;
00153 static const bool hasMachineParameters = false;
00154
00155 static inline magnitudeType magnitude(int a) { return ::abs(a); };
00156 static inline int zero() { return 0; };
00157 static inline int one() { return 1; };
00158 static inline int conjugate(int x) { return x; };
00159 static inline void seedrandom(unsigned int s) { srand(s); };
00160
00161 static inline int random() { return rand(); };
00162 static inline std::string name() { return "int"; };
00163 static inline int squareroot(int x) { return (int) ::sqrt((double) x); };
00164 };
00165
00166 #ifndef __sun
00167 extern const float flt_nan;
00168 #endif
00169
00170 template<>
00171 struct ScalarTraits<float>
00172 {
00173 typedef float magnitudeType;
00174 static const bool isComplex = false;
00175 static const bool isComparable = true;
00176 static const bool hasMachineParameters = true;
00177 static inline float eps() {
00178 #ifdef HAVE_NUMERIC_LIMITS
00179 return std::numeric_limits<float>::epsilon();
00180 #else
00181 LAPACK<int, float> lp; return lp.LAMCH('E');
00182 #endif
00183 }
00184 static inline float sfmin() {
00185 #ifdef HAVE_NUMERIC_LIMITS
00186 return std::numeric_limits<float>::min();
00187 #else
00188 LAPACK<int, float> lp; return lp.LAMCH('S');
00189 #endif
00190 };
00191 static inline float base() {
00192 #ifdef HAVE_NUMERIC_LIMITS
00193 return std::numeric_limits<float>::radix;
00194 #else
00195 LAPACK<int, float> lp; return lp.LAMCH('B');
00196 #endif
00197 };
00198 static inline float prec() {
00199 #ifdef HAVE_NUMERIC_LIMITS
00200 return eps()*base();
00201 #else
00202 LAPACK<int, float> lp; return lp.LAMCH('P');
00203 #endif
00204 };
00205 static inline float t() {
00206 #ifdef HAVE_NUMERIC_LIMITS
00207 return std::numeric_limits<float>::digits;
00208 #else
00209 LAPACK<int, float> lp; return lp.LAMCH('N');
00210 #endif
00211 };
00212 static inline float rnd() {
00213 #ifdef HAVE_NUMERIC_LIMITS
00214 return ( std::numeric_limits<float>::round_style == std::round_to_nearest ? float(1.0) : float(0.0) );
00215 #else
00216 LAPACK<int, float> lp; return lp.LAMCH('R');
00217 #endif
00218 };
00219 static inline float emin() {
00220 #ifdef HAVE_NUMERIC_LIMITS
00221 return std::numeric_limits<float>::min_exponent;
00222 #else
00223 LAPACK<int, float> lp; return lp.LAMCH('M');
00224 #endif
00225 };
00226 static inline float rmin() {
00227 #ifdef HAVE_NUMERIC_LIMITS
00228 return std::numeric_limits<float>::min();
00229 #else
00230 LAPACK<int, float> lp; return lp.LAMCH('U');
00231 #endif
00232 };
00233 static inline float emax() {
00234 #ifdef HAVE_NUMERIC_LIMITS
00235 return std::numeric_limits<float>::max_exponent;
00236 #else
00237 LAPACK<int, float> lp; return lp.LAMCH('L');
00238 #endif
00239 };
00240 static inline float rmax() {
00241 #ifdef HAVE_NUMERIC_LIMITS
00242 return std::numeric_limits<float>::max();
00243 #else
00244 LAPACK<int, float> lp; return lp.LAMCH('O');
00245 #endif
00246 };
00247 static inline magnitudeType magnitude(float a) { return fabs(a); };
00248 static inline float zero() { return(0.0); };
00249 static inline float one() { return(1.0); };
00250 static inline float conjugate(float x) { return(x); };
00251 static inline float nan() {
00252 #ifdef __sun
00253 return 0.0/sin(0.0);
00254 #else
00255 return flt_nan;
00256 #endif
00257 };
00258 static inline bool isnaninf(float x) {
00259 const float tol = 1e-6;
00260 if( !(x <= tol) && !(x > tol) ) return true;
00261 float z=0.0*x; if( !(z <= tol) && !(z > tol) ) return true;
00262 return false;
00263 }
00264 static inline void seedrandom(unsigned int s) { srand(s); };
00265 static inline float random() { float rnd = (float) rand() / RAND_MAX; return (float)(-1.0 + 2.0 * rnd); };
00266 static inline std::string name() { return "float"; };
00267 static inline float squareroot(float x) { return sqrt(x); };
00268 };
00269
00270 #ifndef __sun
00271 extern const double dbl_nan;
00272 #endif
00273
00274 template<>
00275 struct ScalarTraits<double>
00276 {
00277 typedef double magnitudeType;
00278 static const bool isComplex = false;
00279 static const bool isComparable = true;
00280 static const bool hasMachineParameters = true;
00281 static inline double eps() {
00282 #ifdef HAVE_NUMERIC_LIMITS
00283 return std::numeric_limits<double>::epsilon();
00284 #else
00285 LAPACK<int, double> lp; return lp.LAMCH('E');
00286 #endif
00287 }
00288 static inline double sfmin() {
00289 #ifdef HAVE_NUMERIC_LIMITS
00290 return std::numeric_limits<double>::min();
00291 #else
00292 LAPACK<int, double> lp; return lp.LAMCH('S');
00293 #endif
00294 };
00295 static inline double base() {
00296 #ifdef HAVE_NUMERIC_LIMITS
00297 return std::numeric_limits<double>::radix;
00298 #else
00299 LAPACK<int, double> lp; return lp.LAMCH('B');
00300 #endif
00301 };
00302 static inline double prec() {
00303 #ifdef HAVE_NUMERIC_LIMITS
00304 return eps()*base();
00305 #else
00306 LAPACK<int, double> lp; return lp.LAMCH('P');
00307 #endif
00308 };
00309 static inline double t() {
00310 #ifdef HAVE_NUMERIC_LIMITS
00311 return std::numeric_limits<double>::digits;
00312 #else
00313 LAPACK<int, double> lp; return lp.LAMCH('N');
00314 #endif
00315 };
00316 static inline double rnd() {
00317 #ifdef HAVE_NUMERIC_LIMITS
00318 return ( std::numeric_limits<double>::round_style == std::round_to_nearest ? double(1.0) : double(0.0) );
00319 #else
00320 LAPACK<int, double> lp; return lp.LAMCH('R');
00321 #endif
00322 };
00323 static inline double emin() {
00324 #ifdef HAVE_NUMERIC_LIMITS
00325 return std::numeric_limits<double>::min_exponent;
00326 #else
00327 LAPACK<int, double> lp; return lp.LAMCH('M');
00328 #endif
00329 };
00330 static inline double rmin() {
00331 #ifdef HAVE_NUMERIC_LIMITS
00332 return std::numeric_limits<double>::min();
00333 #else
00334 LAPACK<int, double> lp; return lp.LAMCH('U');
00335 #endif
00336 };
00337 static inline double emax() {
00338 #ifdef HAVE_NUMERIC_LIMITS
00339 return std::numeric_limits<double>::max_exponent;
00340 #else
00341 LAPACK<int, double> lp; return lp.LAMCH('L');
00342 #endif
00343 };
00344 static inline double rmax() {
00345 #ifdef HAVE_NUMERIC_LIMITS
00346 return std::numeric_limits<double>::max();
00347 #else
00348 LAPACK<int, double> lp; return lp.LAMCH('O');
00349 #endif
00350 };
00351 static inline magnitudeType magnitude(double a) { return fabs(a); };
00352 static inline double zero() { return 0.0; };
00353 static inline double one() { return 1.0; };
00354 static inline double conjugate(double x) { return(x); };
00355 static inline double nan() {
00356 #ifdef __sun
00357 return 0.0/sin(0.0);
00358 #else
00359 return dbl_nan;
00360 #endif
00361 };
00362 static inline bool isnaninf(double x) {
00363 const double tol = 1e-6;
00364 if( !(x <= tol) && !(x > tol) ) return true;
00365 double z=0.0*x; if( !(z <= tol) && !(z > tol) ) return true;
00366 return false;
00367 }
00368 static inline void seedrandom(unsigned int s) { srand(s); };
00369 static inline double random() { double rnd = (double) rand() / RAND_MAX; return (double)(-1.0 + 2.0 * rnd); };
00370 static inline std::string name() { return "double"; };
00371 static inline double squareroot(double x) { return ::sqrt(x); };
00372 };
00373
00374 #ifdef HAVE_TEUCHOS_GNU_MP
00375
00376 extern gmp_randclass gmp_rng;
00377
00378 template<>
00379 struct ScalarTraits<mpf_class>
00380 {
00381 typedef mpf_class magnitudeType;
00382 static const bool isComplex = false;
00383 static const bool isComparable = true;
00384 static const bool hasMachineParameters = false;
00385
00386 static magnitudeType magnitude(mpf_class a) { return abs(a); };
00387 static inline mpf_class zero() { mpf_class zero = 0.0; return zero; };
00388 static inline mpf_class one() { mpf_class one = 1.0; return one; };
00389 static inline mpf_class conjugate(mpf_class x) { return x; };
00390 static inline bool isnaninf(mpf_class x) { return false; }
00391 static inline void seedrandom(unsigned int s) {
00392 unsigned long int seedVal = static_cast<unsigned long int>(s);
00393 gmp_rng.seed( seedVal );
00394 };
00395 static inline mpf_class random() {
00396 return gmp_rng.get_f();
00397 };
00398 static inline std::string name() { return "mpf_class"; };
00399 static inline mpf_class squareroot(mpf_class x) { return sqrt(x); };
00400
00401 };
00402
00403 #endif
00404
00405 #ifdef HAVE_TEUCHOS_ARPREC
00406
00407 template<>
00408 struct ScalarTraits<mp_real>
00409 {
00410 typedef mp_real magnitudeType;
00411 static const bool isComplex = false;
00412 static const bool isComparable = true;
00413 static const bool hasMachineParameters = false;
00414
00415 static magnitudeType magnitude(mp_real a) { return abs(a); };
00416 static inline mp_real zero() { mp_real zero = 0.0; return zero; };
00417 static inline mp_real one() { mp_real one = 1.0; return one; };
00418 static inline mp_real conjugate(mp_real x) { return x; };
00419 static inline bool isnaninf(mp_real x) { return false; }
00420 static inline void seedrandom(unsigned int s) {
00421 long int seedVal = static_cast<long int>(s);
00422 srand48(seedVal);
00423 };
00424 static inline mp_real random() { return mp_rand(); };
00425 static inline std::string name() { return "mp_real"; };
00426 static inline mp_real squareroot(mp_real x) { return sqrt(x); };
00427
00428 };
00429
00430 #endif // HAVE_TEUCHOS_ARPREC
00431
00432 #if ( defined(HAVE_COMPLEX) || defined(HAVE_COMPLEX_H) ) && defined(HAVE_TEUCHOS_COMPLEX)
00433
00434
00435 template<class T>
00436 struct ScalarTraits<
00437 #if defined(HAVE_COMPLEX)
00438 std::complex<T>
00439 #elif defined(HAVE_COMPLEX_H)
00440 ::complex<T>
00441 #endif
00442 >
00443 {
00444 #if defined(HAVE_COMPLEX)
00445 typedef std::complex<T> ComplexT;
00446 #elif defined(HAVE_COMPLEX_H)
00447 typedef ::complex<T> ComplexT;
00448 #endif
00449 typedef typename ScalarTraits<T>::magnitudeType magnitudeType;
00450 static const bool isComplex = true;
00451 static const bool isComparable = false;
00452 static const bool hasMachineParameters = true;
00453 static inline magnitudeType eps() { return ScalarTraits<magnitudeType>::eps(); };
00454 static inline magnitudeType sfmin() { return ScalarTraits<magnitudeType>::sfmin(); };
00455 static inline magnitudeType base() { return ScalarTraits<magnitudeType>::base(); };
00456 static inline magnitudeType prec() { return ScalarTraits<magnitudeType>::prec(); };
00457 static inline magnitudeType t() { return ScalarTraits<magnitudeType>::t(); };
00458 static inline magnitudeType rnd() { return ScalarTraits<magnitudeType>::rnd(); };
00459 static inline magnitudeType emin() { return ScalarTraits<magnitudeType>::emin(); };
00460 static inline magnitudeType rmin() { return ScalarTraits<magnitudeType>::rmin(); };
00461 static inline magnitudeType emax() { return ScalarTraits<magnitudeType>::emax(); };
00462 static inline magnitudeType rmax() { return ScalarTraits<magnitudeType>::rmax(); };
00463 static magnitudeType magnitude(ComplexT a) { return std::abs(a); };
00464 static inline ComplexT zero() { return ComplexT(ScalarTraits<magnitudeType>::zero(),ScalarTraits<magnitudeType>::zero()); };
00465 static inline ComplexT one() { return ComplexT(ScalarTraits<magnitudeType>::one(),ScalarTraits<magnitudeType>::zero()); };
00466 static inline ComplexT conjugate(ComplexT a){ return ComplexT(a.real(),-a.imag()); };
00467 static inline ComplexT nan() { return ComplexT(ScalarTraits<magnitudeType>::nan(),ScalarTraits<magnitudeType>::nan()); };
00468 static inline bool isnaninf(ComplexT x) { return ScalarTraits<magnitudeType>::isnaninf(x.real()) || ScalarTraits<magnitudeType>::isnaninf(x.imag()); };
00469 static inline void seedrandom(unsigned int s) { ScalarTraits<magnitudeType>::seedrandom(s); };
00470 static inline ComplexT random()
00471 {
00472 const T rnd1 = ScalarTraits<magnitudeType>::random();
00473 const T rnd2 = ScalarTraits<magnitudeType>::random();
00474 return ComplexT(rnd1,rnd2);
00475 };
00476 static inline std::string name() { return std::string("std::complex<")+std::string(ScalarTraits<magnitudeType>::name())+std::string(">"); };
00477
00478 static inline ComplexT squareroot(ComplexT x)
00479 {
00480 typedef ScalarTraits<magnitudeType> STMT;
00481 const T r = x.real(), i = x.imag();
00482 const T a = STMT::squareroot((r*r)+(i*i));
00483 const T nr = STMT::squareroot((a+r)/2);
00484 const T ni = STMT::squareroot((a-r)/2);
00485 return ComplexT(nr,ni);
00486 };
00487 };
00488
00489 #endif // HAVE_COMPLEX || HAVE_COMPLEX_H
00490
00491 #endif // DOXYGEN_SHOULD_SKIP_THIS
00492
00493 }
00494
00495 #endif // _TEUCHOS_SCALARTRAITS_HPP_