mirror of
https://gitlab.com/libeigen/eigen.git
synced 2024-12-21 07:19:46 +08:00
159 lines
5.4 KiB
C++
159 lines
5.4 KiB
C++
// 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
|