This is the Tiny Vector Matrix Expression Templates library found at http://tvmet.sourceforge.net. It is the fastest and most compact matrix lib out there (for < 10x10 matricies). I have done some minor tweaks to make it compile for mbed. For examples and hints on how to use, see: http://tvmet.sourceforge.net/usage.html
Dependents: Eurobot_2012_Secondary
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:
Generated on Tue Jul 12 2022 19:00:11 by 1.7.2