You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
413 lines
9.4 KiB
413 lines
9.4 KiB
#pragma once
|
|
|
|
#include <cmath>
|
|
|
|
#define INFINITY (__builtin_inff())
|
|
#define NAN (__builtin_nanf (""))
|
|
|
|
namespace std {
|
|
|
|
// Taken from libc++
|
|
template <class _Tp>
|
|
class complex {
|
|
public:
|
|
typedef _Tp value_type;
|
|
|
|
private:
|
|
value_type __re_;
|
|
value_type __im_;
|
|
|
|
public:
|
|
complex(const value_type &__re = value_type(), const value_type &__im = value_type())
|
|
: __re_(__re), __im_(__im) {}
|
|
template <class _Xp>
|
|
complex(const complex<_Xp> &__c)
|
|
: __re_(__c.real()), __im_(__c.imag()) {}
|
|
|
|
value_type real() const { return __re_; }
|
|
value_type imag() const { return __im_; }
|
|
|
|
void real(value_type __re) { __re_ = __re; }
|
|
void imag(value_type __im) { __im_ = __im; }
|
|
|
|
complex &operator=(const value_type &__re) {
|
|
__re_ = __re;
|
|
__im_ = value_type();
|
|
return *this;
|
|
}
|
|
complex &operator+=(const value_type &__re) {
|
|
__re_ += __re;
|
|
return *this;
|
|
}
|
|
complex &operator-=(const value_type &__re) {
|
|
__re_ -= __re;
|
|
return *this;
|
|
}
|
|
complex &operator*=(const value_type &__re) {
|
|
__re_ *= __re;
|
|
__im_ *= __re;
|
|
return *this;
|
|
}
|
|
complex &operator/=(const value_type &__re) {
|
|
__re_ /= __re;
|
|
__im_ /= __re;
|
|
return *this;
|
|
}
|
|
|
|
template <class _Xp>
|
|
complex &operator=(const complex<_Xp> &__c) {
|
|
__re_ = __c.real();
|
|
__im_ = __c.imag();
|
|
return *this;
|
|
}
|
|
template <class _Xp>
|
|
complex &operator+=(const complex<_Xp> &__c) {
|
|
__re_ += __c.real();
|
|
__im_ += __c.imag();
|
|
return *this;
|
|
}
|
|
template <class _Xp>
|
|
complex &operator-=(const complex<_Xp> &__c) {
|
|
__re_ -= __c.real();
|
|
__im_ -= __c.imag();
|
|
return *this;
|
|
}
|
|
template <class _Xp>
|
|
complex &operator*=(const complex<_Xp> &__c) {
|
|
*this = *this * complex(__c.real(), __c.imag());
|
|
return *this;
|
|
}
|
|
template <class _Xp>
|
|
complex &operator/=(const complex<_Xp> &__c) {
|
|
*this = *this / complex(__c.real(), __c.imag());
|
|
return *this;
|
|
}
|
|
};
|
|
|
|
template <class _Tp>
|
|
inline complex<_Tp>
|
|
operator+(const complex<_Tp> &__x, const complex<_Tp> &__y) {
|
|
complex<_Tp> __t(__x);
|
|
__t += __y;
|
|
return __t;
|
|
}
|
|
|
|
template <class _Tp>
|
|
inline complex<_Tp>
|
|
operator+(const complex<_Tp> &__x, const _Tp &__y) {
|
|
complex<_Tp> __t(__x);
|
|
__t += __y;
|
|
return __t;
|
|
}
|
|
|
|
template <class _Tp>
|
|
inline complex<_Tp>
|
|
operator+(const _Tp &__x, const complex<_Tp> &__y) {
|
|
complex<_Tp> __t(__y);
|
|
__t += __x;
|
|
return __t;
|
|
}
|
|
|
|
template <class _Tp>
|
|
inline complex<_Tp>
|
|
operator-(const complex<_Tp> &__x, const complex<_Tp> &__y) {
|
|
complex<_Tp> __t(__x);
|
|
__t -= __y;
|
|
return __t;
|
|
}
|
|
|
|
template <class _Tp>
|
|
inline complex<_Tp>
|
|
operator-(const complex<_Tp> &__x, const _Tp &__y) {
|
|
complex<_Tp> __t(__x);
|
|
__t -= __y;
|
|
return __t;
|
|
}
|
|
|
|
template <class _Tp>
|
|
inline complex<_Tp>
|
|
operator-(const _Tp &__x, const complex<_Tp> &__y) {
|
|
complex<_Tp> __t(-__y);
|
|
__t += __x;
|
|
return __t;
|
|
}
|
|
|
|
template <class _Tp>
|
|
complex<_Tp>
|
|
operator*(const complex<_Tp> &__z, const complex<_Tp> &__w) {
|
|
_Tp __a = __z.real();
|
|
_Tp __b = __z.imag();
|
|
_Tp __c = __w.real();
|
|
_Tp __d = __w.imag();
|
|
_Tp __ac = __a * __c;
|
|
_Tp __bd = __b * __d;
|
|
_Tp __ad = __a * __d;
|
|
_Tp __bc = __b * __c;
|
|
_Tp __x = __ac - __bd;
|
|
_Tp __y = __ad + __bc;
|
|
if (std::isnan(__x) && std::isnan(__y)) {
|
|
bool __recalc = false;
|
|
if (std::isinf(__a) || std::isinf(__b)) {
|
|
__a = copysign(std::isinf(__a) ? _Tp(1) : _Tp(0), __a);
|
|
__b = copysign(std::isinf(__b) ? _Tp(1) : _Tp(0), __b);
|
|
if (std::isnan(__c))
|
|
__c = copysign(_Tp(0), __c);
|
|
if (std::isnan(__d))
|
|
__d = copysign(_Tp(0), __d);
|
|
__recalc = true;
|
|
}
|
|
if (std::isinf(__c) || std::isinf(__d)) {
|
|
__c = copysign(std::isinf(__c) ? _Tp(1) : _Tp(0), __c);
|
|
__d = copysign(std::isinf(__d) ? _Tp(1) : _Tp(0), __d);
|
|
if (std::isnan(__a))
|
|
__a = copysign(_Tp(0), __a);
|
|
if (std::isnan(__b))
|
|
__b = copysign(_Tp(0), __b);
|
|
__recalc = true;
|
|
}
|
|
if (!__recalc && (std::isinf(__ac) || std::isinf(__bd) ||
|
|
std::isinf(__ad) || std::isinf(__bc))) {
|
|
if (std::isnan(__a))
|
|
__a = copysign(_Tp(0), __a);
|
|
if (std::isnan(__b))
|
|
__b = copysign(_Tp(0), __b);
|
|
if (std::isnan(__c))
|
|
__c = copysign(_Tp(0), __c);
|
|
if (std::isnan(__d))
|
|
__d = copysign(_Tp(0), __d);
|
|
__recalc = true;
|
|
}
|
|
if (__recalc) {
|
|
__x = _Tp(INFINITY) * (__a * __c - __b * __d);
|
|
__y = _Tp(INFINITY) * (__a * __d + __b * __c);
|
|
}
|
|
}
|
|
return complex<_Tp>(__x, __y);
|
|
}
|
|
|
|
template <class _Tp>
|
|
inline complex<_Tp>
|
|
operator*(const complex<_Tp> &__x, const _Tp &__y) {
|
|
complex<_Tp> __t(__x);
|
|
__t *= __y;
|
|
return __t;
|
|
}
|
|
|
|
template <class _Tp>
|
|
inline complex<_Tp>
|
|
operator*(const _Tp &__x, const complex<_Tp> &__y) {
|
|
complex<_Tp> __t(__y);
|
|
__t *= __x;
|
|
return __t;
|
|
}
|
|
|
|
template <class _Tp>
|
|
complex<_Tp>
|
|
operator/(const complex<_Tp> &__z, const complex<_Tp> &__w) {
|
|
int __ilogbw = 0;
|
|
_Tp __a = __z.real();
|
|
_Tp __b = __z.imag();
|
|
_Tp __c = __w.real();
|
|
_Tp __d = __w.imag();
|
|
_Tp __logbw = logb(fmax(fabs(__c), fabs(__d)));
|
|
if (std::isfinite(__logbw)) {
|
|
__ilogbw = static_cast<int>(__logbw);
|
|
__c = scalbn(__c, -__ilogbw);
|
|
__d = scalbn(__d, -__ilogbw);
|
|
}
|
|
_Tp __denom = __c * __c + __d * __d;
|
|
_Tp __x = scalbn((__a * __c + __b * __d) / __denom, -__ilogbw);
|
|
_Tp __y = scalbn((__b * __c - __a * __d) / __denom, -__ilogbw);
|
|
if (std::isnan(__x) && std::isnan(__y)) {
|
|
if ((__denom == _Tp(0)) && (!std::isnan(__a) || !std::isnan(__b))) {
|
|
__x = copysign(_Tp(INFINITY), __c) * __a;
|
|
__y = copysign(_Tp(INFINITY), __c) * __b;
|
|
} else if ((std::isinf(__a) || std::isinf(__b)) && std::isfinite(__c) && std::isfinite(__d)) {
|
|
__a = copysign(std::isinf(__a) ? _Tp(1) : _Tp(0), __a);
|
|
__b = copysign(std::isinf(__b) ? _Tp(1) : _Tp(0), __b);
|
|
__x = _Tp(INFINITY) * (__a * __c + __b * __d);
|
|
__y = _Tp(INFINITY) * (__b * __c - __a * __d);
|
|
} else if (std::isinf(__logbw) && __logbw > _Tp(0) && std::isfinite(__a) && std::isfinite(__b)) {
|
|
__c = copysign(std::isinf(__c) ? _Tp(1) : _Tp(0), __c);
|
|
__d = copysign(std::isinf(__d) ? _Tp(1) : _Tp(0), __d);
|
|
__x = _Tp(0) * (__a * __c + __b * __d);
|
|
__y = _Tp(0) * (__b * __c - __a * __d);
|
|
}
|
|
}
|
|
return complex<_Tp>(__x, __y);
|
|
}
|
|
|
|
template <class _Tp>
|
|
inline complex<_Tp>
|
|
operator/(const complex<_Tp> &__x, const _Tp &__y) {
|
|
return complex<_Tp>(__x.real() / __y, __x.imag() / __y);
|
|
}
|
|
|
|
template <class _Tp>
|
|
inline complex<_Tp>
|
|
operator/(const _Tp &__x, const complex<_Tp> &__y) {
|
|
complex<_Tp> __t(__x);
|
|
__t /= __y;
|
|
return __t;
|
|
}
|
|
|
|
template <class _Tp>
|
|
inline complex<_Tp>
|
|
operator+(const complex<_Tp> &__x) {
|
|
return __x;
|
|
}
|
|
|
|
template <class _Tp>
|
|
inline complex<_Tp>
|
|
operator-(const complex<_Tp> &__x) {
|
|
return complex<_Tp>(-__x.real(), -__x.imag());
|
|
}
|
|
|
|
template <class _Tp>
|
|
inline bool
|
|
operator==(const complex<_Tp> &__x, const complex<_Tp> &__y) {
|
|
return __x.real() == __y.real() && __x.imag() == __y.imag();
|
|
}
|
|
|
|
template <class _Tp>
|
|
inline bool
|
|
operator==(const complex<_Tp> &__x, const _Tp &__y) {
|
|
return __x.real() == __y && __x.imag() == 0;
|
|
}
|
|
|
|
template <class _Tp>
|
|
inline bool
|
|
operator==(const _Tp &__x, const complex<_Tp> &__y) {
|
|
return __x == __y.real() && 0 == __y.imag();
|
|
}
|
|
|
|
template <class _Tp>
|
|
inline bool
|
|
operator!=(const complex<_Tp> &__x, const complex<_Tp> &__y) {
|
|
return !(__x == __y);
|
|
}
|
|
|
|
template <class _Tp>
|
|
inline bool
|
|
operator!=(const complex<_Tp> &__x, const _Tp &__y) {
|
|
return !(__x == __y);
|
|
}
|
|
|
|
template <class _Tp>
|
|
inline bool
|
|
operator!=(const _Tp &__x, const complex<_Tp> &__y) {
|
|
return !(__x == __y);
|
|
}
|
|
|
|
template <class _Tp> _Tp abs(const std::complex<_Tp> &__c);
|
|
|
|
// arg
|
|
|
|
template <class _Tp> _Tp arg(const std::complex<_Tp> &__c);
|
|
|
|
// norm
|
|
|
|
template <class _Tp> _Tp norm(const std::complex<_Tp> &__c);
|
|
|
|
// conj
|
|
|
|
template <class _Tp> std::complex<_Tp> conj(const std::complex<_Tp> &__c);
|
|
|
|
// proj
|
|
|
|
template <class _Tp> std::complex<_Tp> proj(const std::complex<_Tp> &__c);
|
|
|
|
// polar
|
|
|
|
template <class _Tp>
|
|
complex<_Tp> polar(const _Tp &__rho, const _Tp &__theta = _Tp());
|
|
|
|
// log
|
|
|
|
template <class _Tp> std::complex<_Tp> log(const std::complex<_Tp> &__x);
|
|
|
|
// log10
|
|
|
|
template <class _Tp> std::complex<_Tp> log10(const std::complex<_Tp> &__x);
|
|
|
|
// sqrt
|
|
|
|
template <class _Tp>
|
|
std::complex<_Tp> sqrt(const std::complex<_Tp> &__x);
|
|
|
|
// exp
|
|
|
|
template <class _Tp>
|
|
std::complex<_Tp> exp(const std::complex<_Tp> &__x);
|
|
|
|
// pow
|
|
|
|
template <class _Tp>
|
|
std::complex<_Tp> pow(const std::complex<_Tp> &__x,
|
|
const std::complex<_Tp> &__y);
|
|
|
|
// __sqr, computes pow(x, 2)
|
|
|
|
template <class _Tp> std::complex<_Tp> __sqr(const std::complex<_Tp> &__x);
|
|
|
|
// asinh
|
|
|
|
template <class _Tp>
|
|
std::complex<_Tp> asinh(const std::complex<_Tp> &__x);
|
|
|
|
// acosh
|
|
|
|
template <class _Tp>
|
|
std::complex<_Tp> acosh(const std::complex<_Tp> &__x);
|
|
|
|
// atanh
|
|
|
|
template <class _Tp>
|
|
std::complex<_Tp> atanh(const std::complex<_Tp> &__x);
|
|
|
|
// sinh
|
|
|
|
template <class _Tp>
|
|
std::complex<_Tp> sinh(const std::complex<_Tp> &__x);
|
|
|
|
// cosh
|
|
|
|
template <class _Tp>
|
|
std::complex<_Tp> cosh(const std::complex<_Tp> &__x);
|
|
|
|
// tanh
|
|
|
|
template <class _Tp>
|
|
std::complex<_Tp> tanh(const std::complex<_Tp> &__x);
|
|
|
|
// asin
|
|
|
|
template <class _Tp>
|
|
std::complex<_Tp> asin(const std::complex<_Tp> &__x);
|
|
|
|
// acos
|
|
|
|
template <class _Tp>
|
|
std::complex<_Tp> acos(const std::complex<_Tp> &__x);
|
|
|
|
// atan
|
|
|
|
template <class _Tp>
|
|
std::complex<_Tp> atan(const std::complex<_Tp> &__x);
|
|
|
|
// sin
|
|
|
|
template <class _Tp>
|
|
std::complex<_Tp> sin(const std::complex<_Tp> &__x);
|
|
|
|
// cos
|
|
|
|
template <class _Tp> std::complex<_Tp> cos(const std::complex<_Tp> &__x);
|
|
|
|
// tan
|
|
|
|
template <class _Tp>
|
|
std::complex<_Tp> tan(const std::complex<_Tp> &__x);
|
|
|
|
} // namespace std
|