123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- // 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 = 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 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; }
- }
- } // 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
|