AnnoyingScalar.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. // This file is part of Eigen, a lightweight C++ template library
  2. // for linear algebra.
  3. //
  4. // Copyright (C) 2011-2018 Gael Guennebaud <gael.guennebaud@inria.fr>
  5. //
  6. // This Source Code Form is subject to the terms of the Mozilla
  7. // Public License v. 2.0. If a copy of the MPL was not distributed
  8. // with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
  9. #ifndef EIGEN_TEST_ANNOYING_SCALAR_H
  10. #define EIGEN_TEST_ANNOYING_SCALAR_H
  11. #include <ostream>
  12. #if EIGEN_COMP_GNUC
  13. #pragma GCC diagnostic ignored "-Wshadow"
  14. #endif
  15. #ifndef EIGEN_TEST_ANNOYING_SCALAR_DONT_THROW
  16. struct my_exception
  17. {
  18. my_exception() {}
  19. ~my_exception() {}
  20. };
  21. #endif
  22. // An AnnoyingScalar is a pseudo scalar type that:
  23. // - can randomly through an exception in operator +
  24. // - randomly allocate on the heap or initialize a reference to itself making it non trivially copyable, nor movable, nor relocatable.
  25. class AnnoyingScalar
  26. {
  27. public:
  28. AnnoyingScalar() { init(); *v = 0; }
  29. AnnoyingScalar(long double _v) { init(); *v = _v; }
  30. AnnoyingScalar(double _v) { init(); *v = _v; }
  31. AnnoyingScalar(float _v) { init(); *v = _v; }
  32. AnnoyingScalar(int _v) { init(); *v = _v; }
  33. AnnoyingScalar(long _v) { init(); *v = _v; }
  34. #if EIGEN_HAS_CXX11
  35. AnnoyingScalar(long long _v) { init(); *v = _v; }
  36. #endif
  37. AnnoyingScalar(const AnnoyingScalar& other) { init(); *v = *(other.v); }
  38. ~AnnoyingScalar() {
  39. if(v!=&data)
  40. delete v;
  41. instances--;
  42. }
  43. void init() {
  44. if(internal::random<bool>())
  45. v = new float;
  46. else
  47. v = &data;
  48. instances++;
  49. }
  50. AnnoyingScalar operator+(const AnnoyingScalar& other) const
  51. {
  52. #ifndef EIGEN_TEST_ANNOYING_SCALAR_DONT_THROW
  53. countdown--;
  54. if(countdown<=0 && !dont_throw)
  55. throw my_exception();
  56. #endif
  57. return AnnoyingScalar(*v+*other.v);
  58. }
  59. AnnoyingScalar operator-() const
  60. { return AnnoyingScalar(-*v); }
  61. AnnoyingScalar operator-(const AnnoyingScalar& other) const
  62. { return AnnoyingScalar(*v-*other.v); }
  63. AnnoyingScalar operator*(const AnnoyingScalar& other) const
  64. { return AnnoyingScalar((*v)*(*other.v)); }
  65. AnnoyingScalar operator/(const AnnoyingScalar& other) const
  66. { return AnnoyingScalar((*v)/(*other.v)); }
  67. AnnoyingScalar& operator+=(const AnnoyingScalar& other) { *v += *other.v; return *this; }
  68. AnnoyingScalar& operator-=(const AnnoyingScalar& other) { *v -= *other.v; return *this; }
  69. AnnoyingScalar& operator*=(const AnnoyingScalar& other) { *v *= *other.v; return *this; }
  70. AnnoyingScalar& operator/=(const AnnoyingScalar& other) { *v /= *other.v; return *this; }
  71. AnnoyingScalar& operator= (const AnnoyingScalar& other) { *v = *other.v; return *this; }
  72. bool operator==(const AnnoyingScalar& other) const { return *v == *other.v; }
  73. bool operator!=(const AnnoyingScalar& other) const { return *v != *other.v; }
  74. bool operator<=(const AnnoyingScalar& other) const { return *v <= *other.v; }
  75. bool operator< (const AnnoyingScalar& other) const { return *v < *other.v; }
  76. bool operator>=(const AnnoyingScalar& other) const { return *v >= *other.v; }
  77. bool operator> (const AnnoyingScalar& other) const { return *v > *other.v; }
  78. float* v;
  79. float data;
  80. static int instances;
  81. #ifndef EIGEN_TEST_ANNOYING_SCALAR_DONT_THROW
  82. static int countdown;
  83. static bool dont_throw;
  84. #endif
  85. };
  86. AnnoyingScalar real(const AnnoyingScalar &x) { return x; }
  87. AnnoyingScalar imag(const AnnoyingScalar & ) { return 0; }
  88. AnnoyingScalar conj(const AnnoyingScalar &x) { return x; }
  89. AnnoyingScalar sqrt(const AnnoyingScalar &x) { return std::sqrt(*x.v); }
  90. AnnoyingScalar abs (const AnnoyingScalar &x) { return std::abs(*x.v); }
  91. AnnoyingScalar cos (const AnnoyingScalar &x) { return std::cos(*x.v); }
  92. AnnoyingScalar sin (const AnnoyingScalar &x) { return std::sin(*x.v); }
  93. AnnoyingScalar acos(const AnnoyingScalar &x) { return std::acos(*x.v); }
  94. AnnoyingScalar atan2(const AnnoyingScalar &y,const AnnoyingScalar &x) { return std::atan2(*y.v,*x.v); }
  95. std::ostream& operator<<(std::ostream& stream,const AnnoyingScalar& x) {
  96. stream << (*(x.v));
  97. return stream;
  98. }
  99. int AnnoyingScalar::instances = 0;
  100. #ifndef EIGEN_TEST_ANNOYING_SCALAR_DONT_THROW
  101. int AnnoyingScalar::countdown = 0;
  102. bool AnnoyingScalar::dont_throw = false;
  103. #endif
  104. namespace Eigen {
  105. template<>
  106. struct NumTraits<AnnoyingScalar> : NumTraits<float>
  107. {
  108. enum {
  109. RequireInitialization = 1,
  110. };
  111. typedef AnnoyingScalar Real;
  112. typedef AnnoyingScalar Nested;
  113. typedef AnnoyingScalar Literal;
  114. typedef AnnoyingScalar NonInteger;
  115. };
  116. template<> inline AnnoyingScalar test_precision<AnnoyingScalar>() { return test_precision<float>(); }
  117. namespace numext {
  118. template<>
  119. EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE
  120. bool (isfinite)(const AnnoyingScalar& x) {
  121. return (numext::isfinite)(*x.v);
  122. }
  123. }
  124. namespace internal {
  125. template<> EIGEN_STRONG_INLINE double cast(const AnnoyingScalar& x) { return double(*x.v); }
  126. template<> EIGEN_STRONG_INLINE float cast(const AnnoyingScalar& x) { return *x.v; }
  127. }
  128. } // namespace Eigen
  129. AnnoyingScalar get_test_precision(const AnnoyingScalar&)
  130. { return Eigen::test_precision<AnnoyingScalar>(); }
  131. AnnoyingScalar test_relative_error(const AnnoyingScalar &a, const AnnoyingScalar &b)
  132. { return test_relative_error(*a.v, *b.v); }
  133. inline bool test_isApprox(const AnnoyingScalar &a, const AnnoyingScalar &b)
  134. { return internal::isApprox(*a.v, *b.v, test_precision<float>()); }
  135. inline bool test_isMuchSmallerThan(const AnnoyingScalar &a, const AnnoyingScalar &b)
  136. { return test_isMuchSmallerThan(*a.v, *b.v); }
  137. #endif // EIGEN_TEST_ANNOYING_SCALAR_H