Teuchos_ScalarTraits.hpp

Go to the documentation of this file.
00001 // @HEADER
00002 // ***********************************************************************
00003 // 
00004 //                    Teuchos: Common Tools Package
00005 //                 Copyright (2004) Sandia Corporation
00006 // 
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 // 
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //  
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //  
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00025 // 
00026 // ***********************************************************************
00027 // @HEADER
00028 
00029 // Kris
00030 // 06.18.03 -- Minor formatting changes
00031 //          -- Changed calls to LAPACK objects to use new <OType, SType> templates
00032 // 07.08.03 -- Move into Teuchos package/namespace
00033 // 07.11.03 -- Added ScalarTraits for ARPREC::mp_real
00034 // 07.14.03 -- Fixed int rand() function (was set up to return a floating-point style random number)
00035 // 07.17.03 -- Added squareroot() function
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 /* This is the default structure used by ScalarTraits<T> to produce a compile time
00082   error when the specialization does not exist for type <tt>T</tt>.
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   // Not defined: eps(), sfmin(), base(), prec(), t(), rnd(), emin(), rmin(), emax(), rmax()
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   //static inline char random() { return (-1 + 2*rand()); } // RAB: This version should be used to be consistent with others
00182   static inline char random() { return std::rand(); } // RAB: This version should be used for an unsigned char, not char
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   // Not defined: eps(), sfmin(), base(), prec(), t(), rnd(), emin(), rmin(), emax(), rmax()
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   //static inline int random() { return (-1 + 2*rand()); }  // RAB: This version should be used to be consistent with others
00204   static inline int random() { return std::rand(); }             // RAB: This version should be used for an unsigned int, not int
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) { // RAB: 2004/05/28: Taken from NOX_StatusTest_FiniteValue.C
00312     const float tol = 1e-6; // Any (bounded) number should do!
00313     if( !(x <= tol) && !(x > tol) ) return true;                 // IEEE says this should fail for NaN
00314     float z=0.0*x; if( !(z <= tol) && !(z > tol) ) return true;  // Use fact that Inf*0 = NaN
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) { // RAB: 2004/05/28: Taken from NOX_StatusTest_FiniteValue.C
00437     const double tol = 1e-6; // Any (bounded) number should do!
00438     if( !(x <= tol) && !(x > tol) ) return true;                  // IEEE says this should fail for NaN
00439     double z=0.0*x; if( !(z <= tol) && !(z > tol) ) return true;  // Use fact that Inf*0 = NaN
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   // Not defined: eps(), sfmin(), base(), prec(), t(), rnd(), emin(), rmin(), emax(), rmax()
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; } // mpf_class currently can't handle nan or inf!
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   // Todo: RAB: 2004/05/28: Add nan() and isnaninf() functions when needed!
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   // Not defined: eps(), sfmin(), base(), prec(), t(), rnd(), emin(), rmin(), emax(), rmax()
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; } // ToDo: Change this?
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   // Todo: RAB: 2004/05/28: Add nan() and isnaninf() functions when needed!
00520 };
00521   
00522 #endif // HAVE_TEUCHOS_ARPREC
00523  
00524 #if ( defined(HAVE_COMPLEX) || defined(HAVE_COMPLEX_H) ) && defined(HAVE_TEUCHOS_COMPLEX)
00525 
00526 // Partial specialization for std::complex numbers templated on real type T
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   // This will only return one of the square roots of x, the other can be obtained by taking its conjugate
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 } // Teuchos namespace
00600 
00601 #endif // _TEUCHOS_SCALARTRAITS_HPP_

Generated on Tue Oct 20 12:45:26 2009 for Teuchos - Trilinos Tools Package by doxygen 1.4.7