From 3c99b4831c608e6cba2b483019142ba27d629979 Mon Sep 17 00:00:00 2001 From: zerico <71151164+ZERICO2005@users.noreply.github.com> Date: Fri, 31 Oct 2025 16:09:20 -0600 Subject: [PATCH] added C++ --- src/libc/include/complex.h | 10 +- src/libc/include/tgmath.h | 1 + src/libcxx/header_test.cpp | 3 + src/libcxx/include/__config | 1 + src/libcxx/include/ccomplex | 9 + src/libcxx/include/complex | 1179 +++++++++++++++++ src/libcxx/include/type_traits | 23 + test/floating_point/float32_math/src/main.cpp | 11 +- test/floating_point/float64_math/src/main.cpp | 15 +- 9 files changed, 1246 insertions(+), 6 deletions(-) create mode 100644 src/libcxx/include/ccomplex create mode 100644 src/libcxx/include/complex diff --git a/src/libc/include/complex.h b/src/libc/include/complex.h index 7ca66469b..fd07013e6 100644 --- a/src/libc/include/complex.h +++ b/src/libc/include/complex.h @@ -1,13 +1,17 @@ #ifndef _COMPLEX_H #define _COMPLEX_H +#ifdef __cplusplus + +#include + +#else /* __cplusplus */ + #ifndef __FAST_MATH__ #warning "-ffast-math is required for complex multiplication and division to work properly at this time" #endif -#ifndef __cplusplus #define complex _Complex -#endif #ifdef _Imaginary #define imaginary _Imaginary @@ -121,4 +125,6 @@ double _Complex catanh(double _Complex); float _Complex catanhf(float _Complex); long double _Complex catanhl(long double _Complex); +#endif /* __cplusplus */ + #endif /* _COMPLEX_H */ diff --git a/src/libc/include/tgmath.h b/src/libc/include/tgmath.h index 81f8d5516..be46e80b1 100644 --- a/src/libc/include/tgmath.h +++ b/src/libc/include/tgmath.h @@ -4,6 +4,7 @@ #ifdef __cplusplus #include +#include #else /* __cplusplus */ diff --git a/src/libcxx/header_test.cpp b/src/libcxx/header_test.cpp index e41236337..5f4054828 100644 --- a/src/libcxx/header_test.cpp +++ b/src/libcxx/header_test.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -10,6 +11,7 @@ #include #include #include +#include #if __cplusplus >= 201907L #include #endif // __cplusplus >= 201907L @@ -45,6 +47,7 @@ #include #include #include +#include #include #include #include diff --git a/src/libcxx/include/__config b/src/libcxx/include/__config index a1b666fc3..b4f032950 100644 --- a/src/libcxx/include/__config +++ b/src/libcxx/include/__config @@ -14,5 +14,6 @@ #define _EZCXX_NODEBUG __attribute__((__nodebug__)) #define _EZCXX_TEMPLATE_VIS __attribute__ ((__type_visibility__("default"))) #define _EZCXX_LIFETIMEBOUND [[_Clang::__lifetimebound__]] +#define _EZCXX_INLINE_VISIBILITY _EZCXX_HIDE_FROM_ABI #endif // _EZCXX_CONFIG diff --git a/src/libcxx/include/ccomplex b/src/libcxx/include/ccomplex new file mode 100644 index 000000000..a9385c078 --- /dev/null +++ b/src/libcxx/include/ccomplex @@ -0,0 +1,9 @@ +// -*- C++ -*- +#ifndef _EZCXX_CCOMPLEX +#define _EZCXX_CCOMPLEX + +#include + +#pragma clang system_header + +#endif // _EZCXX_CCOMPLEX diff --git a/src/libcxx/include/complex b/src/libcxx/include/complex new file mode 100644 index 000000000..d8d834042 --- /dev/null +++ b/src/libcxx/include/complex @@ -0,0 +1,1179 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef _EZCXX_COMPLEX +#define _EZCXX_COMPLEX + +#include <__config> +#include +#include + +#pragma clang system_header + +namespace std { + +template class _EZCXX_TEMPLATE_VIS complex; + +template complex<_Tp> operator*(const complex<_Tp>& __z, const complex<_Tp>& __w); +template complex<_Tp> operator/(const complex<_Tp>& __x, const complex<_Tp>& __y); + +template +class _EZCXX_TEMPLATE_VIS complex +{ +public: + typedef _Tp value_type; +private: + value_type __re_; + value_type __im_; +public: + _EZCXX_INLINE_VISIBILITY constexpr + complex(const value_type& __re = value_type(), const value_type& __im = value_type()) + : __re_(__re), __im_(__im) {} + template _EZCXX_INLINE_VISIBILITY constexpr + complex(const complex<_Xp>& __c) + : __re_(__c.real()), __im_(__c.imag()) {} + + _EZCXX_INLINE_VISIBILITY constexpr value_type real() const {return __re_;} + _EZCXX_INLINE_VISIBILITY constexpr value_type imag() const {return __im_;} + + _EZCXX_INLINE_VISIBILITY void real(value_type __re) {__re_ = __re;} + _EZCXX_INLINE_VISIBILITY void imag(value_type __im) {__im_ = __im;} + + _EZCXX_INLINE_VISIBILITY complex& operator= (const value_type& __re) + {__re_ = __re; __im_ = value_type(); return *this;} + _EZCXX_INLINE_VISIBILITY complex& operator+=(const value_type& __re) {__re_ += __re; return *this;} + _EZCXX_INLINE_VISIBILITY complex& operator-=(const value_type& __re) {__re_ -= __re; return *this;} + _EZCXX_INLINE_VISIBILITY complex& operator*=(const value_type& __re) {__re_ *= __re; __im_ *= __re; return *this;} + _EZCXX_INLINE_VISIBILITY complex& operator/=(const value_type& __re) {__re_ /= __re; __im_ /= __re; return *this;} + + template _EZCXX_INLINE_VISIBILITY complex& operator= (const complex<_Xp>& __c) + { + __re_ = __c.real(); + __im_ = __c.imag(); + return *this; + } + template _EZCXX_INLINE_VISIBILITY complex& operator+=(const complex<_Xp>& __c) + { + __re_ += __c.real(); + __im_ += __c.imag(); + return *this; + } + template _EZCXX_INLINE_VISIBILITY complex& operator-=(const complex<_Xp>& __c) + { + __re_ -= __c.real(); + __im_ -= __c.imag(); + return *this; + } + template _EZCXX_INLINE_VISIBILITY complex& operator*=(const complex<_Xp>& __c) + { + *this = *this * complex(__c.real(), __c.imag()); + return *this; + } + template _EZCXX_INLINE_VISIBILITY complex& operator/=(const complex<_Xp>& __c) + { + *this = *this / complex(__c.real(), __c.imag()); + return *this; + } +}; + +template<> class _EZCXX_TEMPLATE_VIS complex; +template<> class _EZCXX_TEMPLATE_VIS complex; + +template<> +class _EZCXX_TEMPLATE_VIS complex +{ + float __re_; + float __im_; +public: + typedef float value_type; + + _EZCXX_INLINE_VISIBILITY constexpr complex(float __re = 0.0f, float __im = 0.0f) + : __re_(__re), __im_(__im) {} + _EZCXX_INLINE_VISIBILITY + explicit constexpr complex(const complex& __c); + _EZCXX_INLINE_VISIBILITY + explicit constexpr complex(const complex& __c); + + _EZCXX_INLINE_VISIBILITY constexpr float real() const {return __re_;} + _EZCXX_INLINE_VISIBILITY constexpr float imag() const {return __im_;} + + _EZCXX_INLINE_VISIBILITY void real(value_type __re) {__re_ = __re;} + _EZCXX_INLINE_VISIBILITY void imag(value_type __im) {__im_ = __im;} + + _EZCXX_INLINE_VISIBILITY complex& operator= (float __re) + {__re_ = __re; __im_ = value_type(); return *this;} + _EZCXX_INLINE_VISIBILITY complex& operator+=(float __re) {__re_ += __re; return *this;} + _EZCXX_INLINE_VISIBILITY complex& operator-=(float __re) {__re_ -= __re; return *this;} + _EZCXX_INLINE_VISIBILITY complex& operator*=(float __re) {__re_ *= __re; __im_ *= __re; return *this;} + _EZCXX_INLINE_VISIBILITY complex& operator/=(float __re) {__re_ /= __re; __im_ /= __re; return *this;} + + template _EZCXX_INLINE_VISIBILITY complex& operator= (const complex<_Xp>& __c) + { + __re_ = __c.real(); + __im_ = __c.imag(); + return *this; + } + template _EZCXX_INLINE_VISIBILITY complex& operator+=(const complex<_Xp>& __c) + { + __re_ += __c.real(); + __im_ += __c.imag(); + return *this; + } + template _EZCXX_INLINE_VISIBILITY complex& operator-=(const complex<_Xp>& __c) + { + __re_ -= __c.real(); + __im_ -= __c.imag(); + return *this; + } + template _EZCXX_INLINE_VISIBILITY complex& operator*=(const complex<_Xp>& __c) + { + *this = *this * complex(__c.real(), __c.imag()); + return *this; + } + template _EZCXX_INLINE_VISIBILITY complex& operator/=(const complex<_Xp>& __c) + { + *this = *this / complex(__c.real(), __c.imag()); + return *this; + } +}; + +template<> +class _EZCXX_TEMPLATE_VIS complex +{ + double __re_; + double __im_; +public: + typedef double value_type; + + _EZCXX_INLINE_VISIBILITY constexpr complex(double __re = 0.0, double __im = 0.0) + : __re_(__re), __im_(__im) {} + _EZCXX_INLINE_VISIBILITY + constexpr complex(const complex& __c); + _EZCXX_INLINE_VISIBILITY + explicit constexpr complex(const complex& __c); + + _EZCXX_INLINE_VISIBILITY constexpr double real() const {return __re_;} + _EZCXX_INLINE_VISIBILITY constexpr double imag() const {return __im_;} + + _EZCXX_INLINE_VISIBILITY void real(value_type __re) {__re_ = __re;} + _EZCXX_INLINE_VISIBILITY void imag(value_type __im) {__im_ = __im;} + + _EZCXX_INLINE_VISIBILITY complex& operator= (double __re) + {__re_ = __re; __im_ = value_type(); return *this;} + _EZCXX_INLINE_VISIBILITY complex& operator+=(double __re) {__re_ += __re; return *this;} + _EZCXX_INLINE_VISIBILITY complex& operator-=(double __re) {__re_ -= __re; return *this;} + _EZCXX_INLINE_VISIBILITY complex& operator*=(double __re) {__re_ *= __re; __im_ *= __re; return *this;} + _EZCXX_INLINE_VISIBILITY complex& operator/=(double __re) {__re_ /= __re; __im_ /= __re; return *this;} + + template _EZCXX_INLINE_VISIBILITY complex& operator= (const complex<_Xp>& __c) + { + __re_ = __c.real(); + __im_ = __c.imag(); + return *this; + } + template _EZCXX_INLINE_VISIBILITY complex& operator+=(const complex<_Xp>& __c) + { + __re_ += __c.real(); + __im_ += __c.imag(); + return *this; + } + template _EZCXX_INLINE_VISIBILITY complex& operator-=(const complex<_Xp>& __c) + { + __re_ -= __c.real(); + __im_ -= __c.imag(); + return *this; + } + template _EZCXX_INLINE_VISIBILITY complex& operator*=(const complex<_Xp>& __c) + { + *this = *this * complex(__c.real(), __c.imag()); + return *this; + } + template _EZCXX_INLINE_VISIBILITY complex& operator/=(const complex<_Xp>& __c) + { + *this = *this / complex(__c.real(), __c.imag()); + return *this; + } +}; + +template<> +class _EZCXX_TEMPLATE_VIS complex +{ + long double __re_; + long double __im_; +public: + typedef long double value_type; + + _EZCXX_INLINE_VISIBILITY constexpr complex(long double __re = 0.0L, long double __im = 0.0L) + : __re_(__re), __im_(__im) {} + _EZCXX_INLINE_VISIBILITY + constexpr complex(const complex& __c); + _EZCXX_INLINE_VISIBILITY + constexpr complex(const complex& __c); + + _EZCXX_INLINE_VISIBILITY constexpr long double real() const {return __re_;} + _EZCXX_INLINE_VISIBILITY constexpr long double imag() const {return __im_;} + + _EZCXX_INLINE_VISIBILITY void real(value_type __re) {__re_ = __re;} + _EZCXX_INLINE_VISIBILITY void imag(value_type __im) {__im_ = __im;} + + _EZCXX_INLINE_VISIBILITY complex& operator= (long double __re) + {__re_ = __re; __im_ = value_type(); return *this;} + _EZCXX_INLINE_VISIBILITY complex& operator+=(long double __re) {__re_ += __re; return *this;} + _EZCXX_INLINE_VISIBILITY complex& operator-=(long double __re) {__re_ -= __re; return *this;} + _EZCXX_INLINE_VISIBILITY complex& operator*=(long double __re) {__re_ *= __re; __im_ *= __re; return *this;} + _EZCXX_INLINE_VISIBILITY complex& operator/=(long double __re) {__re_ /= __re; __im_ /= __re; return *this;} + + template _EZCXX_INLINE_VISIBILITY complex& operator= (const complex<_Xp>& __c) + { + __re_ = __c.real(); + __im_ = __c.imag(); + return *this; + } + template _EZCXX_INLINE_VISIBILITY complex& operator+=(const complex<_Xp>& __c) + { + __re_ += __c.real(); + __im_ += __c.imag(); + return *this; + } + template _EZCXX_INLINE_VISIBILITY complex& operator-=(const complex<_Xp>& __c) + { + __re_ -= __c.real(); + __im_ -= __c.imag(); + return *this; + } + template _EZCXX_INLINE_VISIBILITY complex& operator*=(const complex<_Xp>& __c) + { + *this = *this * complex(__c.real(), __c.imag()); + return *this; + } + template _EZCXX_INLINE_VISIBILITY complex& operator/=(const complex<_Xp>& __c) + { + *this = *this / complex(__c.real(), __c.imag()); + return *this; + } +}; + +inline +constexpr +complex::complex(const complex& __c) + : __re_(__c.real()), __im_(__c.imag()) {} + +inline +constexpr +complex::complex(const complex& __c) + : __re_(__c.real()), __im_(__c.imag()) {} + +inline +constexpr +complex::complex(const complex& __c) + : __re_(__c.real()), __im_(__c.imag()) {} + +inline +constexpr +complex::complex(const complex& __c) + : __re_(__c.real()), __im_(__c.imag()) {} + +inline +constexpr +complex::complex(const complex& __c) + : __re_(__c.real()), __im_(__c.imag()) {} + +inline +constexpr +complex::complex(const complex& __c) + : __re_(__c.real()), __im_(__c.imag()) {} + +// 26.3.6 operators: + +template +inline _EZCXX_INLINE_VISIBILITY +complex<_Tp> +operator+(const complex<_Tp>& __x, const complex<_Tp>& __y) +{ + complex<_Tp> __t(__x); + __t += __y; + return __t; +} + +template +inline _EZCXX_INLINE_VISIBILITY +complex<_Tp> +operator+(const complex<_Tp>& __x, const _Tp& __y) +{ + complex<_Tp> __t(__x); + __t += __y; + return __t; +} + +template +inline _EZCXX_INLINE_VISIBILITY +complex<_Tp> +operator+(const _Tp& __x, const complex<_Tp>& __y) +{ + complex<_Tp> __t(__y); + __t += __x; + return __t; +} + +template +inline _EZCXX_INLINE_VISIBILITY +complex<_Tp> +operator-(const complex<_Tp>& __x, const complex<_Tp>& __y) +{ + complex<_Tp> __t(__x); + __t -= __y; + return __t; +} + +template +inline _EZCXX_INLINE_VISIBILITY +complex<_Tp> +operator-(const complex<_Tp>& __x, const _Tp& __y) +{ + complex<_Tp> __t(__x); + __t -= __y; + return __t; +} + +template +inline _EZCXX_INLINE_VISIBILITY +complex<_Tp> +operator-(const _Tp& __x, const complex<_Tp>& __y) +{ + complex<_Tp> __t(-__y); + __t += __x; + return __t; +} + +template +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 +inline _EZCXX_INLINE_VISIBILITY +complex<_Tp> +operator*(const complex<_Tp>& __x, const _Tp& __y) +{ + complex<_Tp> __t(__x); + __t *= __y; + return __t; +} + +template +inline _EZCXX_INLINE_VISIBILITY +complex<_Tp> +operator*(const _Tp& __x, const complex<_Tp>& __y) +{ + complex<_Tp> __t(__y); + __t *= __x; + return __t; +} + +template +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(__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 +inline _EZCXX_INLINE_VISIBILITY +complex<_Tp> +operator/(const complex<_Tp>& __x, const _Tp& __y) +{ + return complex<_Tp>(__x.real() / __y, __x.imag() / __y); +} + +template +inline _EZCXX_INLINE_VISIBILITY +complex<_Tp> +operator/(const _Tp& __x, const complex<_Tp>& __y) +{ + complex<_Tp> __t(__x); + __t /= __y; + return __t; +} + +template +inline _EZCXX_INLINE_VISIBILITY +complex<_Tp> +operator+(const complex<_Tp>& __x) +{ + return __x; +} + +template +inline _EZCXX_INLINE_VISIBILITY +complex<_Tp> +operator-(const complex<_Tp>& __x) +{ + return complex<_Tp>(-__x.real(), -__x.imag()); +} + +template +inline _EZCXX_INLINE_VISIBILITY constexpr +bool +operator==(const complex<_Tp>& __x, const complex<_Tp>& __y) +{ + return __x.real() == __y.real() && __x.imag() == __y.imag(); +} + +template +inline _EZCXX_INLINE_VISIBILITY constexpr +bool +operator==(const complex<_Tp>& __x, const _Tp& __y) +{ + return __x.real() == __y && __x.imag() == 0; +} + +template +inline _EZCXX_INLINE_VISIBILITY constexpr +bool +operator==(const _Tp& __x, const complex<_Tp>& __y) +{ + return __x == __y.real() && 0 == __y.imag(); +} + +template +inline _EZCXX_INLINE_VISIBILITY constexpr +bool +operator!=(const complex<_Tp>& __x, const complex<_Tp>& __y) +{ + return !(__x == __y); +} + +template +inline _EZCXX_INLINE_VISIBILITY constexpr +bool +operator!=(const complex<_Tp>& __x, const _Tp& __y) +{ + return !(__x == __y); +} + +template +inline _EZCXX_INLINE_VISIBILITY constexpr +bool +operator!=(const _Tp& __x, const complex<_Tp>& __y) +{ + return !(__x == __y); +} + +// 26.3.7 values: + +template ::value, bool = is_floating_point<_Tp>::value> +struct __libcpp_complex_overload_traits {}; + +// Integral Types +template +struct __libcpp_complex_overload_traits<_Tp, true, false> +{ + typedef double _ValueType; + typedef complex _ComplexType; +}; + +// Floating point types +template +struct __libcpp_complex_overload_traits<_Tp, false, true> +{ + typedef _Tp _ValueType; + typedef complex<_Tp> _ComplexType; +}; + +// real + +template +inline _EZCXX_INLINE_VISIBILITY constexpr +_Tp +real(const complex<_Tp>& __c) +{ + return __c.real(); +} + +template +inline _EZCXX_INLINE_VISIBILITY constexpr +typename __libcpp_complex_overload_traits<_Tp>::_ValueType +real(_Tp __re) +{ + return __re; +} + +// imag + +template +inline _EZCXX_INLINE_VISIBILITY constexpr +_Tp +imag(const complex<_Tp>& __c) +{ + return __c.imag(); +} + +template +inline _EZCXX_INLINE_VISIBILITY constexpr +typename __libcpp_complex_overload_traits<_Tp>::_ValueType +imag(_Tp) +{ + return 0; +} + +// abs + +template +inline _EZCXX_INLINE_VISIBILITY +_Tp +abs(const complex<_Tp>& __c) +{ + return hypot(__c.real(), __c.imag()); +} + +// arg + +template +inline _EZCXX_INLINE_VISIBILITY +_Tp +arg(const complex<_Tp>& __c) +{ + return atan2(__c.imag(), __c.real()); +} + +template +inline _EZCXX_INLINE_VISIBILITY +typename enable_if< + is_same<_Tp, long double>::value, + long double +>::type +arg(_Tp __re) +{ + return atan2l(0.L, __re); +} + +template +inline _EZCXX_INLINE_VISIBILITY +typename enable_if +< + is_integral<_Tp>::value || is_same<_Tp, double>::value, + double +>::type +arg(_Tp __re) +{ + return atan2(0., __re); +} + +template +inline _EZCXX_INLINE_VISIBILITY +typename enable_if< + is_same<_Tp, float>::value, + float +>::type +arg(_Tp __re) +{ + return atan2f(0.F, __re); +} + +// norm + +template +inline _EZCXX_INLINE_VISIBILITY +_Tp +norm(const complex<_Tp>& __c) +{ + if (std::isinf(__c.real())) + return abs(__c.real()); + if (std::isinf(__c.imag())) + return abs(__c.imag()); + return __c.real() * __c.real() + __c.imag() * __c.imag(); +} + +template +inline _EZCXX_INLINE_VISIBILITY +typename __libcpp_complex_overload_traits<_Tp>::_ValueType +norm(_Tp __re) +{ + typedef typename __libcpp_complex_overload_traits<_Tp>::_ValueType _ValueType; + return static_cast<_ValueType>(__re) * __re; +} + +// conj + +template +inline _EZCXX_INLINE_VISIBILITY +complex<_Tp> +conj(const complex<_Tp>& __c) +{ + return complex<_Tp>(__c.real(), -__c.imag()); +} + +template +inline _EZCXX_INLINE_VISIBILITY +typename __libcpp_complex_overload_traits<_Tp>::_ComplexType +conj(_Tp __re) +{ + typedef typename __libcpp_complex_overload_traits<_Tp>::_ComplexType _ComplexType; + return _ComplexType(__re); +} + +// proj + +template +inline _EZCXX_INLINE_VISIBILITY +complex<_Tp> +proj(const complex<_Tp>& __c) +{ + complex<_Tp> __r = __c; + if (std::isinf(__c.real()) || std::isinf(__c.imag())) + __r = complex<_Tp>(INFINITY, copysign(_Tp(0), __c.imag())); + return __r; +} + +template +inline _EZCXX_INLINE_VISIBILITY +typename enable_if +< + is_floating_point<_Tp>::value, + typename __libcpp_complex_overload_traits<_Tp>::_ComplexType +>::type +proj(_Tp __re) +{ + if (std::isinf(__re)) + __re = abs(__re); + return complex<_Tp>(__re); +} + +template +inline _EZCXX_INLINE_VISIBILITY +typename enable_if +< + is_integral<_Tp>::value, + typename __libcpp_complex_overload_traits<_Tp>::_ComplexType +>::type +proj(_Tp __re) +{ + typedef typename __libcpp_complex_overload_traits<_Tp>::_ComplexType _ComplexType; + return _ComplexType(__re); +} + +// polar + +template +complex<_Tp> +polar(const _Tp& __rho, const _Tp& __theta = _Tp()) +{ + if (std::isnan(__rho) || signbit(__rho)) + return complex<_Tp>(_Tp(NAN), _Tp(NAN)); + if (std::isnan(__theta)) + { + if (std::isinf(__rho)) + return complex<_Tp>(__rho, __theta); + return complex<_Tp>(__theta, __theta); + } + if (std::isinf(__theta)) + { + if (std::isinf(__rho)) + return complex<_Tp>(__rho, _Tp(NAN)); + return complex<_Tp>(_Tp(NAN), _Tp(NAN)); + } + _Tp __x = __rho * cos(__theta); + if (std::isnan(__x)) + __x = 0; + _Tp __y = __rho * sin(__theta); + if (std::isnan(__y)) + __y = 0; + return complex<_Tp>(__x, __y); +} + +// log + +template +inline _EZCXX_INLINE_VISIBILITY +complex<_Tp> +log(const complex<_Tp>& __x) +{ + return complex<_Tp>(log(abs(__x)), arg(__x)); +} + +// log10 + +template +inline _EZCXX_INLINE_VISIBILITY +complex<_Tp> +log10(const complex<_Tp>& __x) +{ + return log(__x) / log(_Tp(10)); +} + +// sqrt + +template +complex<_Tp> +sqrt(const complex<_Tp>& __x) +{ + if (std::isinf(__x.imag())) + return complex<_Tp>(_Tp(INFINITY), __x.imag()); + if (std::isinf(__x.real())) + { + if (__x.real() > _Tp(0)) + return complex<_Tp>(__x.real(), std::isnan(__x.imag()) ? __x.imag() : copysign(_Tp(0), __x.imag())); + return complex<_Tp>(std::isnan(__x.imag()) ? __x.imag() : _Tp(0), copysign(__x.real(), __x.imag())); + } + return polar(sqrt(abs(__x)), arg(__x) / _Tp(2)); +} + +// exp + +template +complex<_Tp> +exp(const complex<_Tp>& __x) +{ + _Tp __i = __x.imag(); + if (__i == 0) { + return complex<_Tp>(exp(__x.real()), copysign(_Tp(0), __x.imag())); + } + if (std::isinf(__x.real())) + { + if (__x.real() < _Tp(0)) + { + if (!std::isfinite(__i)) + __i = _Tp(1); + } + else if (__i == 0 || !std::isfinite(__i)) + { + if (std::isinf(__i)) + __i = _Tp(NAN); + return complex<_Tp>(__x.real(), __i); + } + } + _Tp __e = exp(__x.real()); + return complex<_Tp>(__e * cos(__i), __e * sin(__i)); +} + +// pow + +template +inline _EZCXX_INLINE_VISIBILITY +complex<_Tp> +pow(const complex<_Tp>& __x, const complex<_Tp>& __y) +{ + return exp(__y * log(__x)); +} + +template +inline _EZCXX_INLINE_VISIBILITY +complex::type> +pow(const complex<_Tp>& __x, const complex<_Up>& __y) +{ + typedef complex::type> result_type; + return std::pow(result_type(__x), result_type(__y)); +} + +template +inline _EZCXX_INLINE_VISIBILITY +typename enable_if +< + is_arithmetic<_Up>::value, + complex::type> +>::type +pow(const complex<_Tp>& __x, const _Up& __y) +{ + typedef complex::type> result_type; + return std::pow(result_type(__x), result_type(__y)); +} + +template +inline _EZCXX_INLINE_VISIBILITY +typename enable_if +< + is_arithmetic<_Tp>::value, + complex::type> +>::type +pow(const _Tp& __x, const complex<_Up>& __y) +{ + typedef complex::type> result_type; + return std::pow(result_type(__x), result_type(__y)); +} + +// __sqr, computes pow(x, 2) + +template +inline _EZCXX_INLINE_VISIBILITY +complex<_Tp> +__sqr(const complex<_Tp>& __x) +{ + return complex<_Tp>((__x.real() - __x.imag()) * (__x.real() + __x.imag()), _Tp(2) * __x.real() * __x.imag()); +} + +// asinh + +template +complex<_Tp> +asinh(const complex<_Tp>& __x) +{ + const _Tp __pi(atan2(+0., -0.)); + if (std::isinf(__x.real())) + { + if (std::isnan(__x.imag())) + return __x; + if (std::isinf(__x.imag())) + return complex<_Tp>(__x.real(), copysign(__pi * _Tp(0.25), __x.imag())); + return complex<_Tp>(__x.real(), copysign(_Tp(0), __x.imag())); + } + if (std::isnan(__x.real())) + { + if (std::isinf(__x.imag())) + return complex<_Tp>(__x.imag(), __x.real()); + if (__x.imag() == 0) + return __x; + return complex<_Tp>(__x.real(), __x.real()); + } + if (std::isinf(__x.imag())) + return complex<_Tp>(copysign(__x.imag(), __x.real()), copysign(__pi/_Tp(2), __x.imag())); + complex<_Tp> __z = log(__x + sqrt(__sqr(__x) + _Tp(1))); + return complex<_Tp>(copysign(__z.real(), __x.real()), copysign(__z.imag(), __x.imag())); +} + +// acosh + +template +complex<_Tp> +acosh(const complex<_Tp>& __x) +{ + const _Tp __pi(atan2(+0., -0.)); + if (std::isinf(__x.real())) + { + if (std::isnan(__x.imag())) + return complex<_Tp>(abs(__x.real()), __x.imag()); + if (std::isinf(__x.imag())) + { + if (__x.real() > 0) + return complex<_Tp>(__x.real(), copysign(__pi * _Tp(0.25), __x.imag())); + else + return complex<_Tp>(-__x.real(), copysign(__pi * _Tp(0.75), __x.imag())); + } + if (__x.real() < 0) + return complex<_Tp>(-__x.real(), copysign(__pi, __x.imag())); + return complex<_Tp>(__x.real(), copysign(_Tp(0), __x.imag())); + } + if (std::isnan(__x.real())) + { + if (std::isinf(__x.imag())) + return complex<_Tp>(abs(__x.imag()), __x.real()); + return complex<_Tp>(__x.real(), __x.real()); + } + if (std::isinf(__x.imag())) + return complex<_Tp>(abs(__x.imag()), copysign(__pi/_Tp(2), __x.imag())); + complex<_Tp> __z = log(__x + sqrt(__sqr(__x) - _Tp(1))); + return complex<_Tp>(copysign(__z.real(), _Tp(0)), copysign(__z.imag(), __x.imag())); +} + +// atanh + +template +complex<_Tp> +atanh(const complex<_Tp>& __x) +{ + const _Tp __pi(atan2(+0., -0.)); + if (std::isinf(__x.imag())) + { + return complex<_Tp>(copysign(_Tp(0), __x.real()), copysign(__pi/_Tp(2), __x.imag())); + } + if (std::isnan(__x.imag())) + { + if (std::isinf(__x.real()) || __x.real() == 0) + return complex<_Tp>(copysign(_Tp(0), __x.real()), __x.imag()); + return complex<_Tp>(__x.imag(), __x.imag()); + } + if (std::isnan(__x.real())) + { + return complex<_Tp>(__x.real(), __x.real()); + } + if (std::isinf(__x.real())) + { + return complex<_Tp>(copysign(_Tp(0), __x.real()), copysign(__pi/_Tp(2), __x.imag())); + } + if (abs(__x.real()) == _Tp(1) && __x.imag() == _Tp(0)) + { + return complex<_Tp>(copysign(_Tp(INFINITY), __x.real()), copysign(_Tp(0), __x.imag())); + } + complex<_Tp> __z = log((_Tp(1) + __x) / (_Tp(1) - __x)) / _Tp(2); + return complex<_Tp>(copysign(__z.real(), __x.real()), copysign(__z.imag(), __x.imag())); +} + +// sinh + +template +complex<_Tp> +sinh(const complex<_Tp>& __x) +{ + if (std::isinf(__x.real()) && !std::isfinite(__x.imag())) + return complex<_Tp>(__x.real(), _Tp(NAN)); + if (__x.real() == 0 && !std::isfinite(__x.imag())) + return complex<_Tp>(__x.real(), _Tp(NAN)); + if (__x.imag() == 0 && !std::isfinite(__x.real())) + return __x; + return complex<_Tp>(sinh(__x.real()) * cos(__x.imag()), cosh(__x.real()) * sin(__x.imag())); +} + +// cosh + +template +complex<_Tp> +cosh(const complex<_Tp>& __x) +{ + if (std::isinf(__x.real()) && !std::isfinite(__x.imag())) + return complex<_Tp>(abs(__x.real()), _Tp(NAN)); + if (__x.real() == 0 && !std::isfinite(__x.imag())) + return complex<_Tp>(_Tp(NAN), __x.real()); + if (__x.real() == 0 && __x.imag() == 0) + return complex<_Tp>(_Tp(1), __x.imag()); + if (__x.imag() == 0 && !std::isfinite(__x.real())) + return complex<_Tp>(abs(__x.real()), __x.imag()); + return complex<_Tp>(cosh(__x.real()) * cos(__x.imag()), sinh(__x.real()) * sin(__x.imag())); +} + +// tanh + +template +complex<_Tp> +tanh(const complex<_Tp>& __x) +{ + if (std::isinf(__x.real())) + { + if (!std::isfinite(__x.imag())) + return complex<_Tp>(copysign(_Tp(1), __x.real()), _Tp(0)); + return complex<_Tp>(copysign(_Tp(1), __x.real()), copysign(_Tp(0), sin(_Tp(2) * __x.imag()))); + } + if (std::isnan(__x.real()) && __x.imag() == 0) + return __x; + _Tp __2r(_Tp(2) * __x.real()); + _Tp __2i(_Tp(2) * __x.imag()); + _Tp __d(cosh(__2r) + cos(__2i)); + _Tp __2rsh(sinh(__2r)); + if (std::isinf(__2rsh) && std::isinf(__d)) + return complex<_Tp>(__2rsh > _Tp(0) ? _Tp(1) : _Tp(-1), __2i > _Tp(0) ? _Tp(0) : _Tp(-0.)); + return complex<_Tp>(__2rsh/__d, sin(__2i)/__d); +} + +// asin + +template +complex<_Tp> +asin(const complex<_Tp>& __x) +{ + complex<_Tp> __z = asinh(complex<_Tp>(-__x.imag(), __x.real())); + return complex<_Tp>(__z.imag(), -__z.real()); +} + +// acos + +template +complex<_Tp> +acos(const complex<_Tp>& __x) +{ + const _Tp __pi(atan2(+0., -0.)); + if (std::isinf(__x.real())) + { + if (std::isnan(__x.imag())) + return complex<_Tp>(__x.imag(), __x.real()); + if (std::isinf(__x.imag())) + { + if (__x.real() < _Tp(0)) + return complex<_Tp>(_Tp(0.75) * __pi, -__x.imag()); + return complex<_Tp>(_Tp(0.25) * __pi, -__x.imag()); + } + if (__x.real() < _Tp(0)) + return complex<_Tp>(__pi, signbit(__x.imag()) ? -__x.real() : __x.real()); + return complex<_Tp>(_Tp(0), signbit(__x.imag()) ? __x.real() : -__x.real()); + } + if (std::isnan(__x.real())) + { + if (std::isinf(__x.imag())) + return complex<_Tp>(__x.real(), -__x.imag()); + return complex<_Tp>(__x.real(), __x.real()); + } + if (std::isinf(__x.imag())) + return complex<_Tp>(__pi/_Tp(2), -__x.imag()); + if (__x.real() == 0 && (__x.imag() == 0 || isnan(__x.imag()))) + return complex<_Tp>(__pi/_Tp(2), -__x.imag()); + complex<_Tp> __z = log(__x + sqrt(__sqr(__x) - _Tp(1))); + if (signbit(__x.imag())) + return complex<_Tp>(abs(__z.imag()), abs(__z.real())); + return complex<_Tp>(abs(__z.imag()), -abs(__z.real())); +} + +// atan + +template +complex<_Tp> +atan(const complex<_Tp>& __x) +{ + complex<_Tp> __z = atanh(complex<_Tp>(-__x.imag(), __x.real())); + return complex<_Tp>(__z.imag(), -__z.real()); +} + +// sin + +template +complex<_Tp> +sin(const complex<_Tp>& __x) +{ + complex<_Tp> __z = sinh(complex<_Tp>(-__x.imag(), __x.real())); + return complex<_Tp>(__z.imag(), -__z.real()); +} + +// cos + +template +inline _EZCXX_INLINE_VISIBILITY +complex<_Tp> +cos(const complex<_Tp>& __x) +{ + return cosh(complex<_Tp>(-__x.imag(), __x.real())); +} + +// tan + +template +complex<_Tp> +tan(const complex<_Tp>& __x) +{ + complex<_Tp> __z = tanh(complex<_Tp>(-__x.imag(), __x.real())); + return complex<_Tp>(__z.imag(), -__z.real()); +} + +#if __cplusplus >= 201402L +// Literal suffix for complex number literals [complex.literals] +inline namespace literals +{ + inline namespace complex_literals + { + constexpr complex operator""il(long double __im) + { + return { 0.0l, __im }; + } + + constexpr complex operator""il(unsigned long long __im) + { + return { 0.0l, static_cast(__im) }; + } + + constexpr complex operator""i(long double __im) + { + return { 0.0, static_cast(__im) }; + } + + constexpr complex operator""i(unsigned long long __im) + { + return { 0.0, static_cast(__im) }; + } + + constexpr complex operator""if(long double __im) + { + return { 0.0f, static_cast(__im) }; + } + + constexpr complex operator""if(unsigned long long __im) + { + return { 0.0f, static_cast(__im) }; + } + } // namespace complex_literals +} // namespace literals +#endif // __cplusplus >= 201402L + +} // namespace std + +#endif // _EZCXX_COMPLEX diff --git a/src/libcxx/include/type_traits b/src/libcxx/include/type_traits index 90b1f39f7..654b79554 100644 --- a/src/libcxx/include/type_traits +++ b/src/libcxx/include/type_traits @@ -644,6 +644,29 @@ struct __nat { ~__nat() = delete; }; +// promote + +template +class __promote { + static_assert((is_arithmetic<_Args>::value && ...)); + + static float __test(float); + static double __test(char); + static double __test(int); + static double __test(unsigned); + static double __test(long); + static double __test(unsigned long); + static double __test(signed __int48); + static double __test(unsigned __int48); + static double __test(long long); + static double __test(unsigned long long); + static double __test(double); + static long double __test(long double); + +public: + using type = decltype((__test(_Args()) + ...)); +}; + //------------------------------------------------------------------------------ // make_signed make_unsigned //------------------------------------------------------------------------------ diff --git a/test/floating_point/float32_math/src/main.cpp b/test/floating_point/float32_math/src/main.cpp index 1c0395d41..da92d68e4 100644 --- a/test/floating_point/float32_math/src/main.cpp +++ b/test/floating_point/float32_math/src/main.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #define ARRAY_LENGTH(x) (sizeof(x) / sizeof(x[0])) @@ -40,7 +41,7 @@ static bool test_result(float guess, float truth) { #define TEST(guess, truth) if (test_result(guess, truth)) { return __LINE__; } static int run_test(void) { - + TEST(std::exp ( 6.3f), 544.5719101259290330593886677332f); TEST(std::exp ( -4.2f), 0.014995576820477706211984360229f); TEST(std::log ( 1.0e-6f), -13.81551055796427410410794872811f); @@ -91,6 +92,14 @@ static int run_test(void) { TEST(std::hypot(1.23f, 4.56f, 7.89f), 9.195575022803087326242198470012610630662f); + using namespace std::complex_literals; + std::complex z1 = 1.0 + 2i; + std::complex z2 = 3.0 - 4.0i; + std::complex z3 = std::conj(z1 * z2); + if (!(std::real(z3) == 11.0 && std::imag(z3) == -2.0)) { + return __LINE__; + } + /* passed all */ return 0; } diff --git a/test/floating_point/float64_math/src/main.cpp b/test/floating_point/float64_math/src/main.cpp index 8d598bbea..80776cf19 100644 --- a/test/floating_point/float64_math/src/main.cpp +++ b/test/floating_point/float64_math/src/main.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #define ARRAY_LENGTH(x) (sizeof(x) / sizeof(x[0])) @@ -40,17 +41,17 @@ static bool test_result(long double guess, long double truth) { #define TEST(guess, truth) if (test_result(guess, truth)) { return __LINE__; } static int run_test(void) { - + TEST(std::exp ( 6.3L), 544.5719101259290330593886677332L); TEST(std::exp ( -4.2L), 0.014995576820477706211984360229L); TEST(std::log ( 1.0e-6L), -13.81551055796427410410794872811L); TEST(std::log ( 3.0e+8L), 19.51929303262047516353917687440L); - + TEST(std::expm1 ( 0.2L), 0.221402758160169833921071994640L); TEST(std::expm1 (-1.0e-8L), -9.999999950000000166666666250e-9L); TEST(std::log1p ( -0.2L), -0.223143551314209755766295090310L); TEST(std::log1p ( 1.0e-8L), 9.999999950000000333333330833e-9L); - + TEST(std::sin ( 1.0L), 0.841470984807896506652502321630L); TEST(std::sin ( -0.6L), -0.564642473395035357200945445659L); TEST(std::cos ( 1.5L), 0.070737201667702910088189851434L); @@ -91,6 +92,14 @@ static int run_test(void) { TEST(std::hypot(1.23L, 4.56L, 7.89L), 9.195575022803087326242198470012610630662L); + using namespace std::complex_literals; + std::complex z1 = 1.0L + 2il; + std::complex z2 = 3.0L - 4.0il; + std::complex z3 = std::conj(z1 * z2); + if (!(std::real(z3) == 11.0L && std::imag(z3) == -2.0L)) { + return __LINE__; + } + /* passed all */ return 0; }