| // 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> | |
| #if EIGEN_COMP_GNUC | |
| #pragma GCC diagnostic ignored "-Wshadow" | |
| #endif | |
| #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, nor relocatable. | |
| 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; } | |
| #if EIGEN_HAS_CXX11 | |
| AnnoyingScalar(long long _v) { init(); *v = _v; } | |
| #endif | |
| 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(const AnnoyingScalar &a, const AnnoyingScalar &b) | |
| { return test_relative_error(*a.v, *b.v); } | |
| inline bool test_isApprox(const AnnoyingScalar &a, const AnnoyingScalar &b) | |
| { return internal::isApprox(*a.v, *b.v, test_precision<float>()); } | |
| inline bool test_isMuchSmallerThan(const AnnoyingScalar &a, const AnnoyingScalar &b) | |
| { return test_isMuchSmallerThan(*a.v, *b.v); } | |
| #endif // EIGEN_TEST_ANNOYING_SCALAR_H |