AnnoyingScalar.h (5707B)
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 10 #ifndef EIGEN_TEST_ANNOYING_SCALAR_H 11 #define EIGEN_TEST_ANNOYING_SCALAR_H 12 13 #include <ostream> 14 15 #if EIGEN_COMP_GNUC 16 #pragma GCC diagnostic ignored "-Wshadow" 17 #endif 18 19 #ifndef EIGEN_TEST_ANNOYING_SCALAR_DONT_THROW 20 struct my_exception 21 { 22 my_exception() {} 23 ~my_exception() {} 24 }; 25 #endif 26 27 // An AnnoyingScalar is a pseudo scalar type that: 28 // - can randomly through an exception in operator + 29 // - randomly allocate on the heap or initialize a reference to itself making it non trivially copyable, nor movable, nor relocatable. 30 31 class AnnoyingScalar 32 { 33 public: 34 AnnoyingScalar() { init(); *v = 0; } 35 AnnoyingScalar(long double _v) { init(); *v = _v; } 36 AnnoyingScalar(double _v) { init(); *v = _v; } 37 AnnoyingScalar(float _v) { init(); *v = _v; } 38 AnnoyingScalar(int _v) { init(); *v = _v; } 39 AnnoyingScalar(long _v) { init(); *v = _v; } 40 #if EIGEN_HAS_CXX11 41 AnnoyingScalar(long long _v) { init(); *v = _v; } 42 #endif 43 AnnoyingScalar(const AnnoyingScalar& other) { init(); *v = *(other.v); } 44 ~AnnoyingScalar() { 45 if(v!=&data) 46 delete v; 47 instances--; 48 } 49 50 void init() { 51 if(internal::random<bool>()) 52 v = new float; 53 else 54 v = &data; 55 instances++; 56 } 57 58 AnnoyingScalar operator+(const AnnoyingScalar& other) const 59 { 60 #ifndef EIGEN_TEST_ANNOYING_SCALAR_DONT_THROW 61 countdown--; 62 if(countdown<=0 && !dont_throw) 63 throw my_exception(); 64 #endif 65 return AnnoyingScalar(*v+*other.v); 66 } 67 68 AnnoyingScalar operator-() const 69 { return AnnoyingScalar(-*v); } 70 71 AnnoyingScalar operator-(const AnnoyingScalar& other) const 72 { return AnnoyingScalar(*v-*other.v); } 73 74 AnnoyingScalar operator*(const AnnoyingScalar& other) const 75 { return AnnoyingScalar((*v)*(*other.v)); } 76 77 AnnoyingScalar operator/(const AnnoyingScalar& other) const 78 { return AnnoyingScalar((*v)/(*other.v)); } 79 80 AnnoyingScalar& operator+=(const AnnoyingScalar& other) { *v += *other.v; return *this; } 81 AnnoyingScalar& operator-=(const AnnoyingScalar& other) { *v -= *other.v; return *this; } 82 AnnoyingScalar& operator*=(const AnnoyingScalar& other) { *v *= *other.v; return *this; } 83 AnnoyingScalar& operator/=(const AnnoyingScalar& other) { *v /= *other.v; return *this; } 84 AnnoyingScalar& operator= (const AnnoyingScalar& other) { *v = *other.v; return *this; } 85 86 bool operator==(const AnnoyingScalar& other) const { return *v == *other.v; } 87 bool operator!=(const AnnoyingScalar& other) const { return *v != *other.v; } 88 bool operator<=(const AnnoyingScalar& other) const { return *v <= *other.v; } 89 bool operator< (const AnnoyingScalar& other) const { return *v < *other.v; } 90 bool operator>=(const AnnoyingScalar& other) const { return *v >= *other.v; } 91 bool operator> (const AnnoyingScalar& other) const { return *v > *other.v; } 92 93 float* v; 94 float data; 95 static int instances; 96 #ifndef EIGEN_TEST_ANNOYING_SCALAR_DONT_THROW 97 static int countdown; 98 static bool dont_throw; 99 #endif 100 }; 101 102 AnnoyingScalar real(const AnnoyingScalar &x) { return x; } 103 AnnoyingScalar imag(const AnnoyingScalar & ) { return 0; } 104 AnnoyingScalar conj(const AnnoyingScalar &x) { return x; } 105 AnnoyingScalar sqrt(const AnnoyingScalar &x) { return std::sqrt(*x.v); } 106 AnnoyingScalar abs (const AnnoyingScalar &x) { return std::abs(*x.v); } 107 AnnoyingScalar cos (const AnnoyingScalar &x) { return std::cos(*x.v); } 108 AnnoyingScalar sin (const AnnoyingScalar &x) { return std::sin(*x.v); } 109 AnnoyingScalar acos(const AnnoyingScalar &x) { return std::acos(*x.v); } 110 AnnoyingScalar atan2(const AnnoyingScalar &y,const AnnoyingScalar &x) { return std::atan2(*y.v,*x.v); } 111 112 std::ostream& operator<<(std::ostream& stream,const AnnoyingScalar& x) { 113 stream << (*(x.v)); 114 return stream; 115 } 116 117 int AnnoyingScalar::instances = 0; 118 119 #ifndef EIGEN_TEST_ANNOYING_SCALAR_DONT_THROW 120 int AnnoyingScalar::countdown = 0; 121 bool AnnoyingScalar::dont_throw = false; 122 #endif 123 124 namespace Eigen { 125 template<> 126 struct NumTraits<AnnoyingScalar> : NumTraits<float> 127 { 128 enum { 129 RequireInitialization = 1, 130 }; 131 typedef AnnoyingScalar Real; 132 typedef AnnoyingScalar Nested; 133 typedef AnnoyingScalar Literal; 134 typedef AnnoyingScalar NonInteger; 135 }; 136 137 template<> inline AnnoyingScalar test_precision<AnnoyingScalar>() { return test_precision<float>(); } 138 139 namespace numext { 140 template<> 141 EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE 142 bool (isfinite)(const AnnoyingScalar& x) { 143 return (numext::isfinite)(*x.v); 144 } 145 } 146 147 namespace internal { 148 template<> EIGEN_STRONG_INLINE double cast(const AnnoyingScalar& x) { return double(*x.v); } 149 template<> EIGEN_STRONG_INLINE float cast(const AnnoyingScalar& x) { return *x.v; } 150 } 151 } // namespace Eigen 152 153 AnnoyingScalar get_test_precision(const AnnoyingScalar&) 154 { return Eigen::test_precision<AnnoyingScalar>(); } 155 156 AnnoyingScalar test_relative_error(const AnnoyingScalar &a, const AnnoyingScalar &b) 157 { return test_relative_error(*a.v, *b.v); } 158 159 inline bool test_isApprox(const AnnoyingScalar &a, const AnnoyingScalar &b) 160 { return internal::isApprox(*a.v, *b.v, test_precision<float>()); } 161 162 inline bool test_isMuchSmallerThan(const AnnoyingScalar &a, const AnnoyingScalar &b) 163 { return test_isMuchSmallerThan(*a.v, *b.v); } 164 165 #endif // EIGEN_TEST_ANNOYING_SCALAR_H