ICRS Eurobot 2013

Dependencies:   mbed mbed-rtos Servo QEI

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers NumericTraits.h Source File

NumericTraits.h

00001 /*
00002  * Tiny Vector Matrix Library
00003  * Dense Vector Matrix Libary of Tiny size using Expression Templates
00004  *
00005  * Copyright (C) 2001 - 2007 Olaf Petzold <opetzold@users.sourceforge.net>
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  *
00021  * $Id: NumericTraits.h,v 1.16 2007-06-23 15:58:58 opetzold Exp $
00022  */
00023 
00024 #ifndef TVMET_NUMERIC_TRAITS_H
00025 #define TVMET_NUMERIC_TRAITS_H
00026 
00027 #if defined(TVMET_HAVE_COMPLEX)
00028 #  include <complex>
00029 #endif
00030 #include <cmath>
00031 #include <limits>
00032 
00033 #include <tvmet/CompileTimeError.h>
00034 
00035 
00036 namespace tvmet {
00037 
00038 
00039 /**
00040  * \class NumericTraits NumericTraits.h "tvmet/NumericTraits.h"
00041  * \brief Traits for integral types for operations.
00042  *
00043  * For each type we have to specialize this traits.
00044  *
00045  * \note Keep in mind that the long types long long and long double doesn't
00046  *       have traits. This is due to the sum_type. We can't give a guarantee
00047  *       that there is a type of holding the sum. Therefore using this traits
00048  *       is only safe if you have long long resp. long double types by
00049  *       working on long ints and doubles. Otherwise you will get not expected
00050  *       result for some circumstances. Anyway, you can use big integer/float
00051  *       libraries and specialize the traits by your own.
00052  *
00053  * \todo The abs function of complex<non_float_type> can have an
00054  *       overrun due to numeric computation. Solve it (someone
00055  *       using value_type=long here?)
00056  */
00057 template<class T>
00058 struct NumericTraits {
00059   typedef T                    base_type;
00060   typedef T                    value_type;
00061   typedef value_type                sum_type;
00062   typedef value_type                diff_type;
00063   typedef value_type                float_type;
00064   typedef value_type                signed_type;
00065 
00066   typedef NumericTraits<value_type>        traits_type;
00067   typedef const value_type&            argument_type;
00068 
00069   static inline
00070   base_type real(argument_type x);
00071 
00072   static inline
00073   base_type imag(argument_type x);
00074 
00075   static inline
00076   value_type conj(argument_type x);
00077 
00078   static inline
00079   base_type abs(argument_type x);
00080 
00081   static inline
00082   value_type sqrt(argument_type x);
00083 
00084   static inline
00085   base_type norm_1(argument_type x) {
00086     return NumericTraits<base_type>::abs(traits_type::real(x))
00087          + NumericTraits<base_type>::abs(traits_type::imag(x));
00088   }
00089 
00090   static inline
00091   base_type norm_2(argument_type x) { return traits_type::abs(x); }
00092 
00093   static inline
00094   base_type norm_inf(argument_type x) {
00095     return std::max(NumericTraits<base_type>::abs(traits_type::real(x)),
00096             NumericTraits<base_type>::abs(traits_type::imag(x)));
00097    }
00098 
00099   static inline
00100   bool equals(argument_type lhs, argument_type rhs) {
00101     static base_type sqrt_epsilon(
00102       NumericTraits<base_type>::sqrt(
00103         std::numeric_limits<base_type>::epsilon()));
00104 
00105     return traits_type::norm_inf(lhs - rhs) < sqrt_epsilon *
00106       std::max(std::max(traits_type::norm_inf(lhs),
00107             traits_type::norm_inf(rhs)),
00108            std::numeric_limits<base_type>::min());
00109   }
00110 };
00111 
00112 
00113 /*
00114  * numeric traits for standard types
00115  */
00116 
00117 
00118 /**
00119  * \class NumericTraits<char> NumericTraits.h "tvmet/NumericTraits.h"
00120  * \brief Traits specialized for char.
00121  */
00122 template<>
00123 struct NumericTraits<char> {
00124   typedef char                    value_type;
00125   typedef value_type                base_type;
00126   typedef long                    sum_type;
00127   typedef int                    diff_type;
00128   typedef float                    float_type;
00129   typedef char                    signed_type;
00130 
00131   typedef NumericTraits<value_type>        traits_type;
00132   typedef value_type                argument_type;
00133 
00134   static inline
00135   base_type real(argument_type x) { return x; }
00136 
00137   static inline
00138   base_type imag(argument_type) { return 0; }
00139 
00140   static inline
00141   value_type conj(argument_type x) { return x; }
00142 
00143   static inline
00144   base_type abs(argument_type x) { return std::abs(x); }
00145 
00146   static inline
00147   value_type sqrt(argument_type x) {
00148     return static_cast<value_type>(std::sqrt(static_cast<float_type>(x)));
00149   }
00150 
00151   static inline
00152   base_type norm_1(argument_type x) { return traits_type::abs(x); }
00153 
00154   static inline
00155   base_type norm_2(argument_type x) { return traits_type::abs(x); }
00156 
00157   static inline
00158   base_type norm_inf(argument_type x) { return traits_type::abs(x); }
00159 
00160   static inline
00161   bool equals(argument_type lhs, argument_type rhs) { return lhs == rhs; }
00162 
00163   enum { is_complex = false };
00164 
00165   /** Complexity on operations. */
00166   enum {
00167     ops_plus = 1,    /**< Complexity on plus/minus ops. */
00168     ops_muls = 1    /**< Complexity on multiplications. */
00169   };
00170 };
00171 
00172 
00173 /**
00174  * \class NumericTraits<unsigned char> NumericTraits.h "tvmet/NumericTraits.h"
00175  * \brief Traits specialized for unsigned char.
00176  *
00177  * \note Normally it doesn't make sense to call <tt>conj</tt>
00178  *       for an unsigned type! An unary minus operator
00179  *       applied to unsigned type will result unsigned. Therefore
00180  *       this function is missing here.
00181  */
00182 template<>
00183 struct NumericTraits<unsigned char> {
00184   typedef unsigned char             value_type;
00185   typedef value_type                base_type;
00186   typedef unsigned long                 sum_type;
00187   typedef int                     diff_type;
00188   typedef float                     float_type;
00189   typedef int                    signed_type;
00190 
00191   typedef NumericTraits<value_type>        traits_type;
00192   typedef value_type                argument_type;
00193 
00194   static inline
00195   base_type real(argument_type x) { return x; }
00196 
00197   static inline
00198   base_type imag(argument_type) { return 0; }
00199 
00200   static inline
00201   base_type abs(argument_type x) { return std::abs(x); }
00202 
00203   static inline
00204   value_type sqrt(argument_type x) {
00205     return static_cast<value_type>(std::sqrt(static_cast<float_type>(x)));
00206   }
00207 
00208   static inline
00209   base_type norm_1(argument_type x) { return traits_type::abs(x); }
00210 
00211   static inline
00212   base_type norm_2(argument_type x) { return traits_type::abs(x); }
00213 
00214   static inline
00215   base_type norm_inf(argument_type x) { return traits_type::abs(x); }
00216 
00217   static inline
00218   bool equals(argument_type lhs, argument_type rhs) { return lhs == rhs; }
00219 
00220   enum { is_complex = false };
00221 
00222   /** Complexity on operations. */
00223   enum {
00224     ops_plus = 1,    /**< Complexity on plus/minus ops. */
00225     ops_muls = 1    /**< Complexity on multiplications. */
00226   };
00227 };
00228 
00229 
00230 /**
00231  * \class NumericTraits<short int> NumericTraits.h "tvmet/NumericTraits.h"
00232  * \brief Traits specialized for short int.
00233  */
00234 template<>
00235 struct NumericTraits<short int> {
00236   typedef short int                 value_type;
00237   typedef value_type                base_type;
00238 #if defined(TVMET_HAVE_LONG_LONG)
00239   typedef long long                 sum_type;
00240 #else
00241   typedef long                     sum_type;
00242 #endif
00243   typedef int                     diff_type;
00244   typedef float                 float_type;
00245   typedef short int                signed_type;
00246 
00247   typedef NumericTraits<value_type>        traits_type;
00248   typedef value_type                argument_type;
00249 
00250   static inline
00251   base_type real(argument_type x) { return x; }
00252 
00253   static inline
00254   base_type imag(argument_type) { return 0; }
00255 
00256   static inline
00257   value_type conj(argument_type x) { return x; }
00258 
00259   static inline
00260   base_type abs(argument_type x) { return std::abs(x); }
00261 
00262   static inline
00263   value_type sqrt(argument_type x) {
00264     return static_cast<value_type>(std::sqrt(static_cast<float_type>(x)));
00265   }
00266 
00267   static inline
00268   base_type norm_1(argument_type x) { return traits_type::abs(x); }
00269 
00270   static inline
00271   base_type norm_2(argument_type x) { return traits_type::abs(x); }
00272 
00273   static inline
00274   base_type norm_inf(argument_type x) { return traits_type::abs(x); }
00275 
00276   static inline
00277   bool equals(argument_type lhs, argument_type rhs) { return lhs == rhs; }
00278 
00279   enum { is_complex = false };
00280 
00281   /** Complexity on operations. */
00282   enum {
00283     ops_plus = 1,    /**< Complexity on plus/minus ops. */
00284     ops_muls = 1    /**< Complexity on multiplications. */
00285   };
00286 };
00287 
00288 
00289 /**
00290  * \class NumericTraits<short unsigned int> NumericTraits.h "tvmet/NumericTraits.h"
00291  * \brief Traits specialized for short unsigned int.
00292  *
00293  * \note Normally it doesn't make sense to call <tt>conj</tt>
00294  *       for an unsigned type! An unary minus operator
00295  *       applied to unsigned type will result unsigned. Therefore
00296  *       this function is missing here.
00297  */
00298 template<>
00299 struct NumericTraits<short unsigned int> {
00300   typedef short unsigned int            value_type;
00301   typedef value_type                base_type;
00302 #if defined(TVMET_HAVE_LONG_LONG)
00303   typedef unsigned long long            sum_type;
00304 #else
00305   typedef unsigned long             sum_type;
00306 #endif
00307   typedef int                     diff_type;
00308   typedef float                 float_type;
00309   typedef int                    signed_type;
00310 
00311   typedef NumericTraits<value_type>        traits_type;
00312   typedef value_type                argument_type;
00313 
00314   static inline
00315   base_type real(argument_type x) { return x; }
00316 
00317   static inline
00318   base_type imag(argument_type) { return 0; }
00319 
00320   static inline
00321   base_type abs(argument_type x) { return std::abs(x); }
00322 
00323   static inline
00324   value_type sqrt(argument_type x) {
00325     return static_cast<value_type>(std::sqrt(static_cast<float_type>(x)));
00326   }
00327 
00328   static inline
00329   base_type norm_1(argument_type x) { return traits_type::abs(x); }
00330 
00331   static inline
00332   base_type norm_2(argument_type x) { return traits_type::abs(x); }
00333 
00334   static inline
00335   base_type norm_inf(argument_type x) { return traits_type::abs(x); }
00336 
00337   static inline
00338   bool equals(argument_type lhs, argument_type rhs) { return lhs == rhs; }
00339 
00340   enum { is_complex = false };
00341 
00342   /** Complexity on operations. */
00343   enum {
00344     ops_plus = 1,    /**< Complexity on plus/minus ops. */
00345     ops_muls = 1    /**< Complexity on multiplications. */
00346   };
00347 };
00348 
00349 
00350 /**
00351  * \class NumericTraits<int> NumericTraits.h "tvmet/NumericTraits.h"
00352  * \brief Traits specialized for int.
00353  */
00354 template<>
00355 struct NumericTraits<int> {
00356   typedef int                     value_type;
00357   typedef value_type                base_type;
00358 #if defined(TVMET_HAVE_LONG_LONG)
00359   typedef long long                 sum_type;
00360 #else
00361   typedef long                     sum_type;
00362 #endif
00363   typedef int                     diff_type;
00364   typedef double                 float_type;
00365   typedef int                    signed_type;
00366 
00367   typedef NumericTraits<value_type>        traits_type;
00368   typedef value_type                argument_type;
00369 
00370   static inline
00371   base_type real(argument_type x) { return x; }
00372 
00373   static inline
00374   base_type imag(argument_type) { return 0; }
00375 
00376   static inline
00377   value_type conj(argument_type x) { return x; }
00378 
00379   static inline
00380   base_type abs(argument_type x) { return std::abs(x); }
00381 
00382   static inline
00383   value_type sqrt(argument_type x) {
00384     return static_cast<value_type>(std::sqrt(static_cast<float_type>(x)));
00385   }
00386 
00387   static inline
00388   base_type norm_1(argument_type x) { return traits_type::abs(x); }
00389 
00390   static inline
00391   base_type norm_2(argument_type x) { return traits_type::abs(x); }
00392 
00393   static inline
00394   base_type norm_inf(argument_type x) { return traits_type::abs(x); }
00395 
00396   static inline
00397   bool equals(argument_type lhs, argument_type rhs) { return lhs == rhs; }
00398 
00399   enum { is_complex = false };
00400 
00401   /** Complexity on operations. */
00402   enum {
00403     ops_plus = 1,    /**< Complexity on plus/minus ops. */
00404     ops_muls = 1    /**< Complexity on multiplications. */
00405   };
00406 };
00407 
00408 
00409 /**
00410  * \class NumericTraits<unsigned int> NumericTraits.h "tvmet/NumericTraits.h"
00411  * \brief Traits specialized for unsigned int.
00412  *
00413  * \note Normally it doesn't make sense to call <tt>conj</tt>
00414  *       for an unsigned type! An unary minus operator
00415  *       applied to unsigned type will result unsigned. Therefore
00416  *       this function is missing here.
00417  */
00418 template<>
00419 struct NumericTraits<unsigned int> {
00420   typedef unsigned int                  value_type;
00421   typedef value_type                base_type;
00422 #if defined(TVMET_HAVE_LONG_LONG)
00423   typedef unsigned long long            sum_type;
00424 #else
00425   typedef unsigned long             sum_type;
00426 #endif
00427   typedef int                      diff_type;
00428   typedef double                 float_type;
00429   typedef long                     signed_type;
00430 
00431   typedef NumericTraits<value_type>        traits_type;
00432   typedef value_type                argument_type;
00433 
00434   static inline
00435   base_type real(argument_type x) { return x; }
00436 
00437   static inline
00438   base_type imag(argument_type) { return 0; }
00439 
00440   static inline
00441   base_type abs(argument_type x) { return x; }
00442 
00443   static inline
00444   value_type sqrt(argument_type x) {
00445     return static_cast<value_type>(std::sqrt(static_cast<float_type>(x)));
00446   }
00447 
00448   static inline
00449   base_type norm_1(argument_type x) { return traits_type::abs(x); }
00450 
00451   static inline
00452   base_type norm_2(argument_type x) { return traits_type::abs(x); }
00453 
00454   static inline
00455   base_type norm_inf(argument_type x) { return traits_type::abs(x); }
00456 
00457   static inline
00458   bool equals(argument_type lhs, argument_type rhs) { return lhs == rhs; }
00459 
00460   enum { is_complex = false };
00461 
00462   /** Complexity on operations. */
00463   enum {
00464     ops_plus = 1,    /**< Complexity on plus/minus ops. */
00465     ops_muls = 1    /**< Complexity on multiplications. */
00466   };
00467 };
00468 
00469 
00470 /**
00471  * \class NumericTraits<long> NumericTraits.h "tvmet/NumericTraits.h"
00472  * \brief Traits specialized for long.
00473  */
00474 template<>
00475 struct NumericTraits<long> {
00476   typedef long                      value_type;
00477   typedef value_type                base_type;
00478 #if defined(TVMET_HAVE_LONG_LONG)
00479   typedef long long                 sum_type;
00480 #else
00481   typedef long                      sum_type;
00482 #endif
00483   typedef long                      diff_type;
00484   typedef double                 float_type;
00485   typedef long                      signed_type;
00486 
00487   typedef NumericTraits<value_type>        traits_type;
00488   typedef value_type                argument_type;
00489 
00490   static inline
00491   base_type real(argument_type x) { return x; }
00492 
00493   static inline
00494   base_type imag(argument_type) { return 0; }
00495 
00496   static inline
00497   value_type conj(argument_type x) { return x; }
00498 
00499   static inline
00500   base_type abs(argument_type x) { return std::abs(x); }
00501 
00502   static inline
00503   value_type sqrt(argument_type x) {
00504     return static_cast<value_type>(std::sqrt(static_cast<float_type>(x)));
00505   }
00506 
00507   static inline
00508   base_type norm_1(argument_type x) { return traits_type::abs(x); }
00509 
00510   static inline
00511   base_type norm_2(argument_type x) { return traits_type::abs(x); }
00512 
00513   static inline
00514   base_type norm_inf(argument_type x) { return traits_type::abs(x); }
00515 
00516   static inline
00517   bool equals(argument_type lhs, argument_type rhs) { return lhs == rhs; }
00518 
00519   enum { is_complex = false };
00520 
00521   /** Complexity on operations. */
00522   enum {
00523     ops_plus = 1,    /**< Complexity on plus/minus ops. */
00524     ops_muls = 1    /**< Complexity on multiplications. */
00525   };
00526 };
00527 
00528 
00529 /**
00530  * \class NumericTraits<unsigned long> NumericTraits.h "tvmet/NumericTraits.h"
00531  * \brief Traits specialized for unsigned long.
00532  *
00533  * \note Normally it doesn't make sense to call <tt>conj</tt>
00534  *       for an unsigned type! An unary minus operator
00535  *       applied to unsigned type will result unsigned. Therefore
00536  *       this function is missing here.
00537  */
00538 template<>
00539 struct NumericTraits<unsigned long> {
00540   typedef unsigned long             value_type;
00541   typedef value_type                base_type;
00542 #if defined(TVMET_HAVE_LONG_LONG)
00543   typedef unsigned long long             sum_type;
00544 #else
00545   typedef unsigned long             sum_type;
00546 #endif
00547   typedef unsigned long             diff_type;
00548   typedef double                 float_type;
00549   typedef long                    signed_type;
00550 
00551   typedef NumericTraits<value_type>        traits_type;
00552   typedef value_type                argument_type;
00553 
00554   static inline
00555   base_type real(argument_type x) { return x; }
00556 
00557   static inline
00558   base_type imag(argument_type) { return 0; }
00559 
00560   static inline
00561   base_type abs(argument_type x) { return x; }
00562 
00563   static inline
00564   value_type sqrt(argument_type x) {
00565     return static_cast<value_type>(std::sqrt(static_cast<float_type>(x)));
00566   }
00567 
00568   static inline
00569   base_type norm_1(argument_type x) { return traits_type::abs(x); }
00570 
00571   static inline
00572   base_type norm_2(argument_type x) { return traits_type::abs(x); }
00573 
00574   static inline
00575   base_type norm_inf(argument_type x) { return traits_type::abs(x); }
00576 
00577   static inline
00578   bool equals(argument_type lhs, argument_type rhs) { return lhs == rhs; }
00579 
00580   enum { is_complex = false };
00581 
00582   /** Complexity on operations. */
00583   enum {
00584     ops_plus = 1,    /**< Complexity on plus/minus ops. */
00585     ops_muls = 1    /**< Complexity on multiplications. */
00586   };
00587 };
00588 
00589 
00590 /**
00591  * \class NumericTraits<float> NumericTraits.h "tvmet/NumericTraits.h"
00592  * \brief Traits specialized for float.
00593  */
00594 template<>
00595 struct NumericTraits<float> {
00596   typedef float                    value_type;
00597   typedef value_type                base_type;
00598   typedef double                 sum_type;
00599   typedef float                 diff_type;
00600   typedef float                 float_type;
00601   typedef float                    signed_type;
00602 
00603   typedef NumericTraits<value_type>        traits_type;
00604   typedef value_type                argument_type;
00605 
00606   static inline
00607   base_type real(argument_type x) { return x; }
00608 
00609   static inline
00610   base_type imag(argument_type) { return 0; }
00611 
00612   static inline
00613   value_type conj(argument_type x) { return x; }
00614 
00615   static inline
00616   base_type abs(argument_type x) { return std::abs(x); }
00617 
00618   static inline
00619   value_type sqrt(argument_type x) { return std::sqrt(x); }
00620 
00621   static inline
00622   base_type norm_1(argument_type x) { return traits_type::abs(x); }
00623 
00624   static inline
00625   base_type norm_2(argument_type x) { return traits_type::abs(x); }
00626 
00627   static inline
00628   base_type norm_inf(argument_type x) { return traits_type::abs(x); }
00629 
00630   static inline
00631   bool equals(argument_type lhs, argument_type rhs) {
00632     static base_type sqrt_epsilon(
00633       NumericTraits<base_type>::sqrt(
00634         std::numeric_limits<base_type>::epsilon()));
00635 
00636     return traits_type::norm_inf(lhs - rhs) < sqrt_epsilon *
00637       std::max(std::max(traits_type::norm_inf(lhs),
00638             traits_type::norm_inf(rhs)),
00639            std::numeric_limits<base_type>::min());
00640   }
00641 
00642   enum { is_complex = false };
00643 
00644   /** Complexity on operations. */
00645   enum {
00646     ops_plus = 1,    /**< Complexity on plus/minus ops. */
00647     ops_muls = 1    /**< Complexity on multiplications. */
00648   };
00649 };
00650 
00651 
00652 /**
00653  * \class NumericTraits<double> NumericTraits.h "tvmet/NumericTraits.h"
00654  * \brief Traits specialized for double.
00655  */
00656 template<>
00657 struct NumericTraits<double> {
00658   typedef double                 value_type;
00659   typedef value_type                base_type;
00660 #if defined(TVMET_HAVE_LONG_DOUBLE)
00661   typedef long double                 sum_type;
00662 #else
00663   typedef double                 sum_type;
00664 #endif
00665   typedef double                diff_type;
00666   typedef double                 float_type;
00667   typedef double                signed_type;
00668 
00669   typedef NumericTraits<value_type>        traits_type;
00670   typedef value_type                argument_type;
00671 
00672   static inline
00673   base_type real(argument_type x) { return x; }
00674 
00675   static inline
00676   base_type imag(argument_type) { return 0; }
00677 
00678   static inline
00679   value_type conj(argument_type x) { return x; }
00680 
00681   static inline
00682   base_type abs(argument_type x) { return std::abs(x); }
00683 
00684   static inline
00685   value_type sqrt(argument_type x) { return std::sqrt(x); }
00686 
00687   static inline
00688   base_type norm_1(argument_type x) { return traits_type::abs(x); }
00689 
00690   static inline
00691   base_type norm_2(argument_type x) { return traits_type::abs(x); }
00692 
00693   static inline
00694   base_type norm_inf(argument_type x) { return traits_type::abs(x); }
00695 
00696   static inline
00697   bool equals(argument_type lhs, argument_type rhs) {
00698     static base_type sqrt_epsilon(
00699       NumericTraits<base_type>::sqrt(
00700         std::numeric_limits<base_type>::epsilon()));
00701 
00702     return traits_type::norm_inf(lhs - rhs) < sqrt_epsilon *
00703       std::max(std::max(traits_type::norm_inf(lhs),
00704             traits_type::norm_inf(rhs)),
00705            std::numeric_limits<base_type>::min());
00706   }
00707 
00708   enum { is_complex = false };
00709 
00710   /** Complexity on operations. */
00711   enum {
00712     ops_plus = 1,    /**< Complexity on plus/minus ops. */
00713     ops_muls = 1    /**< Complexity on multiplications. */
00714   };
00715 };
00716 
00717 
00718 #if defined(TVMET_HAVE_LONG_DOUBLE)
00719 /**
00720  * \class NumericTraits<long double> NumericTraits.h "tvmet/NumericTraits.h"
00721  * \brief Traits specialized for long double.
00722  */
00723 template<>
00724 struct NumericTraits<long double> {
00725   typedef long double                 value_type;
00726   typedef value_type                base_type;
00727   typedef long double                 sum_type;
00728   typedef long double                diff_type;
00729   typedef long double                 float_type;
00730   typedef long double                signed_type;
00731 
00732   typedef NumericTraits<value_type>        traits_type;
00733   typedef value_type                argument_type;
00734 
00735   static inline
00736   base_type real(argument_type x) { return x; }
00737 
00738   static inline
00739   base_type imag(argument_type) { return 0; }
00740 
00741   static inline
00742   value_type conj(argument_type x) { return x; }
00743 
00744   static inline
00745   base_type abs(argument_type x) { return std::abs(x); }
00746 
00747   static inline
00748   value_type sqrt(argument_type x) { return std::sqrt(x); }
00749 
00750   static inline
00751   base_type norm_1(argument_type x) { return traits_type::abs(x); }
00752 
00753   static inline
00754   base_type norm_2(argument_type x) { return traits_type::abs(x); }
00755 
00756   static inline
00757   base_type norm_inf(argument_type x) { return traits_type::abs(x); }
00758 
00759   static inline
00760   bool equals(argument_type lhs, argument_type rhs) {
00761     static base_type sqrt_epsilon(
00762       NumericTraits<base_type>::sqrt(
00763         std::numeric_limits<base_type>::epsilon()));
00764 
00765     return traits_type::norm_inf(lhs - rhs) < sqrt_epsilon *
00766       std::max(std::max(traits_type::norm_inf(lhs),
00767             traits_type::norm_inf(rhs)),
00768            std::numeric_limits<base_type>::min());
00769   }
00770 
00771   enum { is_complex = false };
00772 
00773   /** Complexity on operations. */
00774   enum {
00775     ops_plus = 1,    /**< Complexity on plus/minus ops. */
00776     ops_muls = 1    /**< Complexity on multiplications. */
00777   };
00778 };
00779 #endif // TVMET_HAVE_LONG_DOUBLE
00780 
00781 
00782 /*
00783  * numeric traits for complex types
00784  */
00785 #if defined(TVMET_HAVE_COMPLEX)
00786 
00787 /**
00788  * \class NumericTraits< std::complex<int> > NumericTraits.h "tvmet/NumericTraits.h"
00789  * \brief Traits specialized for std::complex<int>.
00790  */
00791 template<>
00792 struct NumericTraits< std::complex<int> > {
00793   typedef int                    base_type;
00794   typedef std::complex<int>            value_type;
00795   typedef std::complex<long>             sum_type;
00796   typedef std::complex<int>            diff_type;
00797   typedef std::complex<float>            float_type;
00798   typedef std::complex<int>            signed_type;
00799 
00800   typedef NumericTraits<value_type>        traits_type;
00801   typedef const value_type&            argument_type;
00802 
00803   static inline
00804   base_type real(argument_type z) { return std::real(z); }
00805 
00806   static inline
00807   base_type imag(argument_type z) { return std::imag(z); }
00808 
00809   static inline
00810   value_type conj(argument_type z) { return std::conj(z); }
00811 
00812   static inline
00813   base_type abs(argument_type z) {
00814     base_type x = z.real();
00815     base_type y = z.imag();
00816 
00817     // XXX probably case of overrun; header complex uses scaling
00818     return static_cast<base_type>(NumericTraits<base_type>::sqrt(x * x + y * y));
00819   }
00820 
00821   static /* inline */
00822   value_type sqrt(argument_type z) {
00823     // borrowed and adapted from header complex
00824     base_type x = z.real();
00825     base_type y = z.imag();
00826 
00827     if(x == base_type()) {
00828     base_type t = NumericTraits<base_type>::sqrt(
00829                         NumericTraits<base_type>::abs(y) / 2);
00830     return value_type(t, y < base_type() ? -t : t);
00831     }
00832     else {
00833       base_type t = NumericTraits<base_type>::sqrt(
00834               2 * (traits_type::abs(z)
00835                     + NumericTraits<base_type>::abs(x)));
00836       base_type u = t / 2;
00837       return x > base_type()
00838     ? value_type(u, y / t)
00839     : value_type(NumericTraits<base_type>::abs(y) / t, y < base_type() ? -u : u);
00840     }
00841   }
00842 
00843   static inline
00844   base_type norm_1(argument_type z) {
00845     return NumericTraits<base_type>::abs((traits_type::real(z)))
00846          + NumericTraits<base_type>::abs((traits_type::imag(z)));
00847   }
00848 
00849   static inline
00850   base_type norm_2(argument_type z) { return traits_type::abs(z); }
00851 
00852   static inline
00853   base_type norm_inf(argument_type z) {
00854     return std::max(NumericTraits<base_type>::abs(traits_type::real(z)),
00855             NumericTraits<base_type>::abs(traits_type::imag(z)));
00856   }
00857 
00858   static inline
00859   bool equals(argument_type lhs, argument_type rhs) {
00860     return (traits_type::real(lhs) == traits_type::real(rhs))
00861         && (traits_type::imag(lhs) == traits_type::imag(rhs));
00862   }
00863 
00864   enum { is_complex = true };
00865 
00866   /** Complexity on operations. */
00867   enum {
00868     ops_plus = 2,    /**< Complexity on plus/minus ops. */
00869     ops_muls = 6    /**< Complexity on multiplications. */
00870   };
00871 };
00872 
00873 
00874 /**
00875  * \class NumericTraits< std::complex<unsigned int> > NumericTraits.h "tvmet/NumericTraits.h"
00876  * \brief Traits specialized for std::complex<unsigned int>.
00877  *
00878  * \note Normally it doesn't make sense to call <tt>conj</tt>
00879  *       for an unsigned type! An unary minus operator
00880  *       applied to unsigned type will result unsigned. Therefore
00881  *       this function is missing here.
00882  */
00883 template<>
00884 struct NumericTraits< std::complex<unsigned int> > {
00885   typedef unsigned int                base_type;
00886   typedef std::complex<unsigned int>         value_type;
00887   typedef std::complex<unsigned long>         sum_type;
00888   typedef std::complex<int>            diff_type;
00889   typedef std::complex<float>            float_type;
00890   typedef std::complex<int>            signed_type;
00891 
00892   typedef NumericTraits<value_type>        traits_type;
00893   typedef const value_type&            argument_type;
00894 
00895   static inline
00896   base_type real(argument_type z) { return std::real(z); }
00897 
00898   static inline
00899   base_type imag(argument_type z) { return std::imag(z); }
00900 
00901   static inline
00902   base_type abs(argument_type z) {
00903     base_type x = z.real();
00904     base_type y = z.imag();
00905 
00906     // XXX probably case of overrun; header complex uses scaling
00907     return static_cast<base_type>(NumericTraits<base_type>::sqrt(x * x + y * y));
00908   }
00909 
00910   static /* inline */
00911   value_type sqrt(argument_type z) {
00912     // borrowed and adapted from header complex
00913     base_type x = z.real();
00914     base_type y = z.imag();
00915 
00916     if(x == base_type()) {
00917     base_type t = NumericTraits<base_type>::sqrt(
00918                         NumericTraits<base_type>::abs(y) / 2);
00919     return value_type(t, t);
00920     }
00921     else {
00922       base_type t = NumericTraits<base_type>::sqrt(
00923               2 * (traits_type::abs(z)
00924                     + NumericTraits<base_type>::abs(x)));
00925       return value_type(t / 2, y / t);
00926     }
00927   }
00928 
00929   static inline
00930   base_type norm_1(argument_type z) {
00931     return NumericTraits<base_type>::abs((traits_type::real(z)))
00932          + NumericTraits<base_type>::abs((traits_type::imag(z)));
00933   }
00934 
00935   static inline
00936   base_type norm_2(argument_type z) { return traits_type::abs(z); }
00937 
00938   static inline
00939   base_type norm_inf(argument_type z) {
00940     return std::max(NumericTraits<base_type>::abs(traits_type::real(z)),
00941             NumericTraits<base_type>::abs(traits_type::imag(z)));
00942   }
00943 
00944   static inline
00945   bool equals(argument_type lhs, argument_type rhs) {
00946     return (traits_type::real(lhs) == traits_type::real(rhs))
00947         && (traits_type::imag(lhs) == traits_type::imag(rhs));
00948   }
00949 
00950   enum { is_complex = true };
00951 
00952   /** Complexity on operations. */
00953   enum {
00954     ops_plus = 2,    /**< Complexity on plus/minus ops. */
00955     ops_muls = 6    /**< Complexity on multiplications. */
00956   };
00957 };
00958 
00959 
00960 /**
00961  * \class NumericTraits< std::complex<long> > NumericTraits.h "tvmet/NumericTraits.h"
00962  * \brief Traits specialized for std::complex<long>.
00963  */
00964 template<>
00965 struct NumericTraits< std::complex<long> > {
00966   typedef long                    base_type;
00967   typedef std::complex<long>            value_type;
00968 #if defined(TVMET_HAVE_LONG_LONG)
00969   typedef std::complex<long long>        sum_type;
00970 #else
00971   typedef std::complex<long>            sum_type;
00972 #endif
00973   typedef std::complex<int>            diff_type;
00974   typedef std::complex<float>            float_type;
00975   typedef std::complex<int>            signed_type;
00976 
00977   typedef NumericTraits<value_type>        traits_type;
00978   typedef const value_type&            argument_type;
00979 
00980   static inline
00981   base_type real(argument_type z) { return std::real(z); }
00982 
00983   static inline
00984   base_type imag(argument_type z) { return std::imag(z); }
00985 
00986   static inline
00987   value_type conj(argument_type z) { return std::conj(z); }
00988 
00989   static inline
00990   base_type abs(argument_type z) {
00991     base_type x = z.real();
00992     base_type y = z.imag();
00993 
00994     // XXX probably case of overrun; header complex uses scaling
00995     return static_cast<base_type>(NumericTraits<base_type>::sqrt(x * x + y * y));
00996   }
00997 
00998   static /* inline */
00999   value_type sqrt(argument_type z) {
01000     // borrowed and adapted from header complex
01001     base_type x = z.real();
01002     base_type y = z.imag();
01003 
01004     if(x == base_type()) {
01005     base_type t = NumericTraits<base_type>::sqrt(
01006                         NumericTraits<base_type>::abs(y) / 2);
01007     return value_type(t, y < base_type() ? -t : t);
01008     }
01009     else {
01010       base_type t = NumericTraits<base_type>::sqrt(
01011               2 * (traits_type::abs(z)
01012                     + NumericTraits<base_type>::abs(x)));
01013       base_type u = t / 2;
01014       return x > base_type()
01015     ? value_type(u, y / t)
01016     : value_type(NumericTraits<base_type>::abs(y) / t, y < base_type() ? -u : u);
01017     }
01018   }
01019 
01020   static inline
01021   base_type norm_1(argument_type z) {
01022     return NumericTraits<base_type>::abs((traits_type::real(z)))
01023          + NumericTraits<base_type>::abs((traits_type::imag(z)));
01024   }
01025 
01026   static inline
01027   base_type norm_2(argument_type z) { return traits_type::abs(z); }
01028 
01029   static inline
01030   base_type norm_inf(argument_type z) {
01031     return std::max(NumericTraits<base_type>::abs(traits_type::real(z)),
01032             NumericTraits<base_type>::abs(traits_type::imag(z)));
01033   }
01034 
01035   static inline
01036   bool equals(argument_type lhs, argument_type rhs) {
01037     return (traits_type::real(lhs) == traits_type::real(rhs))
01038         && (traits_type::imag(lhs) == traits_type::imag(rhs));
01039   }
01040 
01041   enum { is_complex = true };
01042 
01043   /** Complexity on operations. */
01044   enum {
01045     ops_plus = 2,    /**< Complexity on plus/minus ops. */
01046     ops_muls = 6    /**< Complexity on multiplications. */
01047   };
01048 };
01049 
01050 
01051 /**
01052  * \class NumericTraits< std::complex<unsigned long> > NumericTraits.h "tvmet/NumericTraits.h"
01053  * \brief Traits specialized for std::complex<unsigned long>.
01054  *
01055  * \note Normally it doesn't make sense to call <tt>conj</tt>
01056  *       for an unsigned type! An unary minus operator
01057  *       applied to unsigned type will result unsigned. Therefore
01058  *       this function is missing here.
01059  */
01060 template<>
01061 struct NumericTraits< std::complex<unsigned long> > {
01062   typedef unsigned long                base_type;
01063   typedef std::complex<unsigned long>        value_type;
01064 #if defined(TVMET_HAVE_LONG_LONG)
01065   typedef std::complex<unsigned long long>    sum_type;
01066 #else
01067   typedef std::complex<unsigned long>        sum_type;
01068 #endif
01069   typedef std::complex<long>            diff_type;
01070   typedef std::complex<float>            float_type;
01071   typedef std::complex<long>            signed_type;
01072 
01073   typedef NumericTraits<value_type>        traits_type;
01074   typedef const value_type&            argument_type;
01075 
01076   static inline
01077   base_type real(argument_type z) { return std::real(z); }
01078 
01079   static inline
01080   base_type imag(argument_type z) { return std::imag(z); }
01081 
01082   static inline
01083   base_type abs(argument_type z) {
01084     base_type x = z.real();
01085     base_type y = z.imag();
01086 
01087     // XXX probably case of overrun; header complex uses scaling
01088     return static_cast<base_type>(NumericTraits<base_type>::sqrt(x * x + y * y));
01089   }
01090 
01091   static /* inline */
01092   value_type sqrt(argument_type z) {
01093     // borrowed and adapted from header complex
01094     base_type x = z.real();
01095     base_type y = z.imag();
01096 
01097     if(x == base_type()) {
01098     base_type t = NumericTraits<base_type>::sqrt(
01099                         NumericTraits<base_type>::abs(y) / 2);
01100     return value_type(t, t);
01101     }
01102     else {
01103       base_type t = NumericTraits<base_type>::sqrt(
01104               2 * (traits_type::abs(z)
01105                     + NumericTraits<base_type>::abs(x)));
01106       return value_type(t / 2, y / t);
01107     }
01108   }
01109 
01110   static inline
01111   base_type norm_1(argument_type z) {
01112     return NumericTraits<base_type>::abs((traits_type::real(z)))
01113          + NumericTraits<base_type>::abs((traits_type::imag(z)));
01114   }
01115 
01116   static inline
01117   base_type norm_2(argument_type z) { return traits_type::abs(z); }
01118 
01119   static inline
01120   base_type norm_inf(argument_type z) {
01121     return std::max(NumericTraits<base_type>::abs(traits_type::real(z)),
01122             NumericTraits<base_type>::abs(traits_type::imag(z)));
01123   }
01124 
01125   static inline
01126   bool equals(argument_type lhs, argument_type rhs) {
01127     return (traits_type::real(lhs) == traits_type::real(rhs))
01128         && (traits_type::imag(lhs) == traits_type::imag(rhs));
01129   }
01130 
01131   enum { is_complex = true };
01132 
01133   /** Complexity  on operations.*/
01134   enum {
01135     ops_plus = 2,    /**< Complexity on plus/minus ops. */
01136     ops_muls = 6    /**< Complexity on multiplications. */
01137   };
01138 };
01139 
01140 
01141 /**
01142  * \class NumericTraits< std::complex<float> > NumericTraits.h "tvmet/NumericTraits.h"
01143  * \brief Traits specialized for std::complex<float>.
01144  */
01145 template<>
01146 struct NumericTraits< std::complex<float> > {
01147   typedef float                    base_type;
01148   typedef std::complex<float>            value_type;
01149   typedef std::complex<double>            sum_type;
01150   typedef std::complex<float>            diff_type;
01151   typedef std::complex<float>            float_type;
01152   typedef std::complex<float>            signed_type;
01153 
01154   typedef NumericTraits<value_type>        traits_type;
01155   typedef const value_type&            argument_type;
01156 
01157   static inline
01158   base_type real(argument_type z) { return std::real(z); }
01159 
01160   static inline
01161   base_type imag(argument_type z) { return std::imag(z); }
01162 
01163   static inline
01164   value_type conj(argument_type z) { return std::conj(z); }
01165 
01166   static inline
01167   base_type abs(argument_type z) { return std::abs(z); }
01168 
01169   static inline
01170   value_type sqrt(argument_type z) { return std::sqrt(z); }
01171 
01172   static inline
01173   base_type norm_1(argument_type z) {
01174     return NumericTraits<base_type>::abs((traits_type::real(z)))
01175          + NumericTraits<base_type>::abs((traits_type::imag(z)));
01176   }
01177 
01178   static inline
01179   base_type norm_2(argument_type z) { return traits_type::abs(z); }
01180 
01181   static inline
01182   base_type norm_inf(argument_type z) {
01183     return std::max(NumericTraits<base_type>::abs(traits_type::real(z)),
01184                 NumericTraits<base_type>::abs(traits_type::imag(z)));
01185   }
01186 
01187  static inline
01188   bool equals(argument_type lhs, argument_type rhs) {
01189     static base_type sqrt_epsilon(
01190       NumericTraits<base_type>::sqrt(
01191         std::numeric_limits<base_type>::epsilon()));
01192 
01193     return traits_type::norm_inf(lhs - rhs) < sqrt_epsilon *
01194       std::max(std::max(traits_type::norm_inf(lhs),
01195             traits_type::norm_inf(rhs)),
01196            std::numeric_limits<base_type>::min());
01197   }
01198 
01199   enum { is_complex = true };
01200 
01201   /** Complexity on operations. */
01202   enum {
01203     ops_plus = 2,    /**< Complexity on plus/minus ops. */
01204     ops_muls = 6    /**< Complexity on multiplications. */
01205   };
01206 };
01207 
01208 
01209 /**
01210  * \class NumericTraits< std::complex<double> > NumericTraits.h "tvmet/NumericTraits.h"
01211  * \brief Traits specialized for std::complex<double>.
01212  */
01213 template<>
01214 struct NumericTraits< std::complex<double> > {
01215   typedef double                base_type;
01216   typedef std::complex<double>            value_type;
01217 #if defined(TVMET_HAVE_LONG_DOUBLE)
01218   typedef std::complex<long double>         sum_type;
01219 #else
01220   typedef std::complex<double>            sum_type;
01221 #endif
01222   typedef std::complex<double>            diff_type;
01223   typedef std::complex<double>            float_type;
01224   typedef std::complex<double>            signed_type;
01225 
01226   typedef NumericTraits<value_type>        traits_type;
01227   typedef const value_type&            argument_type;
01228 
01229   static inline
01230   base_type real(argument_type z) { return std::real(z); }
01231 
01232   static inline
01233   base_type imag(argument_type z) { return std::imag(z); }
01234 
01235   static inline
01236   value_type conj(argument_type z) { return std::conj(z); }
01237 
01238   static inline
01239   base_type abs(argument_type z) { return std::abs(z); }
01240 
01241   static inline
01242   value_type sqrt(argument_type z) { return std::sqrt(z); }
01243 
01244   static inline
01245   base_type norm_1(argument_type z) {
01246     return NumericTraits<base_type>::abs((traits_type::real(z)))
01247          + NumericTraits<base_type>::abs((traits_type::imag(z)));
01248   }
01249 
01250   static inline
01251   base_type norm_2(argument_type z) { return traits_type::abs(z); }
01252 
01253   static inline
01254   base_type norm_inf(argument_type z) {
01255     return std::max(NumericTraits<base_type>::abs(traits_type::real(z)),
01256                 NumericTraits<base_type>::abs(traits_type::imag(z)));
01257   }
01258 
01259  static inline
01260   bool equals(argument_type lhs, argument_type rhs) {
01261     static base_type sqrt_epsilon(
01262       NumericTraits<base_type>::sqrt(
01263         std::numeric_limits<base_type>::epsilon()));
01264 
01265     return traits_type::norm_inf(lhs - rhs) < sqrt_epsilon *
01266       std::max(std::max(traits_type::norm_inf(lhs),
01267             traits_type::norm_inf(rhs)),
01268            std::numeric_limits<base_type>::min());
01269   }
01270 
01271   enum { is_complex = true };
01272 
01273   /** Complexity on operations. */
01274   enum {
01275     ops_plus = 2,    /**< Complexity on plus/minus ops. */
01276     ops_muls = 6    /**< Complexity on multiplications. */
01277   };
01278 };
01279 
01280 
01281 #if defined(TVMET_HAVE_LONG_DOUBLE)
01282 /**
01283  * \class NumericTraits< std::complex<long double> > NumericTraits.h "tvmet/NumericTraits.h"
01284  * \brief Traits specialized for std::complex<double>.
01285  */
01286 template<>
01287 struct NumericTraits< std::complex<long double> > {
01288   typedef long double                base_type;
01289   typedef std::complex<long double>        value_type;
01290   typedef std::complex<long double>         sum_type;
01291   typedef std::complex<long double>        diff_type;
01292   typedef std::complex<long double>        float_type;
01293   typedef std::complex<long double>        signed_type;
01294 
01295   typedef NumericTraits<value_type>        traits_type;
01296   typedef const value_type&            argument_type;
01297 
01298   static inline
01299   base_type real(argument_type z) { return std::real(z); }
01300 
01301   static inline
01302   base_type imag(argument_type z) { return std::imag(z); }
01303 
01304   static inline
01305   value_type conj(argument_type z) { return std::conj(z); }
01306 
01307   static inline
01308   base_type abs(argument_type z) { return std::abs(z); }
01309 
01310   static inline
01311   value_type sqrt(argument_type z) { return std::sqrt(z); }
01312 
01313   static inline
01314   base_type norm_1(argument_type z) {
01315     return NumericTraits<base_type>::abs((traits_type::real(z)))
01316          + NumericTraits<base_type>::abs((traits_type::imag(z)));
01317   }
01318 
01319   static inline
01320   base_type norm_2(argument_type z) { return traits_type::abs(z); }
01321 
01322   static inline
01323   base_type norm_inf(argument_type z) {
01324     return std::max(NumericTraits<base_type>::abs(traits_type::real(z)),
01325                 NumericTraits<base_type>::abs(traits_type::imag(z)));
01326   }
01327 
01328   static inline
01329   bool equals(argument_type lhs, argument_type rhs) {
01330     static base_type sqrt_epsilon(
01331       NumericTraits<base_type>::sqrt(
01332         std::numeric_limits<base_type>::epsilon()));
01333 
01334     return traits_type::norm_inf(lhs - rhs) < sqrt_epsilon *
01335       std::max(std::max(traits_type::norm_inf(lhs),
01336             traits_type::norm_inf(rhs)),
01337            std::numeric_limits<base_type>::min());
01338   }
01339 
01340   enum { is_complex = true };
01341 
01342   /** Complexity on operations. */
01343   enum {
01344     ops_plus = 2,    /**< Complexity on plus/minus ops. */
01345     ops_muls = 6    /**< Complexity on multiplications. */
01346   };
01347 };
01348 #endif // defined(TVMET_HAVE_LONG_DOUBLE)
01349 
01350 
01351 #endif // defined(TVMET_HAVE_COMPLEX)
01352 
01353 
01354 } // namespace tvmet
01355 
01356 
01357 #endif //  TVMET_NUMERIC_TRAITS_H
01358 
01359 
01360 // Local Variables:
01361 // mode:C++
01362 // tab-width:8
01363 // End: