| /* |
| * Tiny Vector Matrix Library |
| * Dense Vector Matrix Libary of Tiny size using Expression Templates |
| * |
| * Copyright (C) 2001 - 2003 Olaf Petzold <opetzold@users.sourceforge.net> |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| * |
| * $Id: NumericTraits.h,v 1.11 2004/11/04 18:10:35 opetzold Exp $ |
| */ |
| |
| #ifndef TVMET_NUMERIC_TRAITS_H |
| #define TVMET_NUMERIC_TRAITS_H |
| |
| #if defined(TVMET_HAVE_COMPLEX) |
| # include <complex> |
| #endif |
| #include <cmath> |
| #include <limits> |
| |
| #include <tvmet/CompileTimeError.h> |
| |
| |
| namespace tvmet { |
| |
| |
| /** |
| * \class NumericTraits NumericTraits.h "tvmet/NumericTraits.h" |
| * \brief Traits for integral types for operations. |
| * |
| * For each type we have to specialize this traits. |
| * |
| * \note Keep in mind that the long types long long and long double doesn't |
| * have traits. This is due to the sum_type. We can't give a guarantee |
| * that there is a type of holding the sum. Therefore using this traits |
| * is only safe if you have long long resp. long double types by |
| * working on long ints and doubles. Otherwise you will get not expected |
| * result for some circumstances. Anyway, you can use big integer/float |
| * libraries and specialize the traits by your own. |
| * |
| * \todo The abs function of complex<non_float_type> can have an |
| * overrun due to numeric computation. Solve it (someone |
| * using value_type=long here?) |
| */ |
| template<class T> |
| struct NumericTraits { |
| typedef T base_type; |
| typedef T value_type; |
| typedef value_type sum_type; |
| typedef value_type diff_type; |
| typedef value_type float_type; |
| typedef value_type signed_type; |
| |
| typedef NumericTraits<value_type> traits_type; |
| typedef const value_type& argument_type; |
| |
| static inline |
| base_type real(argument_type x); |
| |
| static inline |
| base_type imag(argument_type x); |
| |
| static inline |
| value_type conj(argument_type x); |
| |
| static inline |
| base_type abs(argument_type x); |
| |
| static inline |
| value_type sqrt(argument_type x); |
| |
| static inline |
| base_type norm_1(argument_type x) { |
| return NumericTraits<base_type>::abs(traits_type::real(x)) |
| + NumericTraits<base_type>::abs(traits_type::imag(x)); |
| } |
| |
| static inline |
| base_type norm_2(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| base_type norm_inf(argument_type x) { |
| return std::max(NumericTraits<base_type>::abs(traits_type::real(x)), |
| NumericTraits<base_type>::abs(traits_type::imag(x))); |
| } |
| |
| static inline |
| bool equals(argument_type lhs, argument_type rhs) { |
| static base_type sqrt_epsilon( |
| NumericTraits<base_type>::sqrt( |
| std::numeric_limits<base_type>::epsilon())); |
| |
| return traits_type::norm_inf(lhs - rhs) < sqrt_epsilon * |
| std::max(std::max(traits_type::norm_inf(lhs), |
| traits_type::norm_inf(rhs)), |
| std::numeric_limits<base_type>::min()); |
| } |
| }; |
| |
| |
| /* |
| * numeric traits for standard types |
| */ |
| |
| |
| /** |
| * \class NumericTraits<char> NumericTraits.h "tvmet/NumericTraits.h" |
| * \brief Traits specialized for char. |
| */ |
| template<> |
| struct NumericTraits<char> { |
| typedef char value_type; |
| typedef value_type base_type; |
| typedef long sum_type; |
| typedef int diff_type; |
| typedef float float_type; |
| typedef char signed_type; |
| |
| typedef NumericTraits<value_type> traits_type; |
| typedef value_type argument_type; |
| |
| static inline |
| base_type real(argument_type x) { return x; } |
| |
| static inline |
| base_type imag(argument_type x) { return 0; } |
| |
| static inline |
| value_type conj(argument_type x) { return x; } |
| |
| static inline |
| base_type abs(argument_type x) { return std::abs(x); } |
| |
| static inline |
| value_type sqrt(argument_type x) { |
| return static_cast<value_type>(std::sqrt(static_cast<float_type>(x))); |
| } |
| |
| static inline |
| base_type norm_1(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| base_type norm_2(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| base_type norm_inf(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| bool equals(argument_type lhs, argument_type rhs) { return lhs == rhs; } |
| |
| enum { is_complex = false }; |
| |
| /** Complexity on operations. */ |
| enum { |
| ops_plus = 1, /**< Complexity on plus/minus ops. */ |
| ops_muls = 1 /**< Complexity on multiplications. */ |
| }; |
| }; |
| |
| |
| /** |
| * \class NumericTraits<unsigned char> NumericTraits.h "tvmet/NumericTraits.h" |
| * \brief Traits specialized for unsigned char. |
| * |
| * \note Normally it doesn't make sense to call <tt>conj</tt> |
| * for an unsigned type! An unary minus operator |
| * applied to unsigned type will result unsigned. Therefore |
| * this function is missing here. |
| */ |
| template<> |
| struct NumericTraits<unsigned char> { |
| typedef unsigned char value_type; |
| typedef value_type base_type; |
| typedef unsigned long sum_type; |
| typedef int diff_type; |
| typedef float float_type; |
| typedef int signed_type; |
| |
| typedef NumericTraits<value_type> traits_type; |
| typedef value_type argument_type; |
| |
| static inline |
| base_type real(argument_type x) { return x; } |
| |
| static inline |
| base_type imag(argument_type x) { return 0; } |
| |
| static inline |
| base_type abs(argument_type x) { return std::abs(x); } |
| |
| static inline |
| value_type sqrt(argument_type x) { |
| return static_cast<value_type>(std::sqrt(static_cast<float_type>(x))); |
| } |
| |
| static inline |
| base_type norm_1(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| base_type norm_2(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| base_type norm_inf(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| bool equals(argument_type lhs, argument_type rhs) { return lhs == rhs; } |
| |
| enum { is_complex = false }; |
| |
| /** Complexity on operations. */ |
| enum { |
| ops_plus = 1, /**< Complexity on plus/minus ops. */ |
| ops_muls = 1 /**< Complexity on multiplications. */ |
| }; |
| }; |
| |
| |
| /** |
| * \class NumericTraits<short int> NumericTraits.h "tvmet/NumericTraits.h" |
| * \brief Traits specialized for short int. |
| */ |
| template<> |
| struct NumericTraits<short int> { |
| typedef short int value_type; |
| typedef value_type base_type; |
| #if defined(TVMET_HAVE_LONG_LONG) |
| typedef long long sum_type; |
| #else |
| typedef long sum_type; |
| #endif |
| typedef int diff_type; |
| typedef float float_type; |
| typedef short int signed_type; |
| |
| typedef NumericTraits<value_type> traits_type; |
| typedef value_type argument_type; |
| |
| static inline |
| base_type real(argument_type x) { return x; } |
| |
| static inline |
| base_type imag(argument_type x) { return 0; } |
| |
| static inline |
| value_type conj(argument_type x) { return x; } |
| |
| static inline |
| base_type abs(argument_type x) { return std::abs(x); } |
| |
| static inline |
| value_type sqrt(argument_type x) { |
| return static_cast<value_type>(std::sqrt(static_cast<float_type>(x))); |
| } |
| |
| static inline |
| base_type norm_1(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| base_type norm_2(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| base_type norm_inf(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| bool equals(argument_type lhs, argument_type rhs) { return lhs == rhs; } |
| |
| enum { is_complex = false }; |
| |
| /** Complexity on operations. */ |
| enum { |
| ops_plus = 1, /**< Complexity on plus/minus ops. */ |
| ops_muls = 1 /**< Complexity on multiplications. */ |
| }; |
| }; |
| |
| |
| /** |
| * \class NumericTraits<short unsigned int> NumericTraits.h "tvmet/NumericTraits.h" |
| * \brief Traits specialized for short unsigned int. |
| * |
| * \note Normally it doesn't make sense to call <tt>conj</tt> |
| * for an unsigned type! An unary minus operator |
| * applied to unsigned type will result unsigned. Therefore |
| * this function is missing here. |
| */ |
| template<> |
| struct NumericTraits<short unsigned int> { |
| typedef short unsigned int value_type; |
| typedef value_type base_type; |
| #if defined(TVMET_HAVE_LONG_LONG) |
| typedef unsigned long long sum_type; |
| #else |
| typedef unsigned long sum_type; |
| #endif |
| typedef int diff_type; |
| typedef float float_type; |
| typedef int signed_type; |
| |
| typedef NumericTraits<value_type> traits_type; |
| typedef value_type argument_type; |
| |
| static inline |
| base_type real(argument_type x) { return x; } |
| |
| static inline |
| base_type imag(argument_type x) { return 0; } |
| |
| static inline |
| base_type abs(argument_type x) { return std::abs(x); } |
| |
| static inline |
| value_type sqrt(argument_type x) { |
| return static_cast<value_type>(std::sqrt(static_cast<float_type>(x))); |
| } |
| |
| static inline |
| base_type norm_1(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| base_type norm_2(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| base_type norm_inf(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| bool equals(argument_type lhs, argument_type rhs) { return lhs == rhs; } |
| |
| enum { is_complex = false }; |
| |
| /** Complexity on operations. */ |
| enum { |
| ops_plus = 1, /**< Complexity on plus/minus ops. */ |
| ops_muls = 1 /**< Complexity on multiplications. */ |
| }; |
| }; |
| |
| |
| /** |
| * \class NumericTraits<int> NumericTraits.h "tvmet/NumericTraits.h" |
| * \brief Traits specialized for int. |
| */ |
| template<> |
| struct NumericTraits<int> { |
| typedef int value_type; |
| typedef value_type base_type; |
| #if defined(TVMET_HAVE_LONG_LONG) |
| typedef long long sum_type; |
| #else |
| typedef long sum_type; |
| #endif |
| typedef int diff_type; |
| typedef double float_type; |
| typedef int signed_type; |
| |
| typedef NumericTraits<value_type> traits_type; |
| typedef value_type argument_type; |
| |
| static inline |
| base_type real(argument_type x) { return x; } |
| |
| static inline |
| base_type imag(argument_type x) { return 0; } |
| |
| static inline |
| value_type conj(argument_type x) { return x; } |
| |
| static inline |
| base_type abs(argument_type x) { return std::abs(x); } |
| |
| static inline |
| value_type sqrt(argument_type x) { |
| return static_cast<value_type>(std::sqrt(static_cast<float_type>(x))); |
| } |
| |
| static inline |
| base_type norm_1(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| base_type norm_2(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| base_type norm_inf(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| bool equals(argument_type lhs, argument_type rhs) { return lhs == rhs; } |
| |
| enum { is_complex = false }; |
| |
| /** Complexity on operations. */ |
| enum { |
| ops_plus = 1, /**< Complexity on plus/minus ops. */ |
| ops_muls = 1 /**< Complexity on multiplications. */ |
| }; |
| }; |
| |
| |
| /** |
| * \class NumericTraits<unsigned int> NumericTraits.h "tvmet/NumericTraits.h" |
| * \brief Traits specialized for unsigned int. |
| * |
| * \note Normally it doesn't make sense to call <tt>conj</tt> |
| * for an unsigned type! An unary minus operator |
| * applied to unsigned type will result unsigned. Therefore |
| * this function is missing here. |
| */ |
| template<> |
| struct NumericTraits<unsigned int> { |
| typedef unsigned int value_type; |
| typedef value_type base_type; |
| #if defined(TVMET_HAVE_LONG_LONG) |
| typedef unsigned long long sum_type; |
| #else |
| typedef unsigned long sum_type; |
| #endif |
| typedef int diff_type; |
| typedef double float_type; |
| typedef long signed_type; |
| |
| typedef NumericTraits<value_type> traits_type; |
| typedef value_type argument_type; |
| |
| static inline |
| base_type real(argument_type x) { return x; } |
| |
| static inline |
| base_type imag(argument_type x) { return 0; } |
| |
| static inline |
| base_type abs(argument_type x) { return x; } |
| |
| static inline |
| value_type sqrt(argument_type x) { |
| return static_cast<value_type>(std::sqrt(static_cast<float_type>(x))); |
| } |
| |
| static inline |
| base_type norm_1(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| base_type norm_2(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| base_type norm_inf(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| bool equals(argument_type lhs, argument_type rhs) { return lhs == rhs; } |
| |
| enum { is_complex = false }; |
| |
| /** Complexity on operations. */ |
| enum { |
| ops_plus = 1, /**< Complexity on plus/minus ops. */ |
| ops_muls = 1 /**< Complexity on multiplications. */ |
| }; |
| }; |
| |
| |
| /** |
| * \class NumericTraits<long> NumericTraits.h "tvmet/NumericTraits.h" |
| * \brief Traits specialized for long. |
| */ |
| template<> |
| struct NumericTraits<long> { |
| typedef long value_type; |
| typedef value_type base_type; |
| #if defined(TVMET_HAVE_LONG_LONG) |
| typedef long long sum_type; |
| #else |
| typedef long sum_type; |
| #endif |
| typedef long diff_type; |
| typedef double float_type; |
| typedef long signed_type; |
| |
| typedef NumericTraits<value_type> traits_type; |
| typedef value_type argument_type; |
| |
| static inline |
| base_type real(argument_type x) { return x; } |
| |
| static inline |
| base_type imag(argument_type x) { return 0; } |
| |
| static inline |
| value_type conj(argument_type x) { return x; } |
| |
| static inline |
| base_type abs(argument_type x) { return std::abs(x); } |
| |
| static inline |
| value_type sqrt(argument_type x) { |
| return static_cast<value_type>(std::sqrt(static_cast<float_type>(x))); |
| } |
| |
| static inline |
| base_type norm_1(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| base_type norm_2(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| base_type norm_inf(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| bool equals(argument_type lhs, argument_type rhs) { return lhs == rhs; } |
| |
| enum { is_complex = false }; |
| |
| /** Complexity on operations. */ |
| enum { |
| ops_plus = 1, /**< Complexity on plus/minus ops. */ |
| ops_muls = 1 /**< Complexity on multiplications. */ |
| }; |
| }; |
| |
| |
| /** |
| * \class NumericTraits<unsigned long> NumericTraits.h "tvmet/NumericTraits.h" |
| * \brief Traits specialized for unsigned long. |
| * |
| * \note Normally it doesn't make sense to call <tt>conj</tt> |
| * for an unsigned type! An unary minus operator |
| * applied to unsigned type will result unsigned. Therefore |
| * this function is missing here. |
| */ |
| template<> |
| struct NumericTraits<unsigned long> { |
| typedef unsigned long value_type; |
| typedef value_type base_type; |
| #if defined(TVMET_HAVE_LONG_LONG) |
| typedef unsigned long long sum_type; |
| #else |
| typedef unsigned long sum_type; |
| #endif |
| typedef unsigned long diff_type; |
| typedef double float_type; |
| typedef long signed_type; |
| |
| typedef NumericTraits<value_type> traits_type; |
| typedef value_type argument_type; |
| |
| static inline |
| base_type real(argument_type x) { return x; } |
| |
| static inline |
| base_type imag(argument_type x) { return 0; } |
| |
| static inline |
| base_type abs(argument_type x) { return x; } |
| |
| static inline |
| value_type sqrt(argument_type x) { |
| return static_cast<value_type>(std::sqrt(static_cast<float_type>(x))); |
| } |
| |
| static inline |
| base_type norm_1(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| base_type norm_2(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| base_type norm_inf(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| bool equals(argument_type lhs, argument_type rhs) { return lhs == rhs; } |
| |
| enum { is_complex = false }; |
| |
| /** Complexity on operations. */ |
| enum { |
| ops_plus = 1, /**< Complexity on plus/minus ops. */ |
| ops_muls = 1 /**< Complexity on multiplications. */ |
| }; |
| }; |
| |
| |
| /** |
| * \class NumericTraits<float> NumericTraits.h "tvmet/NumericTraits.h" |
| * \brief Traits specialized for float. |
| */ |
| template<> |
| struct NumericTraits<float> { |
| typedef float value_type; |
| typedef value_type base_type; |
| typedef double sum_type; |
| typedef float diff_type; |
| typedef float float_type; |
| typedef float signed_type; |
| |
| typedef NumericTraits<value_type> traits_type; |
| typedef value_type argument_type; |
| |
| static inline |
| base_type real(argument_type x) { return x; } |
| |
| static inline |
| base_type imag(argument_type x) { return 0; } |
| |
| static inline |
| value_type conj(argument_type x) { return x; } |
| |
| static inline |
| base_type abs(argument_type x) { return std::abs(x); } |
| |
| static inline |
| value_type sqrt(argument_type x) { return std::sqrt(x); } |
| |
| static inline |
| base_type norm_1(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| base_type norm_2(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| base_type norm_inf(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| bool equals(argument_type lhs, argument_type rhs) { |
| static base_type sqrt_epsilon( |
| NumericTraits<base_type>::sqrt( |
| std::numeric_limits<base_type>::epsilon())); |
| |
| return traits_type::norm_inf(lhs - rhs) < sqrt_epsilon * |
| std::max(std::max(traits_type::norm_inf(lhs), |
| traits_type::norm_inf(rhs)), |
| std::numeric_limits<base_type>::min()); |
| } |
| |
| enum { is_complex = false }; |
| |
| /** Complexity on operations. */ |
| enum { |
| ops_plus = 1, /**< Complexity on plus/minus ops. */ |
| ops_muls = 1 /**< Complexity on multiplications. */ |
| }; |
| }; |
| |
| |
| /** |
| * \class NumericTraits<double> NumericTraits.h "tvmet/NumericTraits.h" |
| * \brief Traits specialized for double. |
| */ |
| template<> |
| struct NumericTraits<double> { |
| typedef double value_type; |
| typedef value_type base_type; |
| #if defined(TVMET_HAVE_LONG_DOUBLE) |
| typedef long double sum_type; |
| #else |
| typedef double sum_type; |
| #endif |
| typedef double diff_type; |
| typedef double float_type; |
| typedef double signed_type; |
| |
| typedef NumericTraits<value_type> traits_type; |
| typedef value_type argument_type; |
| |
| static inline |
| base_type real(argument_type x) { return x; } |
| |
| static inline |
| base_type imag(argument_type x) { return 0; } |
| |
| static inline |
| value_type conj(argument_type x) { return x; } |
| |
| static inline |
| base_type abs(argument_type x) { return std::abs(x); } |
| |
| static inline |
| value_type sqrt(argument_type x) { return std::sqrt(x); } |
| |
| static inline |
| base_type norm_1(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| base_type norm_2(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| base_type norm_inf(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| bool equals(argument_type lhs, argument_type rhs) { |
| static base_type sqrt_epsilon( |
| NumericTraits<base_type>::sqrt( |
| std::numeric_limits<base_type>::epsilon())); |
| |
| return traits_type::norm_inf(lhs - rhs) < sqrt_epsilon * |
| std::max(std::max(traits_type::norm_inf(lhs), |
| traits_type::norm_inf(rhs)), |
| std::numeric_limits<base_type>::min()); |
| } |
| |
| enum { is_complex = false }; |
| |
| /** Complexity on operations. */ |
| enum { |
| ops_plus = 1, /**< Complexity on plus/minus ops. */ |
| ops_muls = 1 /**< Complexity on multiplications. */ |
| }; |
| }; |
| |
| |
| #if defined(TVMET_HAVE_LONG_DOUBLE) |
| /** |
| * \class NumericTraits<long double> NumericTraits.h "tvmet/NumericTraits.h" |
| * \brief Traits specialized for long double. |
| */ |
| template<> |
| struct NumericTraits<long double> { |
| typedef long double value_type; |
| typedef value_type base_type; |
| typedef long double sum_type; |
| typedef long double diff_type; |
| typedef long double float_type; |
| typedef long double signed_type; |
| |
| typedef NumericTraits<value_type> traits_type; |
| typedef value_type argument_type; |
| |
| static inline |
| base_type real(argument_type x) { return x; } |
| |
| static inline |
| base_type imag(argument_type x) { return 0; } |
| |
| static inline |
| value_type conj(argument_type x) { return x; } |
| |
| static inline |
| base_type abs(argument_type x) { return std::abs(x); } |
| |
| static inline |
| value_type sqrt(argument_type x) { return std::sqrt(x); } |
| |
| static inline |
| base_type norm_1(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| base_type norm_2(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| base_type norm_inf(argument_type x) { return traits_type::abs(x); } |
| |
| static inline |
| bool equals(argument_type lhs, argument_type rhs) { |
| static base_type sqrt_epsilon( |
| NumericTraits<base_type>::sqrt( |
| std::numeric_limits<base_type>::epsilon())); |
| |
| return traits_type::norm_inf(lhs - rhs) < sqrt_epsilon * |
| std::max(std::max(traits_type::norm_inf(lhs), |
| traits_type::norm_inf(rhs)), |
| std::numeric_limits<base_type>::min()); |
| } |
| |
| enum { is_complex = false }; |
| |
| /** Complexity on operations. */ |
| enum { |
| ops_plus = 1, /**< Complexity on plus/minus ops. */ |
| ops_muls = 1 /**< Complexity on multiplications. */ |
| }; |
| }; |
| #endif // TVMET_HAVE_LONG_DOUBLE |
| |
| |
| /* |
| * numeric traits for complex types |
| */ |
| #if defined(TVMET_HAVE_COMPLEX) |
| |
| /** |
| * \class NumericTraits< std::complex<int> > NumericTraits.h "tvmet/NumericTraits.h" |
| * \brief Traits specialized for std::complex<int>. |
| */ |
| template<> |
| struct NumericTraits< std::complex<int> > { |
| typedef int base_type; |
| typedef std::complex<int> value_type; |
| typedef std::complex<long> sum_type; |
| typedef std::complex<int> diff_type; |
| typedef std::complex<float> float_type; |
| typedef std::complex<int> signed_type; |
| |
| typedef NumericTraits<value_type> traits_type; |
| typedef const value_type& argument_type; |
| |
| static inline |
| base_type real(argument_type z) { return std::real(z); } |
| |
| static inline |
| base_type imag(argument_type z) { return std::imag(z); } |
| |
| static inline |
| value_type conj(argument_type z) { return std::conj(z); } |
| |
| static inline |
| base_type abs(argument_type z) { |
| base_type x = z.real(); |
| base_type y = z.imag(); |
| |
| // XXX probably case of overrun; header complex uses scaling |
| return static_cast<base_type>(NumericTraits<base_type>::sqrt(x * x + y * y)); |
| } |
| |
| static /* inline */ |
| value_type sqrt(argument_type z) { |
| // borrowed and adapted from header complex |
| base_type x = z.real(); |
| base_type y = z.imag(); |
| |
| if(x == base_type()) { |
| base_type t = NumericTraits<base_type>::sqrt( |
| NumericTraits<base_type>::abs(y) / 2); |
| return value_type(t, y < base_type() ? -t : t); |
| } |
| else { |
| base_type t = NumericTraits<base_type>::sqrt( |
| 2 * (traits_type::abs(z) |
| + NumericTraits<base_type>::abs(x))); |
| base_type u = t / 2; |
| return x > base_type() |
| ? value_type(u, y / t) |
| : value_type(NumericTraits<base_type>::abs(y) / t, y < base_type() ? -u : u); |
| } |
| } |
| |
| static inline |
| base_type norm_1(argument_type z) { |
| return NumericTraits<base_type>::abs((traits_type::real(z))) |
| + NumericTraits<base_type>::abs((traits_type::imag(z))); |
| } |
| |
| static inline |
| base_type norm_2(argument_type z) { return traits_type::abs(z); } |
| |
| static inline |
| base_type norm_inf(argument_type z) { |
| return std::max(NumericTraits<base_type>::abs(traits_type::real(z)), |
| NumericTraits<base_type>::abs(traits_type::imag(z))); |
| } |
| |
| static inline |
| bool equals(argument_type lhs, argument_type rhs) { |
| return (traits_type::real(lhs) == traits_type::real(rhs)) |
| && (traits_type::imag(lhs) == traits_type::imag(rhs)); |
| } |
| |
| enum { is_complex = true }; |
| |
| /** Complexity on operations. */ |
| enum { |
| ops_plus = 2, /**< Complexity on plus/minus ops. */ |
| ops_muls = 6 /**< Complexity on multiplications. */ |
| }; |
| }; |
| |
| |
| /** |
| * \class NumericTraits< std::complex<unsigned int> > NumericTraits.h "tvmet/NumericTraits.h" |
| * \brief Traits specialized for std::complex<unsigned int>. |
| * |
| * \note Normally it doesn't make sense to call <tt>conj</tt> |
| * for an unsigned type! An unary minus operator |
| * applied to unsigned type will result unsigned. Therefore |
| * this function is missing here. |
| */ |
| template<> |
| struct NumericTraits< std::complex<unsigned int> > { |
| typedef unsigned int base_type; |
| typedef std::complex<unsigned int> value_type; |
| typedef std::complex<unsigned long> sum_type; |
| typedef std::complex<int> diff_type; |
| typedef std::complex<float> float_type; |
| typedef std::complex<int> signed_type; |
| |
| typedef NumericTraits<value_type> traits_type; |
| typedef const value_type& argument_type; |
| |
| static inline |
| base_type real(argument_type z) { return std::real(z); } |
| |
| static inline |
| base_type imag(argument_type z) { return std::imag(z); } |
| |
| static inline |
| base_type abs(argument_type z) { |
| base_type x = z.real(); |
| base_type y = z.imag(); |
| |
| // XXX probably case of overrun; header complex uses scaling |
| return static_cast<base_type>(NumericTraits<base_type>::sqrt(x * x + y * y)); |
| } |
| |
| static /* inline */ |
| value_type sqrt(argument_type z) { |
| // borrowed and adapted from header complex |
| base_type x = z.real(); |
| base_type y = z.imag(); |
| |
| if(x == base_type()) { |
| base_type t = NumericTraits<base_type>::sqrt( |
| NumericTraits<base_type>::abs(y) / 2); |
| return value_type(t, t); |
| } |
| else { |
| base_type t = NumericTraits<base_type>::sqrt( |
| 2 * (traits_type::abs(z) |
| + NumericTraits<base_type>::abs(x))); |
| return value_type(t / 2, y / t); |
| } |
| } |
| |
| static inline |
| base_type norm_1(argument_type z) { |
| return NumericTraits<base_type>::abs((traits_type::real(z))) |
| + NumericTraits<base_type>::abs((traits_type::imag(z))); |
| } |
| |
| static inline |
| base_type norm_2(argument_type z) { return traits_type::abs(z); } |
| |
| static inline |
| base_type norm_inf(argument_type z) { |
| return std::max(NumericTraits<base_type>::abs(traits_type::real(z)), |
| NumericTraits<base_type>::abs(traits_type::imag(z))); |
| } |
| |
| static inline |
| bool equals(argument_type lhs, argument_type rhs) { |
| return (traits_type::real(lhs) == traits_type::real(rhs)) |
| && (traits_type::imag(lhs) == traits_type::imag(rhs)); |
| } |
| |
| enum { is_complex = true }; |
| |
| /** Complexity on operations. */ |
| enum { |
| ops_plus = 2, /**< Complexity on plus/minus ops. */ |
| ops_muls = 6 /**< Complexity on multiplications. */ |
| }; |
| }; |
| |
| |
| /** |
| * \class NumericTraits< std::complex<long> > NumericTraits.h "tvmet/NumericTraits.h" |
| * \brief Traits specialized for std::complex<long>. |
| */ |
| template<> |
| struct NumericTraits< std::complex<long> > { |
| typedef long base_type; |
| typedef std::complex<long> value_type; |
| #if defined(TVMET_HAVE_LONG_LONG) |
| typedef std::complex<long long> sum_type; |
| #else |
| typedef std::complex<long> sum_type; |
| #endif |
| typedef std::complex<int> diff_type; |
| typedef std::complex<float> float_type; |
| typedef std::complex<int> signed_type; |
| |
| typedef NumericTraits<value_type> traits_type; |
| typedef const value_type& argument_type; |
| |
| static inline |
| base_type real(argument_type z) { return std::real(z); } |
| |
| static inline |
| base_type imag(argument_type z) { return std::imag(z); } |
| |
| static inline |
| value_type conj(argument_type z) { return std::conj(z); } |
| |
| static inline |
| base_type abs(argument_type z) { |
| base_type x = z.real(); |
| base_type y = z.imag(); |
| |
| // XXX probably case of overrun; header complex uses scaling |
| return static_cast<base_type>(NumericTraits<base_type>::sqrt(x * x + y * y)); |
| } |
| |
| static /* inline */ |
| value_type sqrt(argument_type z) { |
| // borrowed and adapted from header complex |
| base_type x = z.real(); |
| base_type y = z.imag(); |
| |
| if(x == base_type()) { |
| base_type t = NumericTraits<base_type>::sqrt( |
| NumericTraits<base_type>::abs(y) / 2); |
| return value_type(t, y < base_type() ? -t : t); |
| } |
| else { |
| base_type t = NumericTraits<base_type>::sqrt( |
| 2 * (traits_type::abs(z) |
| + NumericTraits<base_type>::abs(x))); |
| base_type u = t / 2; |
| return x > base_type() |
| ? value_type(u, y / t) |
| : value_type(NumericTraits<base_type>::abs(y) / t, y < base_type() ? -u : u); |
| } |
| } |
| |
| static inline |
| base_type norm_1(argument_type z) { |
| return NumericTraits<base_type>::abs((traits_type::real(z))) |
| + NumericTraits<base_type>::abs((traits_type::imag(z))); |
| } |
| |
| static inline |
| base_type norm_2(argument_type z) { return traits_type::abs(z); } |
| |
| static inline |
| base_type norm_inf(argument_type z) { |
| return std::max(NumericTraits<base_type>::abs(traits_type::real(z)), |
| NumericTraits<base_type>::abs(traits_type::imag(z))); |
| } |
| |
| static inline |
| bool equals(argument_type lhs, argument_type rhs) { |
| return (traits_type::real(lhs) == traits_type::real(rhs)) |
| && (traits_type::imag(lhs) == traits_type::imag(rhs)); |
| } |
| |
| enum { is_complex = true }; |
| |
| /** Complexity on operations. */ |
| enum { |
| ops_plus = 2, /**< Complexity on plus/minus ops. */ |
| ops_muls = 6 /**< Complexity on multiplications. */ |
| }; |
| }; |
| |
| |
| /** |
| * \class NumericTraits< std::complex<unsigned long> > NumericTraits.h "tvmet/NumericTraits.h" |
| * \brief Traits specialized for std::complex<unsigned long>. |
| * |
| * \note Normally it doesn't make sense to call <tt>conj</tt> |
| * for an unsigned type! An unary minus operator |
| * applied to unsigned type will result unsigned. Therefore |
| * this function is missing here. |
| */ |
| template<> |
| struct NumericTraits< std::complex<unsigned long> > { |
| typedef unsigned long base_type; |
| typedef std::complex<unsigned long> value_type; |
| #if defined(TVMET_HAVE_LONG_LONG) |
| typedef std::complex<unsigned long long> sum_type; |
| #else |
| typedef std::complex<unsigned long> sum_type; |
| #endif |
| typedef std::complex<long> diff_type; |
| typedef std::complex<float> float_type; |
| typedef std::complex<long> signed_type; |
| |
| typedef NumericTraits<value_type> traits_type; |
| typedef const value_type& argument_type; |
| |
| static inline |
| base_type real(argument_type z) { return std::real(z); } |
| |
| static inline |
| base_type imag(argument_type z) { return std::imag(z); } |
| |
| static inline |
| base_type abs(argument_type z) { |
| base_type x = z.real(); |
| base_type y = z.imag(); |
| |
| // XXX probably case of overrun; header complex uses scaling |
| return static_cast<base_type>(NumericTraits<base_type>::sqrt(x * x + y * y)); |
| } |
| |
| static /* inline */ |
| value_type sqrt(argument_type z) { |
| // borrowed and adapted from header complex |
| base_type x = z.real(); |
| base_type y = z.imag(); |
| |
| if(x == base_type()) { |
| base_type t = NumericTraits<base_type>::sqrt( |
| NumericTraits<base_type>::abs(y) / 2); |
| return value_type(t, t); |
| } |
| else { |
| base_type t = NumericTraits<base_type>::sqrt( |
| 2 * (traits_type::abs(z) |
| + NumericTraits<base_type>::abs(x))); |
| return value_type(t / 2, y / t); |
| } |
| } |
| |
| static inline |
| base_type norm_1(argument_type z) { |
| return NumericTraits<base_type>::abs((traits_type::real(z))) |
| + NumericTraits<base_type>::abs((traits_type::imag(z))); |
| } |
| |
| static inline |
| base_type norm_2(argument_type z) { return traits_type::abs(z); } |
| |
| static inline |
| base_type norm_inf(argument_type z) { |
| return std::max(NumericTraits<base_type>::abs(traits_type::real(z)), |
| NumericTraits<base_type>::abs(traits_type::imag(z))); |
| } |
| |
| static inline |
| bool equals(argument_type lhs, argument_type rhs) { |
| return (traits_type::real(lhs) == traits_type::real(rhs)) |
| && (traits_type::imag(lhs) == traits_type::imag(rhs)); |
| } |
| |
| enum { is_complex = true }; |
| |
| /** Complexity on operations.*/ |
| enum { |
| ops_plus = 2, /**< Complexity on plus/minus ops. */ |
| ops_muls = 6 /**< Complexity on multiplications. */ |
| }; |
| }; |
| |
| |
| /** |
| * \class NumericTraits< std::complex<float> > NumericTraits.h "tvmet/NumericTraits.h" |
| * \brief Traits specialized for std::complex<float>. |
| */ |
| template<> |
| struct NumericTraits< std::complex<float> > { |
| typedef float base_type; |
| typedef std::complex<float> value_type; |
| typedef std::complex<double> sum_type; |
| typedef std::complex<float> diff_type; |
| typedef std::complex<float> float_type; |
| typedef std::complex<float> signed_type; |
| |
| typedef NumericTraits<value_type> traits_type; |
| typedef const value_type& argument_type; |
| |
| static inline |
| base_type real(argument_type z) { return std::real(z); } |
| |
| static inline |
| base_type imag(argument_type z) { return std::imag(z); } |
| |
| static inline |
| value_type conj(argument_type z) { return std::conj(z); } |
| |
| static inline |
| base_type abs(argument_type z) { return std::abs(z); } |
| |
| static inline |
| value_type sqrt(argument_type z) { return std::sqrt(z); } |
| |
| static inline |
| base_type norm_1(argument_type z) { |
| return NumericTraits<base_type>::abs((traits_type::real(z))) |
| + NumericTraits<base_type>::abs((traits_type::imag(z))); |
| } |
| |
| static inline |
| base_type norm_2(argument_type z) { return traits_type::abs(z); } |
| |
| static inline |
| base_type norm_inf(argument_type z) { |
| return std::max(NumericTraits<base_type>::abs(traits_type::real(z)), |
| NumericTraits<base_type>::abs(traits_type::imag(z))); |
| } |
| |
| static inline |
| bool equals(argument_type lhs, argument_type rhs) { |
| static base_type sqrt_epsilon( |
| NumericTraits<base_type>::sqrt( |
| std::numeric_limits<base_type>::epsilon())); |
| |
| return traits_type::norm_inf(lhs - rhs) < sqrt_epsilon * |
| std::max(std::max(traits_type::norm_inf(lhs), |
| traits_type::norm_inf(rhs)), |
| std::numeric_limits<base_type>::min()); |
| } |
| |
| enum { is_complex = true }; |
| |
| /** Complexity on operations. */ |
| enum { |
| ops_plus = 2, /**< Complexity on plus/minus ops. */ |
| ops_muls = 6 /**< Complexity on multiplications. */ |
| }; |
| }; |
| |
| |
| /** |
| * \class NumericTraits< std::complex<double> > NumericTraits.h "tvmet/NumericTraits.h" |
| * \brief Traits specialized for std::complex<double>. |
| */ |
| template<> |
| struct NumericTraits< std::complex<double> > { |
| typedef double base_type; |
| typedef std::complex<double> value_type; |
| #if defined(TVMET_HAVE_LONG_DOUBLE) |
| typedef std::complex<long double> sum_type; |
| #else |
| typedef std::complex<double> sum_type; |
| #endif |
| typedef std::complex<double> diff_type; |
| typedef std::complex<double> float_type; |
| typedef std::complex<double> signed_type; |
| |
| typedef NumericTraits<value_type> traits_type; |
| typedef const value_type& argument_type; |
| |
| static inline |
| base_type real(argument_type z) { return std::real(z); } |
| |
| static inline |
| base_type imag(argument_type z) { return std::imag(z); } |
| |
| static inline |
| value_type conj(argument_type z) { return std::conj(z); } |
| |
| static inline |
| base_type abs(argument_type z) { return std::abs(z); } |
| |
| static inline |
| value_type sqrt(argument_type z) { return std::sqrt(z); } |
| |
| static inline |
| base_type norm_1(argument_type z) { |
| return NumericTraits<base_type>::abs((traits_type::real(z))) |
| + NumericTraits<base_type>::abs((traits_type::imag(z))); |
| } |
| |
| static inline |
| base_type norm_2(argument_type z) { return traits_type::abs(z); } |
| |
| static inline |
| base_type norm_inf(argument_type z) { |
| return std::max(NumericTraits<base_type>::abs(traits_type::real(z)), |
| NumericTraits<base_type>::abs(traits_type::imag(z))); |
| } |
| |
| static inline |
| bool equals(argument_type lhs, argument_type rhs) { |
| static base_type sqrt_epsilon( |
| NumericTraits<base_type>::sqrt( |
| std::numeric_limits<base_type>::epsilon())); |
| |
| return traits_type::norm_inf(lhs - rhs) < sqrt_epsilon * |
| std::max(std::max(traits_type::norm_inf(lhs), |
| traits_type::norm_inf(rhs)), |
| std::numeric_limits<base_type>::min()); |
| } |
| |
| enum { is_complex = true }; |
| |
| /** Complexity on operations. */ |
| enum { |
| ops_plus = 2, /**< Complexity on plus/minus ops. */ |
| ops_muls = 6 /**< Complexity on multiplications. */ |
| }; |
| }; |
| |
| |
| #if defined(TVMET_HAVE_LONG_DOUBLE) |
| /** |
| * \class NumericTraits< std::complex<long double> > NumericTraits.h "tvmet/NumericTraits.h" |
| * \brief Traits specialized for std::complex<double>. |
| */ |
| template<> |
| struct NumericTraits< std::complex<long double> > { |
| typedef long double base_type; |
| typedef std::complex<long double> value_type; |
| typedef std::complex<long double> sum_type; |
| typedef std::complex<long double> diff_type; |
| typedef std::complex<long double> float_type; |
| typedef std::complex<long double> signed_type; |
| |
| typedef NumericTraits<value_type> traits_type; |
| typedef const value_type& argument_type; |
| |
| static inline |
| base_type real(argument_type z) { return std::real(z); } |
| |
| static inline |
| base_type imag(argument_type z) { return std::imag(z); } |
| |
| static inline |
| value_type conj(argument_type z) { return std::conj(z); } |
| |
| static inline |
| base_type abs(argument_type z) { return std::abs(z); } |
| |
| static inline |
| value_type sqrt(argument_type z) { return std::sqrt(z); } |
| |
| static inline |
| base_type norm_1(argument_type z) { |
| return NumericTraits<base_type>::abs((traits_type::real(z))) |
| + NumericTraits<base_type>::abs((traits_type::imag(z))); |
| } |
| |
| static inline |
| base_type norm_2(argument_type z) { return traits_type::abs(z); } |
| |
| static inline |
| base_type norm_inf(argument_type z) { |
| return std::max(NumericTraits<base_type>::abs(traits_type::real(z)), |
| NumericTraits<base_type>::abs(traits_type::imag(z))); |
| } |
| |
| static inline |
| bool equals(argument_type lhs, argument_type rhs) { |
| static base_type sqrt_epsilon( |
| NumericTraits<base_type>::sqrt( |
| std::numeric_limits<base_type>::epsilon())); |
| |
| return traits_type::norm_inf(lhs - rhs) < sqrt_epsilon * |
| std::max(std::max(traits_type::norm_inf(lhs), |
| traits_type::norm_inf(rhs)), |
| std::numeric_limits<base_type>::min()); |
| } |
| |
| enum { is_complex = true }; |
| |
| /** Complexity on operations. */ |
| enum { |
| ops_plus = 2, /**< Complexity on plus/minus ops. */ |
| ops_muls = 6 /**< Complexity on multiplications. */ |
| }; |
| }; |
| #endif // defined(TVMET_HAVE_LONG_DOUBLE) |
| |
| |
| #endif // defined(TVMET_HAVE_COMPLEX) |
| |
| |
| } // namespace tvmet |
| |
| |
| #endif // TVMET_NUMERIC_TRAITS_H |
| |
| |
| // Local Variables: |
| // mode:C++ |
| // End: |