LAMA
|
00001 00033 #ifndef LAMA_SCALAR_HPP_ 00034 #define LAMA_SCALAR_HPP_ 00035 00036 // for dll_import 00037 #include <lama/config.hpp> 00038 00039 // base classes 00040 #include <lama/Printable.hpp> 00041 00042 // others 00043 #include <lama/LAMATypes.hpp> 00044 00045 #include <lama/exception/LAMAAssert.hpp> 00046 00047 // logging 00048 #include <logging/logging.hpp> 00049 00050 #include <complex> 00051 #include <cmath> 00052 #include <cstdio> 00053 00054 namespace lama 00055 { 00056 00060 class LAMA_DLL_IMPORTEXPORT Scalar : public Printable 00061 { 00062 public: 00063 00064 enum ScalarType { INDEX_TYPE, FLOAT, DOUBLE, LONG_DOUBLE, 00065 COMPLEX, DOUBLE_COMPLEX, LONG_DOUBLE_COMPLEX, UNKNOWN }; 00066 00070 typedef const Scalar ExpressionMemberType; 00071 00075 inline Scalar(); 00076 00084 template<typename T> 00085 explicit inline Scalar( const T value ); 00086 00092 inline Scalar( const float value ); 00093 00099 inline Scalar( const double value ); 00100 00106 inline Scalar( const long double value ); 00107 00113 template<typename T> 00114 inline Scalar( const std::complex<T> value ); 00115 00119 inline virtual ~Scalar(); 00120 00126 template<typename T> 00127 inline T getValue() const; 00128 00129 // Removed: template<typename T> operator T () const for type conversions 00130 // Might cause problems due to implicit conversions, should only be used explicitly 00131 // Now should be done as: cast<T>( scalar ) 00132 00137 inline Scalar operator-() const; 00138 00142 inline bool isReal() const; 00143 00150 inline virtual void writeAt( std::ostream& stream ) const; 00151 00152 template<typename T> 00153 inline static ScalarType getType(); 00154 00155 inline static size_t getTypeSize( const ScalarType type ); 00156 00157 protected: 00158 00159 LAMA_LOG_DECL_STATIC_LOGGER( logger ); 00160 00161 private: 00162 00163 std::complex<long double> mValue; 00164 }; 00165 00166 LAMA_DLL_IMPORTEXPORT std::ostream& operator<<( std::ostream& stream, const Scalar::ScalarType& object ); 00167 00173 template<typename T> 00174 T cast( const Scalar& scalar ) 00175 { 00176 return scalar.getValue<T>(); 00177 } 00178 00179 const Scalar zero; 00180 00181 inline Scalar::Scalar() 00182 : mValue( 0.0, 0.0 ) 00183 {} 00184 00185 template<typename T> 00186 inline Scalar::Scalar( const T value ) 00187 : mValue( value, 0.0 ) 00188 {} 00189 00190 inline Scalar::Scalar( const float value ) 00191 : mValue( value, 0.0 ) 00192 {} 00193 00194 inline Scalar::Scalar( const double value ) 00195 : mValue( value, 0.0 ) 00196 {} 00197 00198 inline Scalar::Scalar( const long double value ) 00199 : mValue( value, 0.0 ) 00200 {} 00201 00202 template<typename T> 00203 inline Scalar::Scalar( const std::complex<T> value ) 00204 : mValue( value.real(), value.imag() ) 00205 {} 00206 00207 00208 inline Scalar::~Scalar() 00209 {} 00210 00211 template<typename T> 00212 inline T Scalar::getValue() const 00213 { 00214 return static_cast<T>( mValue.real() ); 00215 } 00216 00217 template<> 00218 inline std::complex<float> Scalar::getValue() const 00219 { 00220 return std::complex<float>( static_cast<float>( mValue.real() ), static_cast<float>( mValue.imag() ) ); 00221 } 00222 00223 template<> 00224 inline std::complex<double> Scalar::getValue() const 00225 { 00226 return std::complex<double>( static_cast<double>( mValue.real() ), static_cast<double>( mValue.imag() ) ); 00227 } 00228 00229 template<> 00230 inline std::complex<long double> Scalar::getValue() const 00231 { 00232 return std::complex<long double>( mValue.real(), mValue.imag() ); 00233 } 00234 00235 inline Scalar Scalar::operator-() const 00236 { 00237 return Scalar( -mValue ); 00238 } 00239 00240 inline bool Scalar::isReal() const 00241 { 00242 return mValue.imag() == 0.0; 00243 } 00244 00245 inline void Scalar::writeAt( std::ostream& stream ) const 00246 { 00247 stream << "Scalar(" << mValue.real() << ")"; 00248 } 00249 00250 template<typename T> 00251 inline Scalar::ScalarType Scalar::getType() 00252 { 00253 return UNKNOWN; 00254 } 00255 00256 template<> 00257 inline Scalar::ScalarType Scalar::getType<IndexType>() 00258 { 00259 return INDEX_TYPE; 00260 } 00261 00262 template<> 00263 inline Scalar::ScalarType Scalar::getType<float>() 00264 { 00265 return FLOAT; 00266 } 00267 00268 template<> 00269 inline Scalar::ScalarType Scalar::getType<double>() 00270 { 00271 return DOUBLE; 00272 } 00273 00274 template<> 00275 inline Scalar::ScalarType Scalar::getType<long double>() 00276 { 00277 return LONG_DOUBLE; 00278 } 00279 00280 template<> 00281 inline Scalar::ScalarType Scalar::getType<std::complex<float> >() 00282 { 00283 return COMPLEX; 00284 } 00285 00286 template<> 00287 inline Scalar::ScalarType Scalar::getType<std::complex<double> >() 00288 { 00289 return DOUBLE_COMPLEX; 00290 } 00291 00292 template<> 00293 inline Scalar::ScalarType Scalar::getType<std::complex<long double> >() 00294 { 00295 return LONG_DOUBLE_COMPLEX; 00296 } 00297 00298 inline size_t Scalar::getTypeSize( const ScalarType type ) 00299 { 00300 size_t typeSize = 0; 00301 00302 switch ( type ) 00303 { 00304 case FLOAT: 00305 typeSize = 4; 00306 break; 00307 00308 case DOUBLE: 00309 typeSize = 8; 00310 break; 00311 00312 case LONG_DOUBLE: 00313 typeSize = 16; 00314 break; 00315 00316 case COMPLEX: 00317 typeSize = 8; 00318 break; 00319 00320 case DOUBLE_COMPLEX: 00321 typeSize = 16; 00322 break; 00323 00324 case LONG_DOUBLE_COMPLEX: 00325 typeSize = 32; 00326 break; 00327 00328 default: 00329 typeSize = 0; 00330 } 00331 00332 return typeSize; 00333 } 00334 00342 inline Scalar operator+ ( const Scalar& a, const Scalar& b ) 00343 { 00344 return Scalar( a.getValue<long double>() + b.getValue<long double>() ); 00345 } 00346 00354 inline Scalar operator- ( const Scalar& a, const Scalar& b ) 00355 { 00356 return Scalar( a.getValue<long double>() - b.getValue<long double>() ); 00357 } 00358 00366 inline Scalar operator* ( const Scalar& a, const Scalar& b ) 00367 { 00368 return Scalar( a.getValue<long double>() * b.getValue<long double>() ); 00369 } 00370 00378 inline Scalar operator/ ( const Scalar& a, const Scalar& b ) 00379 { 00380 return Scalar( a.getValue<long double>() / b.getValue<long double>() ); 00381 } 00382 00390 inline bool operator==( const Scalar& a, const Scalar& b ) 00391 { 00392 return a.getValue<long double>() == b.getValue<long double>(); 00393 } 00394 00402 inline bool operator!=( const Scalar& a, const Scalar& b ) 00403 { 00404 return !( a == b ); 00405 } 00406 00407 inline bool operator<( const Scalar& a, const Scalar& b ) 00408 { 00409 if ( !a.isReal() || !b.isReal() ) 00410 { 00411 LAMA_THROWEXCEPTION( "Could not call operator< for Scalar a = " << a << ", b = " << b 00412 << ", because one of them is not real." ); 00413 } 00414 00415 return a.getValue<long double>() < b.getValue<long double>() ; 00416 } 00417 00418 inline bool operator>( const Scalar& a, const Scalar& b ) 00419 { 00420 if ( !a.isReal() || !b.isReal() ) 00421 { 00422 LAMA_THROWEXCEPTION( "Could not call operator> for Scalar a = " << a << ", b = " << b 00423 << ", because one of them is not real." ); 00424 } 00425 00426 return a.getValue<long double>() > b.getValue<long double>() ; 00427 } 00428 00429 inline bool operator<=( const Scalar& a, const Scalar& b ) 00430 { 00431 return !( a > b ); 00432 } 00433 00434 inline bool operator>=( const Scalar& a, const Scalar& b ) 00435 { 00436 return !( a < b ); 00437 } 00438 00439 inline Scalar sqrt( const Scalar scalar ) 00440 { 00441 return std::sqrt( scalar.getValue<std::complex<long double> >() ); 00442 } 00443 00444 inline Scalar abs( const Scalar scalar ) 00445 { 00446 return std::abs( scalar.getValue<std::complex<long double> >() ); 00447 } 00448 00449 inline Scalar max( const Scalar a, const Scalar b ) 00450 { 00451 LAMA_ASSERT_DEBUG( a.isReal(), "Non-real value in max : " << a ); 00452 LAMA_ASSERT_DEBUG( b.isReal(), "Non-real value in max : " << b ); 00453 00454 return std::max( a.getValue<long double >(), b.getValue<long double >() ); 00455 } 00456 00457 inline Scalar min( const Scalar a, const Scalar b ) 00458 { 00459 LAMA_ASSERT_DEBUG( a.isReal(), "Non-real value in max : " << a ); 00460 LAMA_ASSERT_DEBUG( b.isReal(), "Non-real value in max : " << b ); 00461 00462 return std::min( a.getValue<long double >(), b.getValue<long double >() ); 00463 } 00464 00465 } //namespace lama 00466 00467 #endif // LAMA_SCALAR_HPP_