home *** CD-ROM | disk | FTP | other *** search
/ Hackers Magazine 57 / CdHackersMagazineNr57.iso / Software / Multimedia / k3d-setup-0.7.11.0.exe / include / k3d / k3dsdk / almost_equal.h < prev    next >
Encoding:
C/C++ Source or Header  |  2008-11-07  |  5.4 KB  |  198 lines

  1. #ifndef K3DSDK_ALMOST_EQUAL_H
  2. #define K3DSDK_ALMOST_EQUAL_H
  3.  
  4. // K-3D
  5. // Copyright (c) 1995-2007, Timothy M. Shead
  6. //
  7. // Contact: tshead@k-3d.com
  8. //
  9. // This program is free software; you can redistribute it and/or
  10. // modify it under the terms of the GNU General Public
  11. // License as published by the Free Software Foundation; either
  12. // version 2 of the License, or (at your option) any later version.
  13. //
  14. // This program is distributed in the hope that it will be useful,
  15. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17. // General Public License for more details.
  18. //
  19. // You should have received a copy of the GNU General Public
  20. // License along with this program; if not, write to the Free Software
  21. // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  22.  
  23. #include <k3d-platform-config.h>
  24. #include "types.h"
  25. #include <boost/static_assert.hpp>
  26.  
  27. namespace k3d
  28. {
  29.  
  30. /// Functor for testing objects for "loose" equality - specializations for exact types including integers and strings test for exact equality, while specializations for floating-point types test for equality within a caller-specified tolerance
  31. template<typename T>
  32. class almost_equal
  33. {
  34. public:
  35.     almost_equal(const uint64_t) { }
  36.     inline const bool_t operator()(const T A, const T B) const
  37.     {
  38.         // This will be triggered if this template is ever instantiated
  39.         BOOST_STATIC_ASSERT(sizeof(T) == 0);
  40.         return false;
  41.     }
  42. };
  43.  
  44. /// Specialization of almost_equal that tests bool_t for equality
  45. template<>
  46. class almost_equal<bool_t>
  47. {
  48.     typedef bool_t T;
  49. public:
  50.     almost_equal(const uint64_t) { }
  51.     inline const bool_t operator()(const T A, const T B) const { return A == B; }
  52. };
  53.  
  54. /// Specialization of almost_equal that tests int8_t for equality
  55. template<>
  56. class almost_equal<int8_t>
  57. {
  58.     typedef int8_t T;
  59. public:
  60.     almost_equal(const uint64_t) { }
  61.     inline const bool_t operator()(const T A, const T B) const { return A == B; }
  62. };
  63.  
  64. /// Specialization of almost_equal that tests int16_t for equality
  65. template<>
  66. class almost_equal<int16_t>
  67. {
  68.     typedef int16_t T;
  69. public:
  70.     almost_equal(const uint64_t) { }
  71.     inline const bool_t operator()(const T A, const T B) const { return A == B; }
  72. };
  73.  
  74. /// Specialization of almost_equal that tests int32_t for equality
  75. template<>
  76. class almost_equal<int32_t>
  77. {
  78.     typedef int32_t T;
  79. public:
  80.     almost_equal(const uint64_t) { }
  81.     inline const bool_t operator()(const T A, const T B) const { return A == B; }
  82. };
  83.  
  84. /// Specialization of almost_equal that tests int64_t for equality
  85. template<>
  86. class almost_equal<int64_t>
  87. {
  88.     typedef int64_t T;
  89. public:
  90.     almost_equal(const uint64_t) { }
  91.     inline const bool_t operator()(const T A, const T B) const { return A == B; }
  92. };
  93.  
  94. /// Specialization of almost_equal that tests uint8_t for equality
  95. template<>
  96. class almost_equal<uint8_t>
  97. {
  98.     typedef uint8_t T;
  99. public:
  100.     almost_equal(const uint64_t) { }
  101.     inline const bool_t operator()(const T A, const T B) const { return A == B; }
  102. };
  103.  
  104. /// Specialization of almost_equal that tests uint16_t for equality
  105. template<>
  106. class almost_equal<uint16_t>
  107. {
  108.     typedef uint16_t T;
  109. public:
  110.     almost_equal(const uint64_t) { }
  111.     inline const bool_t operator()(const T A, const T B) const { return A == B; }
  112. };
  113.  
  114. /// Specialization of almost_equal that tests uint32_t for equality
  115. template<>
  116. class almost_equal<uint32_t>
  117. {
  118.     typedef uint32_t T;
  119. public:
  120.     almost_equal(const uint64_t) { }
  121.     inline const bool_t operator()(const T A, const T B) const { return A == B; }
  122. };
  123.  
  124. /// Specialization of almost_equal that tests uint64_t for equality
  125. template<>
  126. class almost_equal<uint64_t>
  127. {
  128.     typedef uint64_t T;
  129. public:
  130.     almost_equal(const uint64_t) { }
  131.     inline const bool_t operator()(const T A, const T B) const { return A == B; }
  132. };
  133.  
  134. /// Specialization of almost_equal that tests two double_t values for near-equality - based on "Comparing floating point numbers" by Bruce Dawson
  135. template<>
  136. class almost_equal<double_t>
  137. {
  138.     typedef double_t T;
  139.  
  140. public:
  141.     almost_equal(const uint64_t Threshold) :
  142.         threshold(Threshold)
  143.     {
  144.     }
  145.  
  146.     inline const bool_t operator()(const T A, const T B) const
  147.     {
  148.         const int64_t difference = representable_difference(A, B);
  149.         return difference < 0 ? -difference <= threshold : difference <= threshold;
  150.     }
  151.  
  152. private:
  153.     /// Convert a double_t to a lexicographically-ordered twos-complement integer
  154.     inline static const int64_t to_integer(const double_t Value)
  155.     {
  156.         const int64_t value = *(int64_t*)&Value;
  157.         return value < 0 ? 0x8000000000000000LL - value : value;
  158.     }
  159.  
  160.     /// Given two double_t, returns their difference expressed as the number of uniquely-representable floating-point values that separate them
  161.     inline static const int64_t representable_difference(const double_t A, const double_t B)
  162.     {
  163.         return to_integer(B) - to_integer(A);
  164.     }
  165.  
  166.     const uint64_t threshold;
  167. };
  168.  
  169. /// Specialization of almost_equal that tests string_t for equality
  170. template<>
  171. class almost_equal<string_t>
  172. {
  173.     typedef string_t T;
  174. public:
  175.     almost_equal(const uint64_t) { }
  176.     inline const bool_t operator()(const T A, const T B) const { return A == B; }
  177. };
  178.  
  179. #ifdef K3D_API_DARWIN
  180.  
  181. /// Specialization of almost_equal for use with unsigned long (required on OSX)
  182. /// \deprecated New code must use the sized K-3D types instead of unsigned long
  183. template<>
  184. class almost_equal<unsigned long>
  185. {
  186.     typedef unsigned long T;
  187. public:
  188.     almost_equal(const uint64_t) { }
  189.     inline const bool_t operator()(const T A, const T B) const { return A == B; }
  190. };
  191.  
  192. #endif // K3D_API_DARWIN
  193.  
  194. } // namespace k3d
  195.  
  196. #endif // !K3DSDK_ALMOST_EQUAL_H
  197.  
  198.