|  | // 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 = static_cast<float>(_v); | 
|  | } | 
|  | AnnoyingScalar(double _v) { | 
|  | init(); | 
|  | *v = static_cast<float>(_v); | 
|  | } | 
|  | AnnoyingScalar(float _v) { | 
|  | init(); | 
|  | *v = _v; | 
|  | } | 
|  | AnnoyingScalar(int _v) { | 
|  | init(); | 
|  | *v = static_cast<float>(_v); | 
|  | } | 
|  | AnnoyingScalar(long _v) { | 
|  | init(); | 
|  | *v = static_cast<float>(_v); | 
|  | } | 
|  | AnnoyingScalar(long long _v) { | 
|  | init(); | 
|  | *v = static_cast<float>(_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 numext::equal_strict(*v, *other.v); } | 
|  | bool operator!=(const AnnoyingScalar& other) const { return numext::not_equal_strict(*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 = 1, | 
|  | }; | 
|  | typedef AnnoyingScalar Real; | 
|  | typedef AnnoyingScalar Nested; | 
|  | typedef AnnoyingScalar Literal; | 
|  | typedef AnnoyingScalar NonInteger; | 
|  | }; | 
|  |  | 
|  | template <> | 
|  | inline AnnoyingScalar test_precision<AnnoyingScalar>() { | 
|  | return test_precision<float>(); | 
|  | } | 
|  |  | 
|  | namespace numext { | 
|  | template <> | 
|  | EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE bool(isfinite)(const AnnoyingScalar& x) { | 
|  | return (numext::isfinite)(*x.v); | 
|  | } | 
|  | }  // namespace numext | 
|  |  | 
|  | namespace internal { | 
|  | template <> | 
|  | EIGEN_STRONG_INLINE double cast(const AnnoyingScalar& x) { | 
|  | return double(*x.v); | 
|  | } | 
|  | template <> | 
|  | EIGEN_STRONG_INLINE float cast(const AnnoyingScalar& x) { | 
|  | return *x.v; | 
|  | } | 
|  |  | 
|  | template <> | 
|  | struct random_impl<AnnoyingScalar> { | 
|  | using Impl = random_impl<float>; | 
|  | static EIGEN_DEVICE_FUNC inline AnnoyingScalar run(const AnnoyingScalar& x, const AnnoyingScalar& y) { | 
|  | float result = Impl::run(*x.v, *y.v); | 
|  | return AnnoyingScalar(result); | 
|  | } | 
|  | static EIGEN_DEVICE_FUNC inline AnnoyingScalar run() { | 
|  | float result = Impl::run(); | 
|  | return AnnoyingScalar(result); | 
|  | } | 
|  | }; | 
|  |  | 
|  | }  // namespace internal | 
|  | }  // namespace Eigen | 
|  |  | 
|  | 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 |