xref: /aosp_15_r20/external/eigen/test/AnnoyingScalar.h (revision bf2c37156dfe67e5dfebd6d394bad8b2ab5804d4)
1 // This file is part of Eigen, a lightweight C++ template library
2 // for linear algebra.
3 //
4 // Copyright (C) 2011-2018 Gael Guennebaud <[email protected]>
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 {
my_exceptionmy_exception22   my_exception() {}
~my_exceptionmy_exception23   ~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:
AnnoyingScalar()34     AnnoyingScalar()                { init(); *v = 0;  }
AnnoyingScalar(long double _v)35     AnnoyingScalar(long double _v)  { init(); *v = _v; }
AnnoyingScalar(double _v)36     AnnoyingScalar(double _v)       { init(); *v = _v; }
AnnoyingScalar(float _v)37     AnnoyingScalar(float _v)        { init(); *v = _v; }
AnnoyingScalar(int _v)38     AnnoyingScalar(int _v)          { init(); *v = _v; }
AnnoyingScalar(long _v)39     AnnoyingScalar(long _v)         { init(); *v = _v; }
40     #if EIGEN_HAS_CXX11
AnnoyingScalar(long long _v)41     AnnoyingScalar(long long _v)    { init(); *v = _v; }
42     #endif
AnnoyingScalar(const AnnoyingScalar & other)43     AnnoyingScalar(const AnnoyingScalar& other) { init(); *v = *(other.v); }
~AnnoyingScalar()44     ~AnnoyingScalar() {
45       if(v!=&data)
46         delete v;
47       instances--;
48     }
49 
init()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 
real(const AnnoyingScalar & x)102 AnnoyingScalar real(const AnnoyingScalar &x) { return x; }
imag(const AnnoyingScalar &)103 AnnoyingScalar imag(const AnnoyingScalar & ) { return 0; }
conj(const AnnoyingScalar & x)104 AnnoyingScalar conj(const AnnoyingScalar &x) { return x; }
sqrt(const AnnoyingScalar & x)105 AnnoyingScalar sqrt(const AnnoyingScalar &x) { return std::sqrt(*x.v); }
abs(const AnnoyingScalar & x)106 AnnoyingScalar abs (const AnnoyingScalar &x) { return std::abs(*x.v); }
cos(const AnnoyingScalar & x)107 AnnoyingScalar cos (const AnnoyingScalar &x) { return std::cos(*x.v); }
sin(const AnnoyingScalar & x)108 AnnoyingScalar sin (const AnnoyingScalar &x) { return std::sin(*x.v); }
acos(const AnnoyingScalar & x)109 AnnoyingScalar acos(const AnnoyingScalar &x) { return std::acos(*x.v); }
atan2(const AnnoyingScalar & y,const AnnoyingScalar & x)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
166