| // 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 |