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
00086 template<class T>
00087 struct UndefinedScalarTraits
00088 {
00090 static inline T notDefined() { return T::this_type_is_missing_a_specialization(); }
00091 };
00092
00093 template<class T>
00094 struct ScalarTraits
00095 {
00097 typedef T magnitudeType;
00099 static const bool isComplex = false;
00101 static const bool isComparable = false;
00103 static const bool hasMachineParameters = false;
00105 static inline magnitudeType eps() { return UndefinedScalarTraits<T>::notDefined(); }
00107 static inline magnitudeType sfmin() { return UndefinedScalarTraits<T>::notDefined(); }
00109 static inline magnitudeType base() { return UndefinedScalarTraits<T>::notDefined(); }
00111 static inline magnitudeType prec() { return UndefinedScalarTraits<T>::notDefined(); }
00113 static inline magnitudeType t() { return UndefinedScalarTraits<T>::notDefined(); }
00115 static inline magnitudeType rnd() { return UndefinedScalarTraits<T>::notDefined(); }
00117 static inline magnitudeType emin() { return UndefinedScalarTraits<T>::notDefined(); }
00119 static inline magnitudeType rmin() { return UndefinedScalarTraits<T>::notDefined(); }
00121 static inline magnitudeType emax() { return UndefinedScalarTraits<T>::notDefined(); }
00123 static inline magnitudeType rmax() { return UndefinedScalarTraits<T>::notDefined(); }
00125 static inline magnitudeType magnitude(T a) { return UndefinedScalarTraits<T>::notDefined(); }
00127 static inline T zero() { return UndefinedScalarTraits<T>::notDefined(); }
00129 static inline T one() { return UndefinedScalarTraits<T>::notDefined(); }
00131 static inline magnitudeType real(T a) { return UndefinedScalarTraits<T>::notDefined(); }
00133 static inline magnitudeType imag(T a) { return UndefinedScalarTraits<T>::notDefined(); }
00135 static inline T conjugate(T a) { return UndefinedScalarTraits<T>::notDefined(); }
00137 static inline T nan() { return UndefinedScalarTraits<T>::notDefined(); }
00139 static inline bool isnaninf(const T& x) { return UndefinedScalarTraits<T>::notDefined(); }
00141 static inline void seedrandom(unsigned int s) { int i; T t = &i; }
00143 static inline T random() { return UndefinedScalarTraits<T>::notDefined(); }
00145 static inline std::string name() { (void)UndefinedScalarTraits<T>::notDefined(); return 0; }
00147 static inline T squareroot(T x) { return UndefinedScalarTraits<T>::notDefined(); }
00149 static inline T pow(T x, T y) { return UndefinedScalarTraits<T>::notDefined(); }
00150 };
00151
00152 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00153
00154
00155 void throwScalarTraitsNanInfError( const std::string &errMsg );
00156
00157
00158 #define TEUCHOS_SCALAR_TRAITS_NAN_INF_ERR( VALUE, MSG ) \
00159 if (isnaninf(VALUE)) { \
00160 std::ostringstream omsg; \
00161 omsg << MSG; \
00162 throwScalarTraitsNanInfError(omsg.str()); \
00163 }
00164
00165
00166 template<>
00167 struct ScalarTraits<char>
00168 {
00169 typedef char magnitudeType;
00170 static const bool isComplex = false;
00171 static const bool isComparable = true;
00172 static const bool hasMachineParameters = false;
00173
00174 static inline magnitudeType magnitude(char a) { return static_cast<char>(std::fabs(static_cast<double>(a))); }
00175 static inline char zero() { return 0; }
00176 static inline char one() { return 1; }
00177 static inline char conjugate(char x) { return x; }
00178 static inline char real(char x) { return x; }
00179 static inline char imag(char x) { return 0; }
00180 static inline void seedrandom(unsigned int s) { std::srand(s); }
00181
00182 static inline char random() { return std::rand(); }
00183 static inline std::string name() { return "char"; }
00184 static inline char squareroot(char x) { return (char) std::sqrt((double) x); }
00185 static inline char pow(char x, char y) { return (char) std::pow((double)x,(double)y); }
00186 };
00187
00188 template<>
00189 struct ScalarTraits<int>
00190 {
00191 typedef int magnitudeType;
00192 static const bool isComplex = false;
00193 static const bool isComparable = true;
00194 static const bool hasMachineParameters = false;
00195
00196 static inline magnitudeType magnitude(int a) { return static_cast<int>(std::fabs(static_cast<double>(a))); }
00197 static inline int zero() { return 0; }
00198 static inline int one() { return 1; }
00199 static inline int conjugate(int x) { return x; }
00200 static inline int real(int x) { return x; }
00201 static inline int imag(int x) { return 0; }
00202 static inline void seedrandom(unsigned int s) { std::srand(s); }
00203
00204 static inline int random() { return std::rand(); }
00205 static inline std::string name() { return "int"; }
00206 static inline int squareroot(int x) { return (int) std::sqrt((double) x); }
00207 static inline int pow(int x, int y) { return (int) std::pow((double)x,(double)y); }
00208 };
00209
00210 #ifndef __sun
00211 extern const float flt_nan;
00212 #endif
00213
00214 template<>
00215 struct ScalarTraits<float>
00216 {
00217 typedef float magnitudeType;
00218 static const bool isComplex = false;
00219 static const bool isComparable = true;
00220 static const bool hasMachineParameters = true;
00221 static inline float eps() {
00222 #ifdef HAVE_NUMERIC_LIMITS
00223 return std::numeric_limits<float>::epsilon();
00224 #else
00225 LAPACK<int, float> lp; return lp.LAMCH('E');
00226 #endif
00227 }
00228 static inline float sfmin() {
00229 #ifdef HAVE_NUMERIC_LIMITS
00230 return std::numeric_limits<float>::min();
00231 #else
00232 LAPACK<int, float> lp; return lp.LAMCH('S');
00233 #endif
00234 }
00235 static inline float base() {
00236 #ifdef HAVE_NUMERIC_LIMITS
00237 return std::numeric_limits<float>::radix;
00238 #else
00239 LAPACK<int, float> lp; return lp.LAMCH('B');
00240 #endif
00241 }
00242 static inline float prec() {
00243 #ifdef HAVE_NUMERIC_LIMITS
00244 return eps()*base();
00245 #else
00246 LAPACK<int, float> lp; return lp.LAMCH('P');
00247 #endif
00248 }
00249 static inline float t() {
00250 #ifdef HAVE_NUMERIC_LIMITS
00251 return std::numeric_limits<float>::digits;
00252 #else
00253 LAPACK<int, float> lp; return lp.LAMCH('N');
00254 #endif
00255 }
00256 static inline float rnd() {
00257 #ifdef HAVE_NUMERIC_LIMITS
00258 return ( std::numeric_limits<float>::round_style == std::round_to_nearest ? float(1.0) : float(0.0) );
00259 #else
00260 LAPACK<int, float> lp; return lp.LAMCH('R');
00261 #endif
00262 }
00263 static inline float emin() {
00264 #ifdef HAVE_NUMERIC_LIMITS
00265 return std::numeric_limits<float>::min_exponent;
00266 #else
00267 LAPACK<int, float> lp; return lp.LAMCH('M');
00268 #endif
00269 }
00270 static inline float rmin() {
00271 #ifdef HAVE_NUMERIC_LIMITS
00272 return std::numeric_limits<float>::min();
00273 #else
00274 LAPACK<int, float> lp; return lp.LAMCH('U');
00275 #endif
00276 }
00277 static inline float emax() {
00278 #ifdef HAVE_NUMERIC_LIMITS
00279 return std::numeric_limits<float>::max_exponent;
00280 #else
00281 LAPACK<int, float> lp; return lp.LAMCH('L');
00282 #endif
00283 }
00284 static inline float rmax() {
00285 #ifdef HAVE_NUMERIC_LIMITS
00286 return std::numeric_limits<float>::max();
00287 #else
00288 LAPACK<int, float> lp; return lp.LAMCH('O');
00289 #endif
00290 }
00291 static inline magnitudeType magnitude(float a)
00292 {
00293 #ifdef TEUCHOS_DEBUG
00294 TEUCHOS_SCALAR_TRAITS_NAN_INF_ERR(
00295 a, "Error, the input value to magnitude(...) a = " << a << " can not be NaN!" );
00296 #endif
00297 return std::fabs(a);
00298 }
00299 static inline float zero() { return(0.0); }
00300 static inline float one() { return(1.0); }
00301 static inline float conjugate(float x) { return(x); }
00302 static inline float real(float x) { return x; }
00303 static inline float imag(float x) { return 0; }
00304 static inline float nan() {
00305 #ifdef __sun
00306 return 0.0/std::sin(0.0);
00307 #else
00308 return flt_nan;
00309 #endif
00310 }
00311 static inline bool isnaninf(float x) {
00312 const float tol = 1e-6;
00313 if( !(x <= tol) && !(x > tol) ) return true;
00314 float z=0.0*x; if( !(z <= tol) && !(z > tol) ) return true;
00315 return false;
00316 }
00317 static inline void seedrandom(unsigned int s) { std::srand(s); }
00318 static inline float random() { float rnd = (float) std::rand() / RAND_MAX; return (float)(-1.0 + 2.0 * rnd); }
00319 static inline std::string name() { return "float"; }
00320 static inline float squareroot(float x)
00321 {
00322 #ifdef TEUCHOS_DEBUG
00323 TEUCHOS_SCALAR_TRAITS_NAN_INF_ERR(
00324 x, "Error, the input value to squareroot(...) x = " << x << " can not be NaN!" );
00325 #endif
00326 errno = 0;
00327 const float rtn = std::sqrt(x);
00328 if (errno)
00329 return nan();
00330 return rtn;
00331 }
00332 static inline float pow(float x, float y) { return std::pow(x,y); }
00333 };
00334
00335 #ifndef __sun
00336 extern const double dbl_nan;
00337 #endif
00338
00339 template<>
00340 struct ScalarTraits<double>
00341 {
00342 typedef double magnitudeType;
00343 static const bool isComplex = false;
00344 static const bool isComparable = true;
00345 static const bool hasMachineParameters = true;
00346 static inline double eps() {
00347 #ifdef HAVE_NUMERIC_LIMITS
00348 return std::numeric_limits<double>::epsilon();
00349 #else
00350 LAPACK<int, double> lp; return lp.LAMCH('E');
00351 #endif
00352 }
00353 static inline double sfmin() {
00354 #ifdef HAVE_NUMERIC_LIMITS
00355 return std::numeric_limits<double>::min();
00356 #else
00357 LAPACK<int, double> lp; return lp.LAMCH('S');
00358 #endif
00359 }
00360 static inline double base() {
00361 #ifdef HAVE_NUMERIC_LIMITS
00362 return std::numeric_limits<double>::radix;
00363 #else
00364 LAPACK<int, double> lp; return lp.LAMCH('B');
00365 #endif
00366 }
00367 static inline double prec() {
00368 #ifdef HAVE_NUMERIC_LIMITS
00369 return eps()*base();
00370 #else
00371 LAPACK<int, double> lp; return lp.LAMCH('P');
00372 #endif
00373 }
00374 static inline double t() {
00375 #ifdef HAVE_NUMERIC_LIMITS
00376 return std::numeric_limits<double>::digits;
00377 #else
00378 LAPACK<int, double> lp; return lp.LAMCH('N');
00379 #endif
00380 }
00381 static inline double rnd() {
00382 #ifdef HAVE_NUMERIC_LIMITS
00383 return ( std::numeric_limits<double>::round_style == std::round_to_nearest ? double(1.0) : double(0.0) );
00384 #else
00385 LAPACK<int, double> lp; return lp.LAMCH('R');
00386 #endif
00387 }
00388 static inline double emin() {
00389 #ifdef HAVE_NUMERIC_LIMITS
00390 return std::numeric_limits<double>::min_exponent;
00391 #else
00392 LAPACK<int, double> lp; return lp.LAMCH('M');
00393 #endif
00394 }
00395 static inline double rmin() {
00396 #ifdef HAVE_NUMERIC_LIMITS
00397 return std::numeric_limits<double>::min();
00398 #else
00399 LAPACK<int, double> lp; return lp.LAMCH('U');
00400 #endif
00401 }
00402 static inline double emax() {
00403 #ifdef HAVE_NUMERIC_LIMITS
00404 return std::numeric_limits<double>::max_exponent;
00405 #else
00406 LAPACK<int, double> lp; return lp.LAMCH('L');
00407 #endif
00408 }
00409 static inline double rmax() {
00410 #ifdef HAVE_NUMERIC_LIMITS
00411 return std::numeric_limits<double>::max();
00412 #else
00413 LAPACK<int, double> lp; return lp.LAMCH('O');
00414 #endif
00415 }
00416 static inline magnitudeType magnitude(double a)
00417 {
00418 #ifdef TEUCHOS_DEBUG
00419 TEUCHOS_SCALAR_TRAITS_NAN_INF_ERR(
00420 a, "Error, the input value to magnitude(...) a = " << a << " can not be NaN!" );
00421 #endif
00422 return std::fabs(a);
00423 }
00424 static inline double zero() { return 0.0; }
00425 static inline double one() { return 1.0; }
00426 static inline double conjugate(double x) { return(x); }
00427 static inline double real(double x) { return(x); }
00428 static inline double imag(double x) { return(0); }
00429 static inline double nan() {
00430 #ifdef __sun
00431 return 0.0/std::sin(0.0);
00432 #else
00433 return dbl_nan;
00434 #endif
00435 }
00436 static inline bool isnaninf(double x) {
00437 const double tol = 1e-6;
00438 if( !(x <= tol) && !(x > tol) ) return true;
00439 double z=0.0*x; if( !(z <= tol) && !(z > tol) ) return true;
00440 return false;
00441 }
00442 static inline void seedrandom(unsigned int s) { std::srand(s); }
00443 static inline double random() { double rnd = (double) std::rand() / RAND_MAX; return (double)(-1.0 + 2.0 * rnd); }
00444 static inline std::string name() { return "double"; }
00445 static inline double squareroot(double x)
00446 {
00447 #ifdef TEUCHOS_DEBUG
00448 TEUCHOS_SCALAR_TRAITS_NAN_INF_ERR(
00449 x, "Error, the input value to squareroot(...) x = " << x << " can not be NaN!" );
00450 #endif
00451 errno = 0;
00452 const double rtn = std::sqrt(x);
00453 if (errno)
00454 return nan();
00455 return rtn;
00456 }
00457 static inline double pow(double x, double y) { return std::pow(x,y); }
00458 };
00459
00460 #ifdef HAVE_TEUCHOS_GNU_MP
00461
00462 extern gmp_randclass gmp_rng;
00463
00464 template<>
00465 struct ScalarTraits<mpf_class>
00466 {
00467 typedef mpf_class magnitudeType;
00468 static const bool isComplex = false;
00469 static const bool isComparable = true;
00470 static const bool hasMachineParameters = false;
00471
00472 static magnitudeType magnitude(mpf_class a) { return std::abs(a); }
00473 static inline mpf_class zero() { mpf_class zero = 0.0; return zero; }
00474 static inline mpf_class one() { mpf_class one = 1.0; return one; }
00475 static inline mpf_class conjugate(mpf_class x) { return x; }
00476 static inline mpf_class real(mpf_class x) { return(x); }
00477 static inline mpf_class imag(mpf_class x) { return(0); }
00478 static inline bool isnaninf(mpf_class x) { return false; }
00479 static inline void seedrandom(unsigned int s) {
00480 unsigned long int seedVal = static_cast<unsigned long int>(s);
00481 gmp_rng.seed( seedVal );
00482 }
00483 static inline mpf_class random() {
00484 return gmp_rng.get_f();
00485 }
00486 static inline std::string name() { return "mpf_class"; }
00487 static inline mpf_class squareroot(mpf_class x) { return std::sqrt(x); }
00488 static inline mpf_class pow(mpf_class x, mpf_class y) { return pow(x,y); }
00489
00490 };
00491
00492 #endif
00493
00494 #ifdef HAVE_TEUCHOS_ARPREC
00495
00496 template<>
00497 struct ScalarTraits<mp_real>
00498 {
00499 typedef mp_real magnitudeType;
00500 static const bool isComplex = false;
00501 static const bool isComparable = true;
00502 static const bool hasMachineParameters = false;
00503
00504 static magnitudeType magnitude(mp_real a) { return std::abs(a); }
00505 static inline mp_real zero() { mp_real zero = 0.0; return zero; }
00506 static inline mp_real one() { mp_real one = 1.0; return one; }
00507 static inline mp_real conjugate(mp_real x) { return x; }
00508 static inline mp_real real(mp_real x) { return(x); }
00509 static inline mp_real imag(mp_real x) { return(0); }
00510 static inline bool isnaninf(mp_real x) { return false; }
00511 static inline void seedrandom(unsigned int s) {
00512 long int seedVal = static_cast<long int>(s);
00513 srand48(seedVal);
00514 }
00515 static inline mp_real random() { return mp_rand(); }
00516 static inline std::string name() { return "mp_real"; }
00517 static inline mp_real squareroot(mp_real x) { return std::sqrt(x); }
00518 static inline mp_real pow(mp_real x, mp_real y) { return pow(x,y); }
00519
00520 };
00521
00522 #endif // HAVE_TEUCHOS_ARPREC
00523
00524 #if ( defined(HAVE_COMPLEX) || defined(HAVE_COMPLEX_H) ) && defined(HAVE_TEUCHOS_COMPLEX)
00525
00526
00527 template<class T>
00528 struct ScalarTraits<
00529 #if defined(HAVE_COMPLEX)
00530 std::complex<T>
00531 #elif defined(HAVE_COMPLEX_H)
00532 std::complex<T>
00533 #endif
00534 >
00535 {
00536 #if defined(HAVE_COMPLEX)
00537 typedef std::complex<T> ComplexT;
00538 #elif defined(HAVE_COMPLEX_H)
00539 typedef std::complex<T> ComplexT;
00540 #endif
00541 typedef typename ScalarTraits<T>::magnitudeType magnitudeType;
00542 static const bool isComplex = true;
00543 static const bool isComparable = false;
00544 static const bool hasMachineParameters = true;
00545 static inline magnitudeType eps() { return ScalarTraits<magnitudeType>::eps(); }
00546 static inline magnitudeType sfmin() { return ScalarTraits<magnitudeType>::sfmin(); }
00547 static inline magnitudeType base() { return ScalarTraits<magnitudeType>::base(); }
00548 static inline magnitudeType prec() { return ScalarTraits<magnitudeType>::prec(); }
00549 static inline magnitudeType t() { return ScalarTraits<magnitudeType>::t(); }
00550 static inline magnitudeType rnd() { return ScalarTraits<magnitudeType>::rnd(); }
00551 static inline magnitudeType emin() { return ScalarTraits<magnitudeType>::emin(); }
00552 static inline magnitudeType rmin() { return ScalarTraits<magnitudeType>::rmin(); }
00553 static inline magnitudeType emax() { return ScalarTraits<magnitudeType>::emax(); }
00554 static inline magnitudeType rmax() { return ScalarTraits<magnitudeType>::rmax(); }
00555 static magnitudeType magnitude(ComplexT a)
00556 {
00557 #ifdef TEUCHOS_DEBUG
00558 TEUCHOS_SCALAR_TRAITS_NAN_INF_ERR(
00559 a, "Error, the input value to magnitude(...) a = " << a << " can not be NaN!" );
00560 #endif
00561 return std::abs(a);
00562 }
00563 static inline ComplexT zero() { return ComplexT(ScalarTraits<magnitudeType>::zero(),ScalarTraits<magnitudeType>::zero()); }
00564 static inline ComplexT one() { return ComplexT(ScalarTraits<magnitudeType>::one(),ScalarTraits<magnitudeType>::zero()); }
00565 static inline ComplexT conjugate(ComplexT a){ return ComplexT(a.real(),-a.imag()); }
00566 static inline magnitudeType real(ComplexT a) { return a.real(); }
00567 static inline magnitudeType imag(ComplexT a) { return a.imag(); }
00568 static inline ComplexT nan() { return ComplexT(ScalarTraits<magnitudeType>::nan(),ScalarTraits<magnitudeType>::nan()); }
00569 static inline bool isnaninf(ComplexT x) { return ScalarTraits<magnitudeType>::isnaninf(x.real()) || ScalarTraits<magnitudeType>::isnaninf(x.imag()); }
00570 static inline void seedrandom(unsigned int s) { ScalarTraits<magnitudeType>::seedrandom(s); }
00571 static inline ComplexT random()
00572 {
00573 const T rnd1 = ScalarTraits<magnitudeType>::random();
00574 const T rnd2 = ScalarTraits<magnitudeType>::random();
00575 return ComplexT(rnd1,rnd2);
00576 }
00577 static inline std::string name() { return std::string("std::complex<")+std::string(ScalarTraits<magnitudeType>::name())+std::string(">"); }
00578
00579 static inline ComplexT squareroot(ComplexT x)
00580 {
00581 #ifdef TEUCHOS_DEBUG
00582 TEUCHOS_SCALAR_TRAITS_NAN_INF_ERR(
00583 x, "Error, the input value to squareroot(...) x = " << x << " can not be NaN!" );
00584 #endif
00585 typedef ScalarTraits<magnitudeType> STMT;
00586 const T r = x.real(), i = x.imag();
00587 const T a = STMT::squareroot((r*r)+(i*i));
00588 const T nr = STMT::squareroot((a+r)/2);
00589 const T ni = STMT::squareroot((a-r)/2);
00590 return ComplexT(nr,ni);
00591 }
00592 static inline ComplexT pow(ComplexT x, ComplexT y) { return pow(x,y); }
00593 };
00594
00595 #endif // HAVE_COMPLEX || HAVE_COMPLEX_H
00596
00597 #endif // DOXYGEN_SHOULD_SKIP_THIS
00598
00599 }
00600
00601 #endif // _TEUCHOS_SCALARTRAITS_HPP_