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

#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
