aboutsummaryrefslogtreecommitdiffhomepage
path: root/test/AnnoyingScalar.h
diff options
context:
space:
mode:
authorGravatar Gael Guennebaud <g.gael@free.fr>2018-07-18 23:27:37 +0200
committerGravatar Gael Guennebaud <g.gael@free.fr>2018-07-18 23:27:37 +0200
commit053ed97c72543d513e92cdef1b14839844664c34 (patch)
tree5438b919d9cf5e1bc483ec4a665690ca3f490d96 /test/AnnoyingScalar.h
parenta503fc87254aca625d7b128a2260599d40dc0889 (diff)
Generalize ScalarWithExceptions to a full non-copyable and trowing scalar type to be used in other unit tests.
Diffstat (limited to 'test/AnnoyingScalar.h')
-rw-r--r--test/AnnoyingScalar.h151
1 files changed, 151 insertions, 0 deletions
diff --git a/test/AnnoyingScalar.h b/test/AnnoyingScalar.h
new file mode 100644
index 000000000..08854a114
--- /dev/null
+++ b/test/AnnoyingScalar.h
@@ -0,0 +1,151 @@
+// This file is part of Eigen, a lightweight C++ template library
+// for linear algebra.
+//
+// Copyright (C) 2011-2018 Gael Guennebaud <gael.guennebaud@inria.fr>
+//
+// This Source Code Form is subject to the terms of the Mozilla
+// Public License v. 2.0. If a copy of the MPL was not distributed
+// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef EIGEN_TEST_ANNOYING_SCALAR_H
+#define EIGEN_TEST_ANNOYING_SCALAR_H
+
+#include <ostream>
+
+#ifndef EIGEN_TEST_ANNOYING_SCALAR_DONT_THROW
+struct my_exception
+{
+ my_exception() {}
+ ~my_exception() {}
+};
+#endif
+
+// An AnnoyingScalar is a pseudo scalar type that:
+// - can randomly through an exception in operator +
+// - randomly allocate on the heap or initialize a reference to itself making it non trivially copyable, nor movable.
+
+class AnnoyingScalar
+{
+ public:
+ AnnoyingScalar() { init(); *v = 0; }
+ AnnoyingScalar(long double _v) { init(); *v = _v; }
+ AnnoyingScalar(double _v) { init(); *v = _v; }
+ AnnoyingScalar(float _v) { init(); *v = _v; }
+ AnnoyingScalar(int _v) { init(); *v = _v; }
+ AnnoyingScalar(long _v) { init(); *v = _v; }
+ AnnoyingScalar(const AnnoyingScalar& other) { init(); *v = *(other.v); }
+ ~AnnoyingScalar() {
+ if(v!=&data)
+ delete v;
+ instances--;
+ }
+
+ void init() {
+ if(internal::random<bool>())
+ v = new float;
+ else
+ v = &data;
+ instances++;
+ }
+
+ AnnoyingScalar operator+(const AnnoyingScalar& other) const
+ {
+ #ifndef EIGEN_TEST_ANNOYING_SCALAR_DONT_THROW
+ countdown--;
+ if(countdown<=0 && !dont_throw)
+ throw my_exception();
+ #endif
+ return AnnoyingScalar(*v+*other.v);
+ }
+
+ AnnoyingScalar operator-() const
+ { return AnnoyingScalar(-*v); }
+
+ AnnoyingScalar operator-(const AnnoyingScalar& other) const
+ { return AnnoyingScalar(*v-*other.v); }
+
+ AnnoyingScalar operator*(const AnnoyingScalar& other) const
+ { return AnnoyingScalar((*v)*(*other.v)); }
+
+ AnnoyingScalar operator/(const AnnoyingScalar& other) const
+ { return AnnoyingScalar((*v)/(*other.v)); }
+
+ AnnoyingScalar& operator+=(const AnnoyingScalar& other) { *v += *other.v; return *this; }
+ AnnoyingScalar& operator-=(const AnnoyingScalar& other) { *v -= *other.v; return *this; }
+ AnnoyingScalar& operator*=(const AnnoyingScalar& other) { *v *= *other.v; return *this; }
+ AnnoyingScalar& operator/=(const AnnoyingScalar& other) { *v /= *other.v; return *this; }
+ AnnoyingScalar& operator= (const AnnoyingScalar& other) { *v = *other.v; return *this; }
+
+ bool operator==(const AnnoyingScalar& other) const { return *v == *other.v; }
+ bool operator!=(const AnnoyingScalar& other) const { return *v != *other.v; }
+ bool operator<=(const AnnoyingScalar& other) const { return *v <= *other.v; }
+ bool operator< (const AnnoyingScalar& other) const { return *v < *other.v; }
+ bool operator>=(const AnnoyingScalar& other) const { return *v >= *other.v; }
+ bool operator> (const AnnoyingScalar& other) const { return *v > *other.v; }
+
+ float* v;
+ float data;
+ static int instances;
+#ifndef EIGEN_TEST_ANNOYING_SCALAR_DONT_THROW
+ static int countdown;
+ static bool dont_throw;
+#endif
+};
+
+AnnoyingScalar real(const AnnoyingScalar &x) { return x; }
+AnnoyingScalar imag(const AnnoyingScalar & ) { return 0; }
+AnnoyingScalar conj(const AnnoyingScalar &x) { return x; }
+AnnoyingScalar sqrt(const AnnoyingScalar &x) { return std::sqrt(*x.v); }
+AnnoyingScalar abs (const AnnoyingScalar &x) { return std::abs(*x.v); }
+AnnoyingScalar cos (const AnnoyingScalar &x) { return std::cos(*x.v); }
+AnnoyingScalar sin (const AnnoyingScalar &x) { return std::sin(*x.v); }
+AnnoyingScalar acos(const AnnoyingScalar &x) { return std::acos(*x.v); }
+AnnoyingScalar atan2(const AnnoyingScalar &y,const AnnoyingScalar &x) { return std::atan2(*y.v,*x.v); }
+
+std::ostream& operator<<(std::ostream& stream,const AnnoyingScalar& x) {
+ stream << (*(x.v));
+ return stream;
+}
+
+int AnnoyingScalar::instances = 0;
+
+#ifndef EIGEN_TEST_ANNOYING_SCALAR_DONT_THROW
+int AnnoyingScalar::countdown = 0;
+bool AnnoyingScalar::dont_throw = false;
+#endif
+
+namespace Eigen {
+template<>
+struct NumTraits<AnnoyingScalar> : NumTraits<float>
+{
+ enum {
+ RequireInitialization = true
+ };
+ typedef AnnoyingScalar Real;
+ typedef AnnoyingScalar Nested;
+ typedef AnnoyingScalar Literal;
+ typedef AnnoyingScalar NonInteger;
+};
+
+template<> inline AnnoyingScalar test_precision<AnnoyingScalar>() { return test_precision<float>(); }
+
+namespace internal {
+ template<> double cast(const AnnoyingScalar& x) { return double(*x.v); }
+ template<> float cast(const AnnoyingScalar& x) { return *x.v; }
+}
+
+}
+
+AnnoyingScalar get_test_precision(const AnnoyingScalar&)
+{ return Eigen::test_precision<AnnoyingScalar>(); }
+
+AnnoyingScalar test_relative_error(AnnoyingScalar a, AnnoyingScalar b)
+{ return test_relative_error(*a.v, *b.v); }
+
+inline bool test_isApprox(AnnoyingScalar a, AnnoyingScalar b)
+{ return internal::isApprox(*a.v, *b.v, test_precision<float>()); }
+
+inline bool test_isMuchSmallerThan(AnnoyingScalar a, AnnoyingScalar b)
+{ return test_isMuchSmallerThan(*a.v, *b.v); }
+
+#endif // EIGEN_TEST_ANNOYING_SCALAR_H