diff --git a/include/eve/module/complex/complex.hpp b/include/eve/module/complex/complex.hpp index 3083bff4480..cb51b44ee0e 100644 --- a/include/eve/module/complex/complex.hpp +++ b/include/eve/module/complex/complex.hpp @@ -28,8 +28,8 @@ namespace eve //! //! **Required header:** `#include ` //! - //! eve::complex is structure representing complex number and mean to be used in conjunction with - //! eve::wide. + //! eve::complex is structure representing complex number and is meant to be used in + //! conjunction with eve::wide. //! //! @tparam Type Underlying floating point type //================================================================================================ @@ -49,7 +49,10 @@ namespace eve /// Stream insertion operator friend std::ostream& operator<<(std::ostream& os, like auto const& z) { - return os << real(z) << std::showpos << imag(z) << "i" << std::noshowpos; + os << real(z); + auto i = imag(z); + if(i >= 0) os << '+' << i; else os << '-' << -i; + return os << 'i'; } //============================================================================================== @@ -120,18 +123,18 @@ namespace eve } template Z1, real_value Z2> - EVE_FORCEINLINE friend auto operator+(Z1 const& lhs, Z2 const& rhs) noexcept - requires(requires(as_wide_as_t t) { t += rhs; }) + EVE_FORCEINLINE friend auto operator+(Z1 const& x, Z2 const& y) noexcept + requires(requires(as_wide_as_t t) { t += y; }) { - as_wide_as_t that{lhs}; - return that += rhs; + as_wide_as_t that{x}; + return that += y; } template Z2> - EVE_FORCEINLINE friend auto operator+(Z1 const& lhs, Z2 const& rhs) noexcept - requires(requires(as_wide_as_t t) { t += lhs; }) + EVE_FORCEINLINE friend auto operator+(Z1 const& x, Z2 const& y) noexcept + requires(requires(as_wide_as_t t) { t += x; }) { - return rhs + lhs; + return y + x; } //============================================================================================== diff --git a/include/eve/product_type.hpp b/include/eve/product_type.hpp index 651ba25eae4..d9faeae47b2 100644 --- a/include/eve/product_type.hpp +++ b/include/eve/product_type.hpp @@ -160,16 +160,8 @@ namespace eve template Z1, like Z2> EVE_FORCEINLINE friend auto operator+(Z1 x, Z2 y) requires requires { x += x; } { - if constexpr(scalar_value && simd_value) - { - as_wide_t that{x}; - return that += y; - } - else - { - x += y; - return x; - } + if constexpr(scalar_value && simd_value) return y += x; + else return x += y; } EVE_FORCEINLINE friend auto operator-(eve::like auto x, eve::like auto y) requires requires { x -= y; } diff --git a/old/complex_hpp/complex.hpp b/old/complex_hpp/complex.hpp new file mode 100644 index 00000000000..5e511b172d4 --- /dev/null +++ b/old/complex_hpp/complex.hpp @@ -0,0 +1,825 @@ +//================================================================================================== +/** + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +**/ +//================================================================================================== +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace eve +{ + //================================================================================================ + //! @addtogroup simd_types + //! @{ + //================================================================================================ + //! @brief SIMD-compatible representation of complex numbers + //! + //! **Required header:** `#include ` + //! + //! eve::complex is structure representing complex number and mean to be used in conjunction with + //! eve::wide. + //! + //! @tparam Type Underlying floating point type + //================================================================================================ + template + struct complex : struct_support, Type, Type> + { + template Z> + EVE_FORCEINLINE friend auto tagged_dispatch( eve::tag::is_equal_ + , numeric_type const & + , Z const& z1 + , Z const& z2) noexcept + { + auto [z1r, z1i] = z1; + auto [z2r, z2i] = z2; + return numeric(is_equal)(z1r, z2r) && numeric(is_equal)(z1i, z2i); + } + + + //============================================================================================== + // Operators + //============================================================================================== + //////////////////////////////////////////////////////////////////////////////////////////////// + // add/sub + //////////////////////////////////////////////////////////////////////////////////////////////// + + EVE_FORCEINLINE friend auto& operator+= ( like auto& self + , like auto const& other + ) noexcept + { + real(self) += real(other); + imag(self) += imag(other); + return self; + } + + EVE_FORCEINLINE friend auto& operator-= ( like auto& self + , like auto const& other + ) noexcept + { + real(self) -= real(other); + imag(self) -= imag(other); + return self; + } + + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::sub_ + , like auto const & z1 + , like auto const & z2 + ) noexcept + { + return z1 -= z2; + } + + template Z, floating_real_value O> + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::sub_ + , Z const & self + , O const & other + ) noexcept + { + auto [a, b] = self; + return Z{ a-other, b}; + } + + template Z, floating_real_value O> + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::sub_ + , O const & a0 + , Z const & a1 + ) noexcept + { + auto [a, b] = a1; + return Z{ a0-a, -b}; + } + + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::add_ + , like auto const & z1 + , like auto const & z2 + ) noexcept + { + return z1 += z2; + } + + template Z, floating_real_value O> + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::add_ + , Z const & self + , O const & other + ) noexcept + { + auto [a, b] = self; + return Z{ a+other, b}; + } + + template Z, floating_real_value O> + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::add_ + , O const & a0 + , Z const & a1 + ) noexcept + { + auto [a, b] = a1; + return Z{ a+a0, b}; + } + + template Z> EVE_FORCEINLINE friend auto operator-(Z const & z) noexcept + { + return Z{-real(z), -imag(z)}; + } + + template Z> EVE_FORCEINLINE friend auto operator+(Z const &z) noexcept + { + return z; + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + // multiplies + //////////////////////////////////////////////////////////////////////////////////////////////// + + + EVE_FORCEINLINE friend auto& operator*= ( like auto & self + , like auto const & other + ) noexcept + { + auto [a, b] = self; + auto [c, d] = other; + auto rr = diff_of_prod(a, c, b, d); + auto ri = sum_of_prod(a, d, b, c); + return self = r_t(rr, ri); + } + + EVE_FORCEINLINE friend auto& operator*= ( like auto & self + , callable_i_ const & + ) noexcept + { + auto [a, b] = self; + return self = {-b, a}; + } + + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::mul_ + , like auto z1 + , like auto const & z2 + ) noexcept + { + return z1 *= z2; + } + + template < like Z> + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::mul_ + , raw_type const & + , Z const & z1 + , Z const & z2 + ) noexcept + { + auto [a, b] = z1; + auto [c, d] = z2; + return Z{a,*c-b*d, a*d+d*c}; + } + + template < like Z> + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::mul_ + , Z const & z + , callable_i_ const & + ) noexcept + { + auto [rz, iz] = z; + return Z{-iz, rz}; + } + + template < like Z> + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::mul_ + , callable_i_ const & + , Z const & z + ) noexcept + { + auto [rz, iz] = z; + return Z{-iz, rz}; + } + + template Z, floating_real_value O> + EVE_FORCEINLINE friend auto& operator *= ( Z & self + , O const & other + ) noexcept + { + auto [a, b] = self; + return self = Z{ a*other, b*other}; + } + + template Z, floating_real_value O> + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::mul_ + , Z const & a0 + , O const & a1 + ) noexcept + { + auto [a, b] = a0; + return Z{ a*a1, b*a1}; + } + + template Z, floating_real_value O> + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::mul_ + , O const & a0 + , Z const & a1 + ) noexcept + { + auto [a, b] = a1; + return Z{a*a0, b*a0}; + } + + template Z, floating_real_value O> + EVE_FORCEINLINE friend auto operator*( Z const & a0 + , O const & a1 + ) noexcept + { + return mul(a0, a1); + } + + template Z, floating_real_value O> + EVE_FORCEINLINE friend auto operator*( O const & a0 + , Z const & a1 + ) noexcept + { + return mul(a1, a0); + } + + template Z> + EVE_FORCEINLINE friend auto operator*( Z const & z + , callable_i_ const & + ) noexcept + { + auto [rz, iz] = z; + return Z(-iz, rz); + } + + template Z> + EVE_FORCEINLINE friend auto operator*( callable_i_ const & + , Z const & z + ) noexcept + { + auto [rz, iz] = z; + return Z(-iz, rz); + } + + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::mul_ + , pedantic_type const & + , like auto const & a0 + , like auto const & a1 + ) noexcept + { + auto [a, b] = a0; + auto [c, d] = a1; + using c_t = decltype(a0*a1); + c_t r{diff_of_prod(a, c, b, d), sum_of_prod(a, d, b, c)}; + auto [rr, ri] = r; + auto test = is_finite(ri) && is_finite(rr);//is_finite(r); + if (eve::all(test)) return r; + auto cur = eve::logical_andnot(is_real(a0), test); + if (eve::any(cur)) + { + r = if_else(cur, eve::mul(a1, a), r); + test = logical_or(test, cur); + if (eve::all(test)) return r; + } + cur = eve::logical_andnot(is_imag(a0), test); + if (eve::any(cur)) + { + r = if_else(cur, eve::mul_i(eve::mul(a1, b)), r); + test = logical_or(test, cur); + if (eve::all(test)) return r; + } + cur = eve::logical_andnot(is_real(a1), test); + if (eve::any(cur)) + { + r = if_else(cur, eve::mul(a0, c), r); + test = logical_or(test, cur); + if (eve::all(test)) return r; + } + cur = eve::logical_andnot(is_imag(a1), test); + if (eve::any(cur)) + { + r = if_else(cur, eve::mul_i(eve::mul(a0, d)), r); + test = logical_or(test, cur); + if (eve::all(test)) return r; + } + return r; + } + + //////////////////////////////////////////////////////////////////////////////////////////////// + // divide + //////////////////////////////////////////////////////////////////////////////////////////////// + + template Z> + EVE_FORCEINLINE friend auto operator/= ( Z & self + , like auto const& other + ) noexcept + { + auto rr = eve::abs(real(self)); + auto ii = eve::abs(imag(self)); + auto e = -if_else((rr < ii), exponent(ii), exponent(rr)); + auto oother(eve::ldexp(other, e)); + auto denom = sqr_abs(oother); + self *= conj(oother); + self /= denom; + self = ldexp(self, e); + return self; + } + + template Z, floating_real_value O> + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::div_ + , Z const & a0 + , O const & a1 + ) noexcept + { + auto [a, b] = a0; + return Z{a/a1, b/a1}; + } + + template Z, floating_real_value O> + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::div_ + , O const & a0 + , Z const & a1 + ) noexcept + { + return mul(rec(a1), a0); + } + + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::div_ + , like auto a0 + , like auto const & a1 + ) noexcept + { + + return a0 /= a1; + } + + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::div_ + , pedantic_type const & + , like auto const & a0 + , like auto const & a1 + ) noexcept + { + auto rr = eve::abs(real(a0)); + auto ii = eve::abs(imag(a1)); + auto e = -if_else((rr < ii), exponent(ii), exponent(rr)); + auto aa1 = ldexp(a1, e); + auto denom = sqr_abs(aa1); + auto num = mul(a0, conj(aa1)); + auto r = ldexp(div(num, denom), e); + if (eve::all(is_finite(r))) return r; + auto a1r = real(a1); + r = if_else(is_eqz(denom), mul(a0, copysign(inf(as(rr)), a1r)), r); + r = if_else(is_infinite(a1), mul(a0, rec(copysign(denom, a1r))), r); + return r; + } + + template Z, floating_real_value O> + EVE_FORCEINLINE friend auto operator/= ( Z & self + , O const& other + ) noexcept + { + auto [a, b] = self; + return self = Z{ a/other, b/other}; + } + + template Z> + EVE_FORCEINLINE friend auto tagged_dispatch( eve::tag::rec_, Z const& z ) noexcept + { + auto [a, b] = z; + auto n2 = sqr_abs(z); + return Z{a/n2, -b/n2}; + } + + template Z, floating_real_value O> + EVE_FORCEINLINE friend auto operator/( Z const & a0 + , O const & a1 + ) noexcept + { + return div(a0, a1); + } + + template Z, floating_real_value O> + EVE_FORCEINLINE friend auto operator/( O const & a0 + , Z const & a1 + ) noexcept + { + return div(a0, a1); + } + + //============================================================================================== + // Unary functions + //============================================================================================== + + template Z> + EVE_FORCEINLINE friend auto tagged_dispatch( eve::tag::mul_i_, Z const& z ) noexcept + { + return Z{-imag(z), real(z)}; + } + + + template Z> + EVE_FORCEINLINE friend auto tagged_dispatch( eve::tag::mul_mi_, Z const& z ) noexcept + { + return Z{imag(z), -real(z)}; + } + + template Z> + EVE_FORCEINLINE friend auto tagged_dispatch( eve::tag::sqrt_ + , pedantic_type const & + , Z const& z ) noexcept + { + //always compute the sqrt of the complex with positive imaginary part + //then conjugate if necessary + auto [rz, iz] = z; + auto negimag = is_ltz(iz); + auto x = abs(rz); + auto y = abs(iz); + auto iaz = if_else(negimag, -iz, iz); // always >= 0 or -Nan + auto gtxy = (x > y); + auto gezrz = is_gez(rz); + auto r = if_else(gtxy, y/x, x/y); + auto rr= sqrt(inc(sqr(r))); + auto sqrtx = sqrt(x); + auto w = if_else(gtxy, + sqrtx*sqrt(half(as(r))*inc(rr)), + sqrt(y)*sqrt(half(as(r))*(r+rr))); + auto is_real_z = is_real(z); + auto res = Z(if_else(is_real_z, sqrtx, w) + , if_else(is_real_z, zero, iaz*half(as(r))/w)); + res = if_else(gezrz, res, Z(imag(res), real(res))); + auto infty = inf(as(iaz)); + res = if_else(iaz == infty, Z{infty, infty}, z); + res = if_else(logical_andnot(rz == -infty, is_nan(iz)), Z{if_else(iaz == infty, iaz, zero), infty}, res); + res = if_else(is_eqz(iz) && is_nan(rz), z, res); + res = if_else(is_nan(z), Z(nan(as(iz)), nan(as(iz))), res); + res = if_else(is_eqz(iz) && is_gez(rz), Z(rz), res); + return if_else(negimag, conj(res), res); + } + + template Z> + EVE_FORCEINLINE friend auto tagged_dispatch( eve::tag::sqrt_ + , Z const& z ) noexcept + { + //always compute the sqrt of the complex with positive imaginary part + //then conjugate if necessary + auto [rz, iz] = z; + auto negimag = is_ltz(iz); + auto x = abs(rz); + auto y = abs(iz); + auto iaz = if_else(negimag, -iz, iz); // always >= 0 or -Nan + auto gtxy = (x > y); + auto gezrz = is_gez(rz); + auto r = if_else(gtxy, y/x, x/y); + auto rr= sqrt(inc(sqr(r))); + auto sqrtx = sqrt(x); + auto w = if_else(gtxy, + sqrtx*sqrt(half(as(r))*inc(rr)), + sqrt(y)*sqrt(half(as(r))*(r+rr))); + auto is_real_z = is_real(z); + auto res = Z(if_else(is_real_z, sqrtx, w) + , if_else(is_real_z, zero, iaz*half(as(r))/w)); + res = if_else(gezrz, res, Z(imag(res), real(res))); + return if_else(negimag, conj(res), res); + } + + //============================================================================================== + // trigo + //============================================================================================== + template Z> + EVE_FORCEINLINE friend auto tagged_dispatch( eve::tag::cosh_, Z const& z ) noexcept + { + auto [rz, iz] = z; + auto [s, c] = sincos(iz); + auto [sh, ch] = sinhcosh(rz); + auto r = c*ch; + auto i = s*sh; + i = if_else(is_imag(z) || is_real(z), zero, i); + return Z(r, i); + } + + template Z> + EVE_FORCEINLINE friend auto tagged_dispatch( eve::tag::cosh_, pedantic_type const &, Z const& z ) noexcept + { + auto res = cosh(z); + if (eve::none(is_not_finite(z))) return res; + auto [rz, iz] = z; + res = if_else(is_infinite(rz) && is_not_finite(iz), Z(inf(as(rz)), nan(as(rz))), res); + res = if_else(is_nan(rz) && is_infinite(iz), Z(nan(as(rz)), nan(as(rz))), res); + return res; + } + + template Z> + EVE_FORCEINLINE friend auto tagged_dispatch( eve::tag::cos_, Z const& z ) noexcept + { + return cosh(mul_i(z)); + } + + template Z> + EVE_FORCEINLINE friend auto tagged_dispatch( eve::tag::cos_, pedantic_type const &, Z const& z ) noexcept + { + return pedantic(cosh)(mul_i(z)); + } + + template Z> + EVE_FORCEINLINE friend auto tagged_dispatch( eve::tag::sinh_, Z const& z ) noexcept + { + auto [rz, iz] = z; + auto [s, c] = sincos(iz); + auto [sh, ch] = sinhcosh(rz); + return Z{c*sh, s*ch}; + } + + template Z> + EVE_FORCEINLINE friend auto tagged_dispatch( eve::tag::sinh_, pedantic_type const &, Z const& z ) noexcept + { + auto [r, i] = sinh(z); + if (none(is_not_finite(z))) return Z{r, i}; + auto [zr, zi] = z; + r = if_else(is_infinite(zr) && is_not_finite(zi), zr, r); + i = if_else(is_infinite(zr) && is_nan(zi), nan(as(zr)), i); + r = if_else(is_nan(zr), zr, r); + i = if_else(is_nan(zr), zr, i); + i = if_else(is_real(z), zero, i); + r = if_else(is_imag(z), zero, r); + return Z{ r, i}; + } + + template Z> + EVE_FORCEINLINE friend auto tagged_dispatch( eve::tag::sin_, Z const& z ) noexcept + { + return mul_mi(sinh(mul_i(z))); + } + + template Z> + EVE_FORCEINLINE friend auto tagged_dispatch( eve::tag::sin_, pedantic_type const &, Z const& z ) noexcept + { + return mul_mi(pedantic(sinh)(mul_i(z))); + } + + template Z> + EVE_FORCEINLINE friend auto tagged_dispatch( eve::tag::tan_, Z const& z ) noexcept + //tan( x + iy ) = (sin2x + i sinh(2y)/(cos2x+cosh2y). + { + auto zz = z+z; + auto [rz, iz] = zz; + auto [s, c] = sincos(rz); + auto [sh, ch] = sinhcosh(iz); + auto tmp = c+ch; + auto r = if_else(is_imag(z), zero, s/tmp); + auto i = if_else(is_real(z), zero, sh/tmp); + return Z{r, i}; + } + + template Z> + EVE_FORCEINLINE friend auto tagged_dispatch( eve::tag::tanh_, Z const& z ) noexcept + //tanh( x + iy ) = (sinh2x + i sin(2y)/(cosh2x+cos2y). + { + auto zz = z+z; + auto [rz, iz] = zz; + auto [s, c] = sincos(iz); + auto [sh, ch] = sinhcosh(rz); + auto tmp = c+ch; + auto r = if_else(is_imag(z), zero, sh/tmp); + auto i = if_else(is_real(z), zero, s/tmp); + return Z{r, i}; + } + + //============================================================================================== + // exponential + //============================================================================================== + template Z> + EVE_FORCEINLINE friend auto tagged_dispatch( eve::tag::log_, Z const& z ) noexcept + { + auto argz = eve::arg(z); + auto absz = if_else(is_nan(real(z)) && (inf(as(argz)) == imag(z)), inf(as(argz)), abs(z)); + return Z{log(absz), argz}; + } + + template Z> + EVE_FORCEINLINE friend auto tagged_dispatch( eve::tag::log_, pedantic_type const &, Z const& z ) noexcept + { + auto [zr, zi] = z; + auto argz = eve::arg(z); + auto absz = if_else(is_nan(zr) && is_infinite(zi), inf(as(argz)), abs(z)); + absz = if_else(is_infinite(zr) && is_nan(zi), inf(as(argz)), absz); + return Z{log(absz), argz}; + } + + template Z> + EVE_FORCEINLINE friend auto tagged_dispatch( eve::tag::log10_, Z const& z ) noexcept + { + auto a = if_else(is_real(z) && is_nan(imag(z)), zero, arg(z)) ; + return Z{log10(abs(z)), a*invlog_10(as(real(z)))}; + } + + template Z> + EVE_FORCEINLINE friend auto tagged_dispatch( eve::tag::log10_, pedantic_type const &, Z const& z ) noexcept + { + auto [zr, zi] = z; + auto argz = eve::arg(z); + auto absz = if_else(is_nan(zr) && is_infinite(zi), inf(as(argz)), abs(z)); + absz = if_else(is_infinite(zr) && is_nan(zi), inf(as(argz)), absz); + return Z{log10(absz), argz*invlog_10(as(real(z)))}; + } + + template Z> + EVE_FORCEINLINE friend auto tagged_dispatch( eve::tag::exp_, Z const& z ) noexcept + { + auto [rz, iz] = z; + auto [s, c] = sincos(iz); + auto rho = exp(rz); + return if_else(is_real(z) || rz == minf(as(rz)), + Z{rho}, + Z{rho*c, rho*s}); + } + + template Z> + EVE_FORCEINLINE friend auto tagged_dispatch( eve::tag::exp_i_, Z const& z ) noexcept + { + return exp(mul_i(z)); + } + + template Z> + EVE_FORCEINLINE friend auto tagged_dispatch( eve::tag::exp_ipi_, Z const& z ) noexcept + { + auto [rz, iz] = z; + auto [s, c] = sinpicospi(rz); + auto rho = exp(-pi(as(iz))*iz); + return if_else(is_imag(z) || iz == inf(as(rz)), + Z{rho}, + Z{rho*c, rho*s}); + } + + + //============================================================================================== + // Binary functions + //============================================================================================== + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::ulpdist_ + , like auto const& z1 + , like auto const& z2 + ) noexcept + { + return eve::max( eve::ulpdist(real(z1), real(z2)) + , eve::ulpdist(imag(z1), imag(z2))); + } + + template Z> + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::ldexp_ + , Z const& z1 + , integral_value auto n + ) noexcept + { + return Z{ ldexp(real(z1), n), ldexp(imag(z1), n)}; + } + + template Z> + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::pow_ + , Z const & a + , Z const & b + ) noexcept + { + auto [u, v] = b; + auto labsa = log_abs(a); + auto arga = arg(a); + auto rz = exp(diff_of_prod(u, labsa, v, arga)); + auto iz = exp_i(sum_of_prod(u, arga, v, labsa)); + return if_else(is_eqz(a)&&is_eqz(b), one, mul(iz, rz)); + } + + template Z, floating_real_value T> + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::pow_ + , Z const & a0 + , T const & a1 + ) noexcept + { + auto t = arg(a0); + auto a = abs(a0); + return if_else(is_eqz(a)&&is_eqz(a1), one, eve::pow(a, a1)*exp_i(t*a1)); + } + + template Z, floating_real_value T> + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::pow_ + , T const & a0 + , Z const & a1 + ) noexcept + { + return if_else(is_eqz(a0)&&is_eqz(a1), one, exp(a1*cmplx(log)(a0))); + } + + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::dist_ + , like auto const & z1 + , like auto const & z2 + ) noexcept + { + return abs(z1-z2); + } + + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::acosh_ + , like auto const & z + ) noexcept + { + // acosh(a0) = +/-i acos(a0) + // Choosing the sign of multiplier to give nt2::real(acosh(a0)) >= 0 + // we have compatibility with C99. + auto res = eve::acos(z); + return if_else(is_lez(imag(res)), mul_i(res), mul_mi(res)); + } + + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::acos_ + , like auto const & z + ) noexcept + { + return eve::detail::internal_acos(z); + } + + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::asinh_ + , like auto const & z + ) noexcept + { + // We use asinh(z) = i asin(-i z); + // Note that C99 defines this the other way around (which is + // to say asin is specified in terms of asinh), this is consistent + // with C99 though: + return mul_i(asin(mul_mi(z))); + } + + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::asin_ + , like auto const & z + ) noexcept + { + return eve::detail::internal_asin(z); + } + + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::atan_ + , like auto const & z + ) noexcept + { + // C99 definition here; atan(z) = -i atanh(iz): + return mul_mi(eve::atanh(mul_i(z))); + } + + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::atanh_ + , like auto const & z + ) noexcept + { + return eve::detail::internal_atanh(z); + } + + }; + +/* + template < like Z> + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::mul_ + , raw_type const & + , Z const & z1 + , Z const & z2 + ) noexcept + { + auto [a, b] = z1; + auto [c, d] = z2; + return Z{a*c-b*d, a*d+d*c}; + } + + template < like Z> + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::mul_ + , Z const & z + , callable_i_ const & + ) noexcept + { + auto [rz, iz] = z; + return Z{-iz, rz}; + } + + template < like Z> + EVE_FORCEINLINE friend auto tagged_dispatch ( eve::tag::mul_ + , callable_i_ const & + , Z const & z + ) noexcept + { + auto [rz, iz] = z; + return Z{-iz, rz}; + } +*/ +/* + EVE_FORCEINLINE auto complex_unary_dispatch(eve::tag::sqr_abs_, auto const& z) noexcept + { + auto [zr, zi] = z; + return sum_of_prod(zr, zr, zi, zi); + } + + template + EVE_FORCEINLINE auto complex_unary_dispatch ( eve::tag::sqr_ + , eve::raw_type const & + , Z const& z + ) noexcept + { + auto [zr, zi] = z; + return Z{eve::sqr(zr)-eve::sqr(zi), 2*zr*zi}; + } + + +*/ diff --git a/old/complex_hpp/regular/acos.hpp b/old/complex_hpp/regular/acos.hpp new file mode 100644 index 00000000000..ece3455cb42 --- /dev/null +++ b/old/complex_hpp/regular/acos.hpp @@ -0,0 +1,171 @@ +//================================================================================================== +/* + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +*/ +//================================================================================================== +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace eve +{ + + namespace detail + { + template EVE_FORCEINLINE V acos_(EVE_SUPPORTS(cpu_), cmplx_type const &, V const & v) noexcept + { + using r_t = eve::as_complex_t; + return if_else(is_lez(v, V(1)), r_t(acos(v)), r_t(0, acosh(v))); + } + + template EVE_FORCEINLINE V internal_acos(V const & a0) noexcept + { + // here V is like + // + // This implementation is a simd transcription and adaptation of the boost_math code + // which itself is a transcription of the pseudo-code in: + // + // "Implementing the complex Arcsine and Arccosine Functions using Exception Handling." + // T E Hull, Thomas F Fairgrieve and Ping Tak Peter Tang. + // ACM Transactions on Mathematical Software, Vol 23, No 3, Sept 1997. + // + auto [a0r, a0i] = a0; + using rtype = decltype(a0r); + const rtype a_crossover(1.5); + const rtype b_crossover(0.6417); + auto ltzra0 = is_ltz(a0r); + auto gtzia0 = is_gtz(a0i); + // + // Begin by insuring a0r >= 0 and imag(a0) >= 0 : + // + rtype x = eve::abs(a0r); + rtype y = eve::abs(a0i); + rtype proper_real = eve::acos(x); + auto lexone = (x <= one(as(x))); + auto is_proper_real = logical_and(is_real(a0), lexone); + + auto s_min = eve::sqrtsmallestposval(as(x))*4; + auto s_max = eve::sqrtvalmax(as(x))/8; + rtype xp1 = eve::inc(x); + rtype xm1 = eve::dec(x); + auto not_in_safe_zone = (((x > s_max) || (x < s_min)) || ((y > s_max) || (y < s_min))); + //compute for safe zone + rtype r, i; + rtype yy = eve::sqr(y); + rtype tr = eve::sqrt(sqr(xp1) + yy); //hypot for pedantic ? + rtype ts = eve::sqrt(sqr(xm1) + yy); //hypot for pedantic ? + rtype a = eve::average(tr, ts); + rtype b = x/a; + //compute r for b > b_crossover + rtype apx = a + x; + r = if_else(lexone, + eve::atan(eve::sqrt(half(as(x))*apx*(yy/(tr+xp1)+(ts-xm1)))/x), + eve::atan((y*eve::sqrt(half(as(x))*(apx/(tr+xp1)+apx/(ts+xm1))))/x) + ); + // r is computed + r = if_else((b <= b_crossover), eve::acos(b), r); + //compute am1 temporary for i for a <= a_crossover + rtype tmp = yy/(tr+xp1); + rtype am1 = if_else(lexone, + eve::average(tmp, yy/(ts-xm1)), + eve::average(tmp, (ts+xm1))); + i = if_else((a <= a_crossover), + eve::log1p(am1 + eve::sqrt(am1*(eve::inc(a)))), + eve::log(a + eve::sqrt(eve::dec(eve::sqr(a)))) + ); + // i is computed + //compute for exception zone + if (eve::any(not_in_safe_zone)) + { + auto zone1 = (y <= eve::eps(as(x))*eve::abs(xm1)); + if (eve::any(logical_and(zone1, not_in_safe_zone))) + { + rtype rr = if_else(lexone, proper_real, zero); + rtype ii = if_else(lexone, y/eve::sqrt(-xp1*xm1), + if_else((valmax(as(x))/xp1 > xm1), + eve::log1p(xm1 + eve::sqrt(xp1*xm1)), + log_2(as(x)) + eve::log(x) + ) + ); + r = if_else(zone1, rr, r); + i = if_else(zone1, ii, i); + } + auto zone2 = (y <= s_min); + auto not_treated = logical_notand(zone1, not_in_safe_zone); + if (eve::any(logical_and(zone2, not_treated))) + { + rtype sqrty = eve::sqrt(y); + r = if_else(zone2, sqrty, r); + i = if_else(zone2, sqrty, i); + } + auto zone3 = (dec(eps(as(x))*y) >= x); + not_treated = logical_notand(zone2, not_treated); + if (eve::any(logical_and(zone3, not_treated))) + { + r = if_else(zone3, pio_2(as(x)), r); + i = if_else(zone3, log_2(as(x)) + eve::log(y), i); + } + auto zone4 = (x > one(as(x))); + not_treated = logical_notand(zone3, not_treated); + if (eve::any(logical_and(zone4, not_treated))) + { + r = if_else(zone4, eve::atan(y/x), r); + i = if_else(zone4, log_2(as(x)) + eve::log(y) + half(as(x))*eve::log1p(sqr(x/y)), i); + } + not_treated = logical_notand(zone4, not_treated); + if (eve::any(not_treated)) + { + rtype aa = eve::sqrt(eve::inc(sqr(y))); + r = if_else(not_treated, pio_2(as(x)), r); + i = if_else(not_treated, half(as(x))*eve::log1p(2*y*(y+aa)), i); + } + } + if (eve::any(eve::is_not_finite(a0))) // this is perhaps for pedantic specialization ? + { + auto nanx = eve::is_nan(x); + auto nany = eve::is_nan(y); + auto infx = (x == inf(as(x))) ; + auto infy = (y == inf(as(x))) ; + if (eve::any(infx)) + { + r = eve::if_else(infx, zero, r); + i = eve::if_else(infx, inf(as(x)), i); + r = eve::if_else(logical_and(infx, infy), pio_4(as(x)), r); + i = eve::if_else(logical_and(infx, infy), inf(as(x)), i); + + r = if_else(logical_and(infx, nany), y, r); + i = if_else(logical_and(infx, nany), minf(as(x)), i); + } + if (eve::any(nanx)) + { + r = if_else(nanx, x, r); + i = if_else(nanx, x, i); + i = if_else(logical_and(nanx, infy), y, i); + } + auto test = logical_notand(logical_or(infx, nanx), infy); + if (eve::any(test)) + { + r = if_else(logical_and(infy, test), pio_2(as(x)), r); + i = if_else(logical_and(infy, test), y, i); + } + test = logical_notand(logical_or(infx, nanx), nany); + r = if_else(test,if_else(eve::is_imag(a0), pio_2(as(x)), y), r); + i = if_else(test,y,i); + } + // use proper real results + r = if_else(is_proper_real, proper_real, r); + i = if_else(is_proper_real, zero, i); + // restore signs + r = if_else(ltzra0, pi(as(x))-r, r); + i = if_else(gtzia0, -i, i); + return V{r, i}; + } + } +} diff --git a/old/complex_hpp/regular/acosh.hpp b/old/complex_hpp/regular/acosh.hpp new file mode 100644 index 00000000000..3f776df8bc6 --- /dev/null +++ b/old/complex_hpp/regular/acosh.hpp @@ -0,0 +1,33 @@ +//================================================================================================== +/* + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +*/ +//================================================================================================== +#pragma once + +#include + +namespace eve +{ + + namespace detail + { + template EVE_FORCEINLINE V acosh_(EVE_SUPPORTS(cpu_) + , cmplx_type const & + , V const & v) noexcept + { + using r_t = eve::as_complex_t; + return if_else(eve::abs(v) <= 1, r_t(0, acos(v)), r_t(acosh(v))); + } + template EVE_FORCEINLINE V acosh_(EVE_SUPPORTS(cpu_), V const & a0) noexcept + { + // acosh(a0) = +/-i acos(a0) + // Choosing the sign of multiplier to give nt2::real(acosh(a0)) >= 0 + // we have compatibility with C99. + auto res = eve::acos(a0); + return if_else(is_lez(imag(res)), mul_i(res), mul_mi(res)); + } +} +} diff --git a/old/complex_hpp/regular/asin.hpp b/old/complex_hpp/regular/asin.hpp new file mode 100644 index 00000000000..30068c53c77 --- /dev/null +++ b/old/complex_hpp/regular/asin.hpp @@ -0,0 +1,176 @@ +//================================================================================================== +/* + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +*/ +//================================================================================================== +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace eve +{ + + namespace detail + { + template EVE_FORCEINLINE V asin_(EVE_SUPPORTS(cpu_) + , cmplx_type const & + , V const & v) noexcept + { + using r_t = eve::as_complex_t; + return if_else(is_lez(v, V(1)), r_t(asin(v)), r_t(0, asinh(v))); + } + + template EVE_FORCEINLINE V internal_asin(V const & a0) noexcept + { + // here V is like + // + // + // This implementation is a simd transcription and adaptation of the boost_math code + // which itself is a transcription of the pseudo-code in: + // + // "Implementing the complex Arcsine and Arccosine Functions using Exception Handling." + // T E Hull, Thomas F Fairgrieve and Ping Tak Peter Tang. + // ACM Transactions on Mathematical Software, Vol 23, No 3, Sept 1997. + // + auto [a0r, a0i] = a0; + using rtype = decltype(a0r); + const rtype a_crossover(1.5); + const rtype b_crossover(0.6417); + auto ltzra0 = is_ltz(a0r); + auto ltzia0 = is_ltz(a0i); + + // + // Begin by insuring real(a0) >= 0 and imag(a0) >= 0 : + // + + rtype x = eve::abs(a0r); + rtype y = eve::abs(a0i); + rtype proper_real = eve::asin(x); + auto lexone = (x <= one(as(a0r))); + auto is_proper_real = is_real(a0) && lexone; + + auto s_min = eve::sqrtsmallestposval(as(x))*4; + auto s_max = eve::sqrtvalmax(as(x))/8; + rtype xp1 = eve::inc(x); + rtype xm1 = eve::dec(x); + auto not_in_safe_zone = (((x > s_max) || (x < s_min)) || ((y > s_max) || (y < s_min))); + //compute for safe zone + rtype r, i; + rtype yy = eve::sqr(y); + rtype tr = eve::sqrt(eve::sqr(xp1) + yy);//hypot for pedantic ? + rtype ts = eve::sqrt(eve::sqr(xm1) + yy);//hypot for pedantic ? + rtype a = eve::average(tr, ts); + rtype b = x/a; + //compute r for b > b_crossover + rtype apx = a + x; + r = if_else(lexone, + eve::atan(x/eve::sqrt(half(as(a0r))*apx*(yy/(tr+xp1)+(ts-xm1)))), + eve::atan(x/(y*eve::sqrt(half(as(a0r))*(apx/(tr+xp1)+apx/(ts+xm1))))) + ); + // r is computed + r = if_else((b <= b_crossover), r, eve::asin(b)); + //compute am 1 temporary for i for a <= a_crossover + rtype tmp = yy/(tr+xp1); + rtype am1 = if_else(lexone, + eve::average(tmp, yy/(ts-xm1)), + eve::average(tmp, (ts+xm1))); + i = if_else((a <= a_crossover), + eve::log1p(am1 + eve::sqrt(am1*(eve::inc(a)))), + eve::log(a + eve::sqrt(eve::dec(eve::sqr(a)))) + ); + // i is computed + //compute for exception zone + if (eve::any(not_in_safe_zone)) + { + auto zone1 = (y <= eve::eps(as(a0r))*eve::abs(xm1)); + if (eve::any(logical_and(zone1, not_in_safe_zone))) + { + rtype rr = if_else(lexone, eve::asin(x), pio_2(as(a0r))); + rtype ii = if_else(lexone, y/eve::sqrt(xp1*xm1), + if_else((valmax(as(a0r))/xp1 > xm1), + eve::log1p(xm1 + eve::sqrt(xp1*xm1)), + log_2(as(a0r)) + eve::log(x) + ) + ); + r = if_else(zone1, rr, r); + i = if_else(zone1, ii, i); + } + auto zone2 = (y <= s_min); + auto not_treated = logical_notand(zone1, not_in_safe_zone); + if (eve::any(logical_and(zone2, not_treated))) + { + r = if_else(zone2, pio_2(as(a0r)) - eve::sqrt(y), r); + i = if_else(zone2, eve::sqrt(y), i); + } + auto zone3 = (eve::dec(eps(as(a0r))*y) >= x); + not_treated = logical_notand(zone2, not_treated); + if (eve::any(logical_and(zone3, not_treated))) + { + r = if_else(zone3, x/y, r); + i = if_else(zone3, log_2(as(a0r)) + eve::log(y), i); + } + auto zone4 = (x > one(as(a0r))); + not_treated = logical_notand(zone3, not_treated); + if (eve::any(logical_and(zone4, not_treated))) + { + r = if_else(zone4, eve::atan(x/y), r); + i = if_else(zone4, log_2(as(a0r)) + eve::log(y) + half(as(a0r))*eve::log1p(eve::sqr(x/y)), i); + } + not_treated = logical_notand(zone4, not_treated); + if (eve::any(not_treated)) + { + rtype aa = eve::sqrt(eve::inc(eve::sqr(y))); + r = if_else(not_treated, x/aa, r); + i = if_else(not_treated, half(as(a0r))*eve::log1p(2*y*(y+aa)), i); + } + } + if (eve::any(is_not_finite(a0))) + { + auto nanx = is_nan(x); + auto nany = is_nan(y); + auto infx = (x == inf(as(a0r))) ; + auto infy = (y == inf(as(a0r))) ; + if (eve::any(nanx)) + { + r = if_else(nanx, x, r); + r = if_else(nanx && infy, x, r); + i = if_else(nanx, x, i); + i = if_else(nanx && infy, y, i); + } + if (eve::any(nany)) + { + auto isimag = is_imag(a0); + r = if_else(isimag && nany, zero, r); + r = if_else(logical_and(nany, infx),y, r); + i = if_else(isimag && nany, allbits, i); + i = if_else(nany && infx, x, i); + } + auto test = logical_notand(logical_or(nanx, nany), infx); + if (eve::any(test)) + { + r = if_else(infx && test, + if_else(infy, eve::pio_4(as(a0r)), eve::pio_2(as(a0r))), + r); + } + test = logical_notand(is_nan(x) || is_nan(y), + logical_andnot(infy, infx)); + r = if_else(test,zero,r); + } + // use proper real results + + r = if_else(is_proper_real, proper_real, r); + i = if_else(is_proper_real, zero, i); + // restore signs + r = if_else(ltzra0, -r, r); + i = if_else(ltzia0, -i, i); + return V{r, i}; + } + } +} diff --git a/old/complex_hpp/regular/asinh.hpp b/old/complex_hpp/regular/asinh.hpp new file mode 100644 index 00000000000..82a8715cff2 --- /dev/null +++ b/old/complex_hpp/regular/asinh.hpp @@ -0,0 +1,25 @@ +//================================================================================================== +/* + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +*/ +//================================================================================================== +#pragma once + +#include + +namespace eve +{ + + namespace detail + { + template EVE_FORCEINLINE V asinh_(EVE_SUPPORTS(cpu_) + , cmplx_type const & + , V const & v) noexcept + { + using r_t = eve::as_complex_t; + return if_else(eve::abs(v) <= 1, r_t(0, asin(v)), r_t(asinh(v))); + } + } +} diff --git a/old/complex_hpp/regular/atan.hpp b/old/complex_hpp/regular/atan.hpp new file mode 100644 index 00000000000..84929387594 --- /dev/null +++ b/old/complex_hpp/regular/atan.hpp @@ -0,0 +1,24 @@ +//================================================================================================== +/* + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +*/ +//================================================================================================== +#pragma once + +#include + +namespace eve +{ + namespace detail + { + template EVE_FORCEINLINE V atan_(EVE_SUPPORTS(cpu_) + , cmplx_type const & + , V const & v) noexcept + { + using r_t = eve::as_complex_t; + return if_else(eve::abs(v) <= 1, r_t(0, atan(v)), r_t(atanh(v))); + } + } +} diff --git a/old/complex_hpp/regular/atanh.hpp b/old/complex_hpp/regular/atanh.hpp new file mode 100644 index 00000000000..1c100eab8ff --- /dev/null +++ b/old/complex_hpp/regular/atanh.hpp @@ -0,0 +1,176 @@ +//================================================================================================== +/* + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +*/ +//================================================================================================== +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace eve +{ + namespace detail + { + template EVE_FORCEINLINE V atanh_( EVE_SUPPORTS(cpu_) + , cmplx_type const & + , V const & v) noexcept + { + using r_t = eve::as_complex_t; + return if_else(is_lez(v, V(1)), r_t(asin(v)), r_t(0, asinh(v))); + } + + template EVE_FORCEINLINE V internal_atanh(V const & a0) noexcept + { + // here V is like + // + // + // This implementation is a simd (i.e. no branch) transcription and adaptation of the + // boost_math code which itself is a transcription of the pseudo-code in: + // + // Eric W. Weisstein. "Inverse Hyperbolic Tangent." + // From MathWorld--A Wolfram Web Resource. + // http://mathworld.wolfram.com/InverseHyperbolicTangent.html + // + // Also: The Wolfram Functions Site, + // http://functions.wolfram.com/ElementaryFunctions/ArcTanh/ + // + // Also "Abramowitz and Stegun. Handbook of Mathematical Functions." + // at : http://jove.prohosting.com/~skripty/toc.htm + // + auto [a0r, a0i] = a0; + using rtype = decltype(a0r); + const rtype alpha_crossover(0.3); + auto ltzra0 = is_ltz(a0r); + auto ltzia0 = is_ltz(a0i); + auto s_min = eve::sqrtsmallestposval(as(a0r))*2; + auto s_max = eve::sqrtvalmax(as(a0r))/2; + rtype const two = rtype(2); +// rtype one = One(as(a0r)); + rtype inf = eve::inf(as(a0r)); + rtype x = eve::abs(a0r); + rtype y = eve::abs(a0i); + rtype r = zero(as(a0r)); + rtype i = zero(as(a0r)); + auto gtxmax = (x > s_max); + auto ltxmin = (x < s_min); + auto gtymax = (y > s_max); + auto ltymin = (y < s_min); + rtype xx = eve::sqr(x); + rtype yy = eve::sqr(y); + rtype sqrabs = xx + yy; + + auto not_in_safe_zone = ((gtxmax || ltxmin) || (gtymax || ltymin)); + if(eve::any(not_in_safe_zone)) + { + //treat underflow or overflow + // one or both of x and y are small, calculate divisor carefully: + rtype div = one(as(a0r)); + div += eve::if_else(ltxmin, xx, zero); + div += eve::if_else(ltxmin, yy, zero); + + rtype alpha = x/div; + alpha += alpha; + + auto test = gtymax; + // big y, medium x, divide through by y: + rtype tmp_alpha = (two*x/y) / (y + xx/y); + // small x and y, whatever alpha is, it's too small to calculate: + tmp_alpha = eve::if_else(x > one(as(a0r)), tmp_alpha, zero); + alpha = eve::if_else(test && (x > one(as(a0r))), tmp_alpha, alpha); + + test = eve::logical_andnot(gtxmax, test); + + // big x small y, as above but neglect y^2/x: + tmp_alpha = two/x; + // big x: divide through by x: + tmp_alpha = eve::if_else((y > one(as(a0r))), two / (x + y*y/x), tmp_alpha); + // big x and y: divide alpha through by x*y: + tmp_alpha = eve::if_else(gtymax, (two/y) / (x/y + y/x), tmp_alpha); + // x or y are infinite: the result is 0 + tmp_alpha = eve::if_else((y == inf) || (x == inf), zero, tmp_alpha); + + alpha = eve::if_else(test, tmp_alpha, alpha); + r = eve::if_else((alpha < alpha_crossover), + eve::log1p(alpha) - eve::log1p(-alpha), + eve::log(inc(two*x + xx)) - eve::log(sqr(dec(x))) + ); + test = (x == one(as(a0r))) && ltymin; + r = eve::if_else(test, -(two*(eve::log(y) - eve::log_2(as(a0r)))), r); + r *= rtype(0.25); + //compute the imag part + // y^2 is negligible: + i = eve::atan2(two*y, eve::oneminus(xx)); + i = if_else(gtymax || gtxmax, pi(as(a0r)), i); + rtype tmp_i = eve::if_else(ltymin, atan2(two*y, one(as(a0r))), + eve::atan2(two*y, eve::oneminus(yy))); + i = if_else(ltxmin, tmp_i, i); + } + auto test0 = (inf == x) && (inf == y); + if(eve::any(test0)) + { + //inf x, inf y + r = eve::if_else(test0, zero, r); + i = eve::if_else(test0, pi(as(a0r)), r); + } + auto test = eve::is_nan(a0); + + if(eve::any(test)) + { + //nan x, inf y + r = eve::if_else(eve::is_nan(x) && (y == inf), zero, r); + i = eve::if_else(eve::is_nan(x) && (y == inf), pi(as(a0r)), r); + + r = eve::if_else(is_nan(y) && (x == inf), zero, r); + i = eve::if_else(is_nan(y) && (x == inf), y, i); + + r = eve::if_else(is_nan(y) && eve::is_eqz(x), zero, r); + i = eve::if_else(is_nan(y) && is_eqz(x), allbits, i); + } + //compute for safe zone + // the real part is given by: + // + // eve::real(atanh(z)) == log((1 + x^2 + y^2 + 2x) / (1 + x^2 + y^2 - 2x)) + // + // however, when x is either large (x > 1/e) or very small + // (x < e) then this effectively simplifies + // to log(1), leading to wildly inaccurate results. + // by dividing the above (top and bottom) by (1 + x^2 + y^2) we get: + // + // eve::real(atanh(z)) == log((1 + (2x / (1 + x^2 + y^2))) / (1 - (-2x / (1 + x^2 + y^2)))) + // + // which is much more sensitive to the value of x, when x is not near 1 + // (remember we can compute log(1+x) for small x very accurately). + // + // the cross-over from one method to the other has to be determined + // experimentally, the value used below appears correct to within a + // factor of 2 (and there are larger errors from other parts + // of the input domain anyway). + // + rtype alpha = x*two / (eve::inc(sqrabs)); + rtype sqrxm1 = eve::sqr(eve::dec(x)); + rtype tmp_r = eve::if_else((alpha < alpha_crossover), + eve::log1p(alpha) - log1p(-alpha), + eve::log1p(x+x + sqrabs) - eve::log(sqrxm1 + yy) + )*rtype(0.25); + r = eve::if_else(not_in_safe_zone, r, tmp_r); + + // compute the imag part + i = eve::if_else(not_in_safe_zone, + i, + eve::atan2(y+y, (oneminus(sqrabs))) + )*half(as(a0r)); + + r = eve::if_else( ltzra0,-r, r); + i = eve::if_else(is_infinite(y), pio_2(as(a0r)), i); + i = eve::if_else( ltzia0,-i, i); + return V{r, i}; + } + } +} diff --git a/old/complex_hpp/regular/cmplx.hpp b/old/complex_hpp/regular/cmplx.hpp new file mode 100644 index 00000000000..116efb8b0cf --- /dev/null +++ b/old/complex_hpp/regular/cmplx.hpp @@ -0,0 +1,48 @@ +//================================================================================================== +/** + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +**/ +//================================================================================================== +#pragma once + +#include + +namespace eve +{ + //================================================================================================ + //================================================================================================ + // Function decorators mark-up used in function overloads + struct cmplx_ + { + template static constexpr auto combine( D const& ) noexcept =delete; + }; + + using cmplx_type = decorated; + //================================================================================================ + //! @addtogroup core + //! @{ + //! @var cmplx + //! + //! @brief Higher-order @callable imbuing complex computation return onto other @callable{s} + //! using floating real entries. + //! + //! #### Synopsis + //! + //! #### Members Functions + //! + //! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp} + //! auto operator()(eve::callable auto const& f ) const noexcept; + //! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + //! @param f + //! An instance of eve::callable + //! + //! @return + //! A @callable performing the same kind of operation but while insuring to return + //! cmplx values. + //! + //! @} + //================================================================================================ + inline constexpr cmplx_type const cmplx = {}; +} diff --git a/old/complex_hpp/regular/exp_i.hpp b/old/complex_hpp/regular/exp_i.hpp new file mode 100644 index 00000000000..6ea5727b2e9 --- /dev/null +++ b/old/complex_hpp/regular/exp_i.hpp @@ -0,0 +1,66 @@ +//================================================================================================== +/* + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +*/ +//================================================================================================== +#pragma once + +#include +#include + +namespace eve +{ + //================================================================================================ + //! @addtogroup complex + //! @{ + //! @var exp_i + //! + //! @brief Callable object computing exp_i(x). + //! + //! **Required header:** `#include ` + //! + //! #### Members Functions + //! + //! | Member | Effect | + //! |:-------------|:-----------------------------------------------------------| + //! | `operator()` | the computation of exp_i(x) | + //! + //! --- + //! + //! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp} + //! auto operator()(value auto x) const noexcept; + //! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + //! + //! **Parameters** + //! + //!`x`: [value](@ref eve::value). + //! + //! **Return value** + //! `complex < decltype(x)> equal to exp(i*x) (i*i = -1). + //! + //! #### Example + //! + //! @godbolt{doc/complex/exp_i.cpp} + //! + //! @} + //================================================================================================ + + namespace tag { struct exp_i_; } + template<> struct supports_conditional : std::false_type {}; + + EVE_MAKE_CALLABLE(exp_i_, exp_i); + + namespace detail + { + template + EVE_FORCEINLINE auto exp_i_( EVE_SUPPORTS(cpu_) + , V const & v) noexcept + { + using c_t = eve::as_complex_t; + auto [s, c] = sincos(v); + return c_t{c, s}; + } + } +} diff --git a/old/complex_hpp/regular/exp_ipi.hpp b/old/complex_hpp/regular/exp_ipi.hpp new file mode 100644 index 00000000000..1ce474d3cd0 --- /dev/null +++ b/old/complex_hpp/regular/exp_ipi.hpp @@ -0,0 +1,65 @@ +//================================================================================================== +/* + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +*/ +//================================================================================================== +#pragma once + +#include +#include + +namespace eve +{ + //================================================================================================ + //! @addtogroup complex + //! @{ + //! @var exp_ipi + //! + //! @brief Callable object computing exp_ipi(x). + //! + //! **Required header:** `#include ` + //! + //! #### Members Functions + //! + //! | Member | Effect | + //! |:-------------|:-----------------------------------------------------------| + //! | `operator()` | the computation of exp_ipi(x) | + //! + //! --- + //! + //! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp} + //! auto operator()(value auto x) const noexcept; + //! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + //! + //! **Parameters** + //! + //!`x`: [value](@ref eve::value). + //! + //! **Return value** + //! `complex < decltype(x)> equal to exp(i*pi*x) (i*i = -1). + //! + //! #### Example + //! + //! @godbolt{doc/complex/exp_ipi.cpp} + //! + //! @} + //================================================================================================ + + namespace tag { struct exp_ipi_; } + template<> struct supports_conditional : std::false_type {}; + + EVE_MAKE_CALLABLE(exp_ipi_, exp_ipi); + + namespace detail + { + template EVE_FORCEINLINE + auto exp_ipi_(EVE_SUPPORTS(cpu_), V const & v) noexcept + { + using c_t = eve::as_complex_t; + auto [s, c] = sinpicospi(v); + return c_t{c, s}; + } + } +} diff --git a/old/complex_hpp/regular/log.hpp b/old/complex_hpp/regular/log.hpp new file mode 100644 index 00000000000..e8d922f73c4 --- /dev/null +++ b/old/complex_hpp/regular/log.hpp @@ -0,0 +1,28 @@ +//================================================================================================== +/* + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +*/ +//================================================================================================== +#pragma once + +#include +#include + +namespace eve +{ + template struct complex; + + namespace detail + { + template + EVE_FORCEINLINE auto log_(EVE_SUPPORTS(cpu_), + cmplx_type const &, + V const & v) noexcept + { + using c_t = as_complex_t; + return c_t{log_abs(v), arg(v)}; + } + } +} diff --git a/old/complex_hpp/regular/log10.hpp b/old/complex_hpp/regular/log10.hpp new file mode 100644 index 00000000000..f99e1d003d5 --- /dev/null +++ b/old/complex_hpp/regular/log10.hpp @@ -0,0 +1,28 @@ +//================================================================================================== +/* + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +*/ +//================================================================================================== +#pragma once + +#include +#include + +namespace eve +{ + template struct complex; + + namespace detail + { + template + EVE_FORCEINLINE auto log10_(EVE_SUPPORTS(cpu_), + cmplx_type const &, + V v) noexcept + { + using c_t = as_complex_t; + return c_t{log10(abs(v)), arg(v)/log_10(as(v))}; + } + } +} diff --git a/old/complex_hpp/regular/mul.hpp b/old/complex_hpp/regular/mul.hpp new file mode 100644 index 00000000000..6a878a79fc1 --- /dev/null +++ b/old/complex_hpp/regular/mul.hpp @@ -0,0 +1,27 @@ +//================================================================================================== +/* + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +*/ +//================================================================================================== +#pragma once + +#include +#include + +// namespace eve +// { +// template struct complex; + +// namespace detail +// { +// template +// EVE_FORCEINLINE auto add_(EVE_SUPPORTS(cpu_) +// ,V v +// , like auto const & a) noexcept +// { +// return add(a, v); +// } +// } +// } diff --git a/old/complex_hpp/regular/mul_i.hpp b/old/complex_hpp/regular/mul_i.hpp new file mode 100644 index 00000000000..5e51a6ff4e3 --- /dev/null +++ b/old/complex_hpp/regular/mul_i.hpp @@ -0,0 +1,75 @@ +//================================================================================================== +/* + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +*/ +//================================================================================================== +#pragma once + +#include + +namespace eve +{ + //================================================================================================ + //! @addtogroup complex + //! @{ + //! @var mul_i + //! + //! @brief Callable object computing mul_i part of values. + //! + //! **Required header:** `#include ` + //! + //! #### Members Functions + //! + //! | Member | Effect | + //! |:-------------|:-----------------------------------------------------------| + //! | `operator()` | the computation of mul_i part | + //! + //! --- + //! + //! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp} + //! auto operator()(value auto x) const noexcept; + //! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + //! + //! **Parameters** + //! + //!`x`: [value](@ref eve::value). + //! + //! **Return value** + //! `complex < decltype(x)> equal to x multiplied by i (i*i = -1). + //! + //! #### Example + //! + //! @godbolt{doc/complex/mul_i.cpp} + //! + //! @} + //================================================================================================ + + namespace tag { struct mul_i_; } + template<> struct supports_conditional : std::false_type {}; + + EVE_MAKE_CALLABLE(mul_i_, mul_i); + + namespace detail + { + template EVE_FORCEINLINE + auto mul_i_(EVE_SUPPORTS(cpu_), V const & v) noexcept + { + using c_t = eve::as_complex_t; + return c_t{zero(as(v)), v}; + } + + template EVE_FORCEINLINE + auto operator*(V const & v, callable_i_) noexcept + { + return mul_i(v); + } + + template EVE_FORCEINLINE + auto operator*(callable_i_, V const & v) noexcept + { + return mul_i(v); + } + } +} diff --git a/old/complex_hpp/regular/mul_mi.hpp b/old/complex_hpp/regular/mul_mi.hpp new file mode 100644 index 00000000000..58b981ebe3f --- /dev/null +++ b/old/complex_hpp/regular/mul_mi.hpp @@ -0,0 +1,64 @@ +//================================================================================================== +/* + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +*/ +//================================================================================================== +#pragma once + +#include + +namespace eve +{ + //================================================================================================ + //! @addtogroup complex + //! @{ + //! @var mul_mi + //! + //! @brief Callable object computing mul_mi part of values. + //! + //! **Required header:** `#include ` + //! + //! #### Members Functions + //! + //! | Member | Effect | + //! |:-------------|:-----------------------------------------------------------| + //! | `operator()` | the computation of mul_mi part | + //! + //! --- + //! + //! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp} + //! auto operator()(value auto x) const noexcept; + //! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + //! + //! **Parameters** + //! + //!`x`: [value](@ref eve::value). + //! + //! **Return value** + //! `complex < decltype(x)> equal to x multiplied by -i (i*i = -1). + //! + //! #### Example + //! + //! @godbolt{doc/complex/mul_mi.cpp} + //! + //! @} + //================================================================================================ + + namespace tag { struct mul_mi_; } + template<> struct supports_conditional : std::false_type {}; + + EVE_MAKE_CALLABLE(mul_mi_, mul_mi); + + namespace detail + { + template + EVE_FORCEINLINE auto mul_mi_( EVE_SUPPORTS(cpu_) + , V v) noexcept + { + using c_t = eve::as_complex_t; + return c_t{zero(as(v)), -v}; + } + } +} diff --git a/old/complex_hpp/regular/polar.hpp b/old/complex_hpp/regular/polar.hpp new file mode 100644 index 00000000000..31b0828c3ae --- /dev/null +++ b/old/complex_hpp/regular/polar.hpp @@ -0,0 +1,72 @@ +//================================================================================================== +/* + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +*/ +//================================================================================================== +#pragma once + +#include + +namespace eve +{ + //================================================================================================ + //! @addtogroup math + //! @{ + //! @var polar + //! + //! @brief Callable object computing the polarugate value. + //! + //! **Required header:** `#include ` + //! + //! #### Members Functions + //! + //! | Member | Effect | + //! |:-------------|:-----------------------------------------------------------| + //! | `operator()` | the computation of a complex from a module argument pair | + //! + //! --- + //! + //! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp} + //! auto operator()(floating_value auto rho, auto theta) const noexcept; + //! ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + //! + //! **Parameters** + //! + //!`rho`: the modulus of the complex + //!`theta` the argument in radian of the complex + //! + //! **Return value** + //! + //! the complex value + //! + //! --- + //! + //! #### Example + //! + //! @godbolt{doc/complex/polar.cpp} + //! + //! @} + //================================================================================================ + EVE_MAKE_CALLABLE(polar_, polar); + + namespace detail + { + template + EVE_FORCEINLINE auto polar_( EVE_SUPPORTS(cpu_) + , V const & rho + , U const & theta) noexcept + { + return arithmetic_call(polar, rho, theta); + } + + template + EVE_FORCEINLINE auto polar_(EVE_SUPPORTS(cpu_), U const & rho, U const & theta) noexcept + { + using c_t = eve::as_complex_t; + auto [s, c] = sincos(theta); + return c_t{rho*c, rho*s}; + } + } +} diff --git a/old/complex_hpp/regular/sqrt.hpp b/old/complex_hpp/regular/sqrt.hpp new file mode 100644 index 00000000000..0c6cbf939ad --- /dev/null +++ b/old/complex_hpp/regular/sqrt.hpp @@ -0,0 +1,28 @@ +//================================================================================================== +/* + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +*/ +//================================================================================================== +#pragma once + +#include +#include +#include + +namespace eve +{ + + namespace detail + { + template + EVE_FORCEINLINE auto sqrt_( EVE_SUPPORTS(cpu_) + , cmplx_type const & + , V const & v) noexcept + { + using c_t = as_complex_t; + return if_else(is_positive(v), c_t{sqrt(v), zero(as(v))}, c_t{zero(as(v)), sqrt(-v)}); + } + } +} diff --git a/old/complex_test/acos.cpp b/old/complex_test/acos.cpp new file mode 100644 index 00000000000..8205c82779e --- /dev/null +++ b/old/complex_test/acos.cpp @@ -0,0 +1,125 @@ +//================================================================================================== +/** + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +**/ +//================================================================================================== +#include "test.hpp" +#include "measures.hpp" +#include +#include +#include +#include + +EVE_TEST( "Check behavior of acos on scalar" + , eve::test::scalar::ieee_reals + , eve::test::generate( eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using c_t = std::complex; + using z_t = eve::complex; + for(auto e : a0) + { + for(auto f : a1) + { + TTS_ULP_EQUAL(eve::acos(eve::complex(e, f)), z_t(std::acos(c_t(e, f))), 2); + } + } +}; + +EVE_TEST( "Check behavior of acos on wide" + , eve::test::simd::ieee_reals + , eve::test::generate(eve::test::randoms(-5, 5) + , eve::test::randoms(-5, 5)) + ) + (T const& a0, T const& a1) +{ + using e_t = typename T::value_type; + using ce_t = eve::complex; + using z_t = eve::wide, typename T::cardinal_type>; + using c_t = std::complex; + auto std_acos = [](auto x, auto y){return std::acos(c_t(x, y)); }; + auto init_with_std = [std_acos](auto a0, auto a1){ + z_t b; + for(int i = 0; i != eve::cardinal_v; ++i) + { + ce_t z(std_acos(a0.get(i), a1.get(i))); + b.set(i, z); + } + return b; + }; + TTS_ULP_EQUAL(eve::acos(z_t{a0,a1}), init_with_std(a0, a1), 2); +}; + + +EVE_TEST_TYPES( "Check return types of eve::exp", eve::test::scalar::ieee_reals) + (eve::as) +{ + using e_t = eve::element_type_t; + using c_t = eve::complex; + using s_t = std::complex; + using eve::as; + using eve::acos; + + // specific values tests +#ifndef BOOST_SIMD_NO_INVALIDS + TTS_ULP_EQUAL(eve::acos(c_t(eve::nan (as()), eve::zero(as()))), c_t(eve::nan (as()), eve::nan(as())), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(eve::nan (as()), eve::one(as()))), c_t(eve::nan (as()), eve::nan(as())), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(eve::nan (as()), eve::inf(as()))), c_t(eve::nan (as()), -eve::inf(as())), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(eve::nan (as()), eve::nan(as()))), c_t(eve::nan (as()), eve::nan(as())), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(eve::zero (as()), eve::nan (as()))), c_t(eve::pio_2(as()), eve::nan(as())), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(eve::one (as()), eve::nan (as()))), c_t(eve::nan(as()), eve::nan(as())), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(eve::inf (as()), eve::nan(as()))), c_t(eve::nan (as()), eve::minf(as())), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(eve::one (as()), eve::inf (as()))), c_t(eve::pio_2(as()), -eve::inf(as())), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(eve::inf (as()), eve::one (as()))), c_t(eve::zero(as()), eve::minf (as())), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(eve::inf (as()), eve::inf(as()))), c_t(eve::pio_4(as()), eve::minf (as())), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(-eve::nan (as()), eve::one(as()))), c_t(eve::nan (as()), eve::nan(as())), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(-eve::nan (as()), eve::inf(as()))), c_t(eve::nan (as()), -eve::inf(as())), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(-eve::nan (as()), eve::nan(as()))), c_t(eve::nan (as()), eve::nan(as())), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(-eve::zero (as()), eve::nan (as()))), c_t(eve::pio_2(as()), eve::nan(as())), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(-eve::one (as()), eve::nan (as()))), c_t(eve::nan(as()), eve::nan(as())), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(-eve::inf (as()), eve::nan(as()))), c_t(eve::nan (as()), eve::minf(as())), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(-eve::one (as()), eve::inf (as()))), c_t(eve::pio_2(as()), eve::minf(as())), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(-eve::inf (as()), eve::one (as()))), c_t(eve::pi(as()), -eve::inf (as())), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(-eve::inf (as()), eve::inf(as()))), c_t(T(3)*eve::pio_4(as()), eve::minf (as())), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(eve::nan (as()), eve::one(as()))), c_t(std::acos(s_t(eve::nan (as()), eve::one(as())))), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(eve::nan (as()), eve::inf(as()))), c_t(std::acos(s_t(eve::nan (as()), eve::inf(as())))), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(eve::nan (as()), eve::nan(as()))), c_t(std::acos(s_t(eve::nan (as()), eve::nan(as())))), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(eve::zero (as()), eve::nan (as()))), c_t(std::acos(s_t(eve::zero (as()), eve::nan (as())))), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(eve::one (as()), eve::nan (as()))), c_t(std::acos(s_t(eve::one (as()), eve::nan (as())))), 1.0); + + + TTS_ULP_EQUAL(eve::acos(c_t(eve::one (as()), eve::inf (as()))), c_t(std::acos(s_t(eve::one (as()), eve::inf (as())))), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(eve::inf (as()), eve::one (as()))), c_t(std::acos(s_t(eve::inf (as()), eve::one (as())))), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(eve::inf (as()), eve::inf(as()))), c_t(std::acos(s_t(eve::inf (as()), eve::inf(as())))), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(-eve::nan (as()), eve::one(as()))), c_t(std::acos(s_t(-eve::nan (as()), eve::one(as())))), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(-eve::nan (as()), eve::inf(as()))), c_t(std::acos(s_t(-eve::nan (as()), eve::inf(as())))), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(-eve::nan (as()), eve::nan(as()))), c_t(std::acos(s_t(-eve::nan (as()), eve::nan(as())))), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(-eve::one (as()), eve::inf (as()))),c_t(std::acos(s_t(-eve::one (as()), eve::inf (as())))), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(-eve::inf (as()), eve::one (as()))),c_t(std::acos(s_t(-eve::inf (as()), eve::one (as())))), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(-eve::inf (as()), eve::inf(as()))), c_t(std::acos(s_t(-eve::inf (as()), eve::inf(as())))), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(-eve::one (as()), eve::nan (as()))),c_t(std::acos(s_t(-eve::one (as()), eve::nan (as())))), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(-eve::zero (as()), eve::nan (as()))),c_t(std::acos(s_t(-eve::zero (as()), eve::nan (as())))), 1.0); + + TTS_ULP_EQUAL(eve::acos(c_t(eve::inf (as()), eve::nan(as()))), c_t(eve::nan(as()), eve::minf (as())), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(-eve::inf (as()), eve::nan(as()))), c_t(eve::nan(as()), eve::minf (as())), 1.0); + + +#endif + TTS_ULP_EQUAL(eve::acos(c_t(eve::zero(as()), eve::zero(as()))), c_t(eve::pio_2(as()), eve::zero(as())), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(eve::mzero(as()), eve::zero(as()))), c_t(eve::pio_2(as()), eve::zero(as())), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(eve::one (as()), eve::one (as()))), c_t(0.904556894302381, -1.061275061905036), 2.5); + TTS_ULP_EQUAL(eve::acos(c_t(eve::one (as()), eve::mone (as()))), c_t(0.904556894302381, 1.061275061905036), 2.5); + TTS_ULP_EQUAL(eve::acos(c_t(eve::mone (as()), eve::one (as()))), c_t(2.237035759287412, -1.061275061905036), 2.5); + TTS_ULP_EQUAL(eve::acos(c_t(eve::mone (as()), eve::mone (as()))), c_t(2.237035759287412, 1.061275061905036), 2.5); + + TTS_ULP_EQUAL(eve::acos(c_t(0.5, -0.5)), c_t(std::acos(s_t(0.5, -0.5))), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(1, 1)), c_t(std::acos(s_t(1, 1))), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(1, 10)), c_t(std::acos(s_t(1, 10))), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(10, 10)), c_t(std::acos(s_t(10, 10))), 1.0); + TTS_ULP_EQUAL(eve::acos(c_t(10, 1)), c_t(std::acos(s_t(10, 1))), 1.0); +}; diff --git a/old/complex_test/acosh.cpp b/old/complex_test/acosh.cpp new file mode 100644 index 00000000000..b973c36aeb3 --- /dev/null +++ b/old/complex_test/acosh.cpp @@ -0,0 +1,102 @@ +//================================================================================================== +/** + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +**/ +//================================================================================================== +#include "test.hpp" +#include "measures.hpp" +#include +#include +#include +#include + +EVE_TEST( "Check behavior of acosh on scalar" + , eve::test::scalar::ieee_reals + , eve::test::generate( eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using c_t = std::complex; + using z_t = eve::complex; + for(auto e : a0) + { + for(auto f : a1) + { + TTS_ULP_EQUAL(eve::acosh(eve::complex(e, f)), z_t(std::acosh(c_t(e, f))), 2.0); + } + } +}; + +EVE_TEST( "Check behavior of acosh on wide" + , eve::test::simd::ieee_reals + , eve::test::generate(eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using ce_t = eve::complex; + using z_t = eve::wide, typename T::cardinal_type>; + using c_t = std::complex; + auto std_ch = [](auto x, auto y){return std::acosh(c_t(x, y)); }; + auto init_with_std = [std_ch](auto a0, auto a1){ + z_t b; + for(int i = 0; i != eve::cardinal_v; ++i) + { + ce_t z(std_ch(a0.get(i), a1.get(i))); + b.set(i, z); + } + return b; + }; + TTS_ULP_EQUAL(eve::acosh(z_t{a0,a1}), init_with_std(a0, a1), 2); +}; + + +// EVE_TEST_TYPES( "Check return types of eve::abs", eve::test::scalar::ieee_reals) +// (eve::as) +// { +// using e_t = eve::element_type_t; +// using c_t = eve::complex; +// using eve::as; +// const int N = 24; +// e_t pid = eve::downward(eve::pi)(as()); // nearest pi representation less than mathematical pi +// e_t piu = eve::upward(eve::pi)(as()); // nearest pi representation greater than mathematical pi +// std::array inputs = +// { c_t(eve::zero(as()),eve::zero(as())),//0 +// c_t(eve::inf(as()),eve::zero(as())), //1 +// c_t(eve::minf(as()),eve::zero(as())),//2 +// c_t(eve::nan(as()),eve::zero(as())), //3 +// c_t(eve::zero(as()),eve::inf(as())), //4 +// c_t(eve::inf(as()),eve::inf(as())), //5 +// c_t(eve::minf(as()),eve::inf(as())), //6 +// c_t(eve::nan(as()),eve::inf(as())), //7 +// c_t(eve::zero(as()),eve::minf(as())),//8 +// c_t(eve::inf(as()),eve::minf(as())), //9 +// c_t(eve::minf(as()),eve::minf(as())),//10 +// c_t(eve::nan(as()),eve::minf(as())), //11 +// c_t(eve::zero(as()),eve::nan(as())), //12 +// c_t(eve::inf(as()),eve::nan(as())), //13 +// c_t(eve::minf(as()),eve::nan(as())), //14 +// c_t(eve::nan(as()),eve::nan(as())), //15 +// c_t(eve::zero(as()),pid), //16 +// c_t(eve::inf(as()),pid), //17 +// c_t(eve::minf(as()),pid), //18 +// c_t(eve::nan(as()),pid), //19 +// c_t(eve::zero(as()),piu), //20 +// c_t(eve::inf(as()),piu), //21 +// c_t(eve::minf(as()),piu), //22 +// c_t(eve::nan(as()),piu), //23 +// }; + +// auto acoshine = eve::pedantic(eve::acosh); +// auto tacoshine= [](auto z){return eve::pedantic(eve::acoshh)(eve::mul_i(z));}; +// for(int i=0; i < N; ++i) +// { +// TTS_IEEE_EQUAL(acoshine(-inputs[i]), acoshine(inputs[i])); +// TTS_IEEE_EQUAL(acoshine(inputs[i]), tacoshine(inputs[i])); +// } +// }; diff --git a/old/complex_test/asin.cpp b/old/complex_test/asin.cpp new file mode 100644 index 00000000000..22d92eaba35 --- /dev/null +++ b/old/complex_test/asin.cpp @@ -0,0 +1,123 @@ +//================================================================================================== +/** + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +**/ +//================================================================================================== +#include "test.hpp" +#include "measures.hpp" +#include +#include +#include +#include + +EVE_TEST( "Check behavior of asin on scalar" + , eve::test::scalar::ieee_reals + , eve::test::generate( eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using c_t = std::complex; + using z_t = eve::complex; + for(auto e : a0) + { + for(auto f : a1) + { + TTS_ULP_EQUAL(eve::asin(eve::complex(e, f)), z_t(std::asin(c_t(e, f))), 3.5); + } + } +}; + +EVE_TEST( "Check behavior of asin on wide" + , eve::test::simd::ieee_reals + , eve::test::generate(eve::test::randoms(-5, 5) + , eve::test::randoms(-5, 5)) + ) + (T const& a0, T const& a1) +{ + using e_t = typename T::value_type; + using ce_t = eve::complex; + using z_t = eve::wide, typename T::cardinal_type>; + using c_t = std::complex; + auto std_asin = [](auto x, auto y){return std::asin(c_t(x, y)); }; + auto init_with_std = [std_asin](auto a0, auto a1){ + z_t b; + for(int i = 0; i != eve::cardinal_v; ++i) + { + ce_t z(std_asin(a0.get(i), a1.get(i))); + b.set(i, z); + } + return b; + }; + TTS_ULP_EQUAL(eve::asin(z_t{a0,a1}), init_with_std(a0, a1), 2); +}; + +EVE_TEST_TYPES( "Check return types of eve::asin", eve::test::scalar::ieee_reals) + (eve::as) +{ + using e_t = eve::element_type_t; + using c_t = eve::complex; + using s_t = std::complex; + using eve::as; + auto s_asin = [](auto x){return c_t(std::asin(x)); }; + // specific values tests +#ifndef boost_simd_no_invalids + TTS_ULP_EQUAL(eve::asin(c_t(eve::nan (as()), eve::zero(as()))), s_asin(s_t(eve::nan (as()), eve::zero(as())) ), 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(eve::nan (as()), eve::one(as()))), s_asin(s_t(eve::nan (as()), eve::one(as())) ), 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(eve::nan (as()), eve::inf(as()))), s_asin(s_t(eve::nan (as()), eve::inf(as())) ), 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(eve::nan (as()), eve::nan(as()))), s_asin(s_t(eve::nan (as()), eve::nan(as())) ), 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(eve::zero (as()), eve::nan (as()))), s_asin(s_t(eve::zero (as()), eve::nan (as())) ), 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(eve::one (as()), eve::nan (as()))), s_asin(s_t(eve::one (as()), eve::nan (as())) ), 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(eve::inf (as()), eve::nan(as()))), c_t(eve::nan (as()), eve::inf(as())), 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(eve::one (as()), eve::inf (as()))), s_asin(s_t(eve::one (as()), eve::inf (as())) ), 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(eve::inf (as()), eve::one (as()))), s_asin(s_t(eve::inf (as()), eve::one (as())) ), 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(eve::inf (as()), eve::inf(as()))), s_asin(s_t(eve::inf (as()), eve::inf(as())) ), 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(-eve::nan (as()), eve::one(as()))), s_asin(s_t(-eve::nan (as()), eve::one(as())) ), 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(-eve::nan (as()), eve::inf(as()))), s_asin(s_t(-eve::nan (as()), eve::inf(as())) ), 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(-eve::nan (as()), eve::nan(as()))), s_asin(s_t(-eve::nan (as()), eve::nan(as())) ), 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(-eve::zero (as()), eve::nan (as()))),s_asin(s_t(-eve::zero (as()), eve::nan (as()))), 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(-eve::one (as()), eve::nan (as()))),s_asin(s_t(-eve::one (as()), eve::nan (as()))), 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(-eve::inf (as()), eve::nan(as()))), c_t(eve::nan (as()), eve::inf(as())), 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(-eve::one (as()), eve::inf (as()))),s_asin(s_t(-eve::one (as()), eve::inf (as()))), 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(-eve::inf (as()), eve::one (as()))),s_asin(s_t(-eve::inf (as()), eve::one (as()))), 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(-eve::inf (as()), eve::inf(as()))), s_asin(s_t(-eve::inf (as()), eve::inf(as())) ), 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(eve::nan (as()), eve::one(as()))), s_asin(s_t(eve::nan (as()), eve::one(as())) ), 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(eve::nan (as()), eve::inf(as()))), s_asin(s_t(eve::nan (as()), eve::inf(as())) ), 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(eve::nan (as()), eve::nan(as()))), s_asin(s_t(eve::nan (as()), eve::nan(as())) ), 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(eve::zero (as()), eve::nan (as()))), s_asin(s_t(eve::zero (as()), eve::nan (as())) ), 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(eve::one (as()), eve::nan (as()))), s_asin(s_t(eve::one (as()), eve::nan (as())) ), 2.0); + + + TTS_ULP_EQUAL(eve::asin(c_t(eve::one (as()), eve::inf (as()))), s_asin(s_t(eve::one (as()), eve::inf (as()))) , 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(eve::inf (as()), eve::one (as()))), s_asin(s_t(eve::inf (as()), eve::one (as()))) , 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(eve::inf (as()), eve::inf(as()))), s_asin(s_t(eve::inf (as()), eve::inf(as()))) , 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(-eve::nan (as()), eve::one(as()))), s_asin(s_t(-eve::nan (as()), eve::one(as()))) , 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(-eve::nan (as()), eve::inf(as()))), s_asin(s_t(-eve::nan (as()), eve::inf(as()))) , 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(-eve::nan (as()), eve::nan(as()))), s_asin(s_t(-eve::nan (as()), eve::nan(as()))) , 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(-eve::one (as()), eve::inf (as()))), s_asin(s_t(-eve::one (as()), eve::inf (as()))) , 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(-eve::inf (as()), eve::one (as()))), s_asin(s_t(-eve::inf (as()), eve::one (as()))) , 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(-eve::inf (as()), eve::inf(as()))), s_asin(s_t(-eve::inf (as()), eve::inf(as()))) , 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(-eve::one (as()), eve::nan (as()))), s_asin(s_t(-eve::one (as()), eve::nan (as()))) , 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(-eve::zero (as()), eve::nan (as()))), s_asin(s_t(-eve::zero (as()), eve::nan (as()))) , 2.0); + + TTS_ULP_EQUAL(eve::asin(c_t(eve::inf (as()), eve::nan(as()))), c_t(eve::nan(as()), eve::inf (as())), 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(-eve::inf (as()), eve::nan(as()))), c_t(eve::nan(as()), eve::inf (as())), 2.0); + + +#endif + TTS_ULP_EQUAL(eve::asin(c_t(eve::zero(as()), eve::zero(as()))), s_asin(s_t(eve::zero(as()), eve::zero(as()))) ,2.0); + TTS_ULP_EQUAL(eve::asin(c_t(eve::mzero(as()), eve::zero(as()))), s_asin(s_t(eve::mzero(as()), eve::zero(as()))) ,2.0); + TTS_ULP_EQUAL(eve::asin(c_t(eve::one (as()), eve::one (as()))), s_asin(s_t(eve::one (as()), eve::one (as()))) ,2.0); + TTS_ULP_EQUAL(eve::asin(c_t(eve::one (as()), eve::mone (as()))), s_asin(s_t(eve::one (as()), eve::mone (as()))) ,2.0); + TTS_ULP_EQUAL(eve::asin(c_t(eve::mone (as()), eve::one (as()))), s_asin(s_t(eve::mone (as()), eve::one (as()))) ,2.0); + TTS_ULP_EQUAL(eve::asin(c_t(eve::mone (as()), eve::mone (as()))), s_asin(s_t(eve::mone (as()), eve::mone (as()))),2.0); + + TTS_ULP_EQUAL(eve::asin(c_t(1, 1)), s_asin(s_t(1, 1)), 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(1, 10)), s_asin(s_t(1, 10)), 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(10, 1)), s_asin(s_t(10, 1)), 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(10, 10)), s_asin(s_t(10, 10)), 2.0); + TTS_ULP_EQUAL(eve::asin(c_t(0.5, -0.5)), s_asin(s_t(0.5, -0.5)), 2.0); +}; diff --git a/old/complex_test/asinh.cpp b/old/complex_test/asinh.cpp new file mode 100644 index 00000000000..ea0d1fcd758 --- /dev/null +++ b/old/complex_test/asinh.cpp @@ -0,0 +1,86 @@ +//================================================================================================== +/** + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +**/ +//================================================================================================== +#include "test.hpp" +#include "measures.hpp" +#include +#include +#include +#include + +EVE_TEST( "Check behavior of asinh on scalar" + , eve::test::scalar::ieee_reals + , eve::test::generate( eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using c_t = std::complex; + using z_t = eve::complex; + for(auto e : a0) + { + for(auto f : a1) + { + TTS_ULP_EQUAL(eve::asinh(eve::complex(e, f)), z_t(std::asinh(c_t(e, f))), 3.5); + } + } +}; + +EVE_TEST( "Check behavior of asinh on wide" + , eve::test::simd::ieee_reals + , eve::test::generate(eve::test::randoms(-5, 5) + , eve::test::randoms(-5, 5)) + ) + (T const& a0, T const& a1) +{ + using e_t = typename T::value_type; + using ce_t = eve::complex; + using z_t = eve::wide, typename T::cardinal_type>; + using c_t = std::complex; + auto std_asinh = [](auto x, auto y){return std::asinh(c_t(x, y)); }; + auto init_with_std = [std_asinh](auto a0, auto a1){ + z_t b; + for(int i = 0; i != eve::cardinal_v; ++i) + { + ce_t z(std_asinh(a0.get(i), a1.get(i))); + b.set(i, z); + } + return b; + }; + TTS_ULP_EQUAL(eve::asinh(z_t{a0,a1}), init_with_std(a0, a1), 2); +}; + +EVE_TEST_TYPES( "Check return types of eve::asinh", eve::test::scalar::ieee_reals) + (eve::as) +{ + using e_t = eve::element_type_t; + using c_t = eve::complex; + using eve::as; + + // specific values tests + + TTS_ULP_EQUAL(eve::asinh(c_t(eve::nan (as()), eve::zero(as()))), c_t(eve::nan (as()), eve::zero(as())), 0.75); + TTS_ULP_EQUAL(eve::asinh(c_t(eve::one (as()), eve::inf (as()))), c_t(eve::inf(as()), eve::pio_2(as())), 0.75); + TTS_ULP_EQUAL(eve::asinh(c_t(eve::one (as()), eve::nan (as()))), c_t(eve::nan(as()), eve::nan(as())), 0.75); + TTS_ULP_EQUAL(eve::asinh(c_t(eve::inf (as()), eve::one (as()))), c_t(eve::inf (as()), eve::zero(as())), 0.75); + TTS_ULP_EQUAL(eve::asinh(c_t(eve::inf (as()), eve::inf(as()))), c_t(eve::inf (as()), eve::pi(as())/4), 0.75); + TTS_ULP_EQUAL(eve::asinh(c_t(eve::inf (as()), eve::nan(as()))), c_t(eve::inf (as()), eve::nan(as())), 0.75); + TTS_ULP_EQUAL(eve::asinh(c_t(eve::nan (as()), eve::one(as()))), c_t(eve::nan (as()), eve::nan(as())), 0.75); + TTS_ULP_EQUAL(eve::asinh(c_t(eve::nan (as()), eve::inf(as()))), c_t(eve::minf (as()), eve::nan(as())), 0.75); + TTS_ULP_EQUAL(eve::asinh(c_t(eve::nan (as()), eve::nan(as()))), c_t(eve::nan (as()), eve::nan(as())), 0.75); + TTS_ULP_EQUAL(eve::asinh(c_t(eve::one (as()), -eve::inf (as()))), c_t(eve::inf(as()), -eve::pio_2(as())), 0.75); + TTS_ULP_EQUAL(eve::asinh(c_t(eve::one (as()), -eve::nan (as()))), c_t(eve::nan(as()), -eve::nan(as())), 0.75); + TTS_ULP_EQUAL(eve::asinh(c_t(eve::inf (as()), -eve::one (as()))), c_t(eve::inf (as()), -eve::zero(as())), 0.75); + TTS_ULP_EQUAL(eve::asinh(c_t(eve::inf (as()), -eve::inf(as()))), c_t(eve::inf (as()), -eve::pi(as())/4), 0.75); + TTS_ULP_EQUAL(eve::asinh(c_t(eve::inf (as()), -eve::nan(as()))), c_t(eve::inf (as()), -eve::nan(as())), 0.75); + TTS_ULP_EQUAL(eve::asinh(c_t(eve::nan (as()), -eve::one(as()))), c_t(eve::nan (as()), -eve::nan(as())), 0.75); + TTS_ULP_EQUAL(eve::asinh(c_t(eve::nan (as()), -eve::inf(as()))), c_t(eve::minf (as()), -eve::nan(as())), 0.75); + TTS_ULP_EQUAL(eve::asinh(c_t(eve::nan (as()), -eve::nan(as()))), c_t(eve::nan (as()), -eve::nan(as())), 0.75); + + TTS_ULP_EQUAL(eve::asinh(c_t(eve::zero(as()), eve::zero(as()))), c_t(eve::zero(as()), eve::zero(as())), 0.75); +}; diff --git a/old/complex_test/atan.cpp b/old/complex_test/atan.cpp new file mode 100644 index 00000000000..51f6e6c050a --- /dev/null +++ b/old/complex_test/atan.cpp @@ -0,0 +1,102 @@ +//================================================================================================== +/** + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +**/ +//================================================================================================== +#include "test.hpp" +#include "measures.hpp" +#include +#include +#include +#include + +EVE_TEST( "Check behavior of atan on scalar" + , eve::test::scalar::ieee_reals + , eve::test::generate( eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using c_t = std::complex; + using z_t = eve::complex; + for(auto e : a0) + { + for(auto f : a1) + { + TTS_ULP_EQUAL(eve::atan(eve::complex(e, f)), z_t(std::atan(c_t(e, f))), 2.0); + } + } +}; + +EVE_TEST( "Check behavior of atan on wide" + , eve::test::simd::ieee_reals + , eve::test::generate(eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using ce_t = eve::complex; + using z_t = eve::wide, typename T::cardinal_type>; + using c_t = std::complex; + auto std_ch = [](auto x, auto y){return std::atan(c_t(x, y)); }; + auto init_with_std = [std_ch](auto a0, auto a1){ + z_t b; + for(int i = 0; i != eve::cardinal_v; ++i) + { + ce_t z(std_ch(a0.get(i), a1.get(i))); + b.set(i, z); + } + return b; + }; + TTS_ULP_EQUAL(eve::atan(z_t{a0,a1}), init_with_std(a0, a1), 2); +}; + + +// EVE_TEST_TYPES( "Check return types of eve::abs", eve::test::scalar::ieee_reals) +// (eve::as) +// { +// using e_t = eve::element_type_t; +// using c_t = eve::complex; +// using eve::as; +// const int N = 24; +// e_t pid = eve::downward(eve::pi)(as()); // nearest pi representation less than mathematical pi +// e_t piu = eve::upward(eve::pi)(as()); // nearest pi representation greater than mathematical pi +// std::array inputs = +// { c_t(eve::zero(as()),eve::zero(as())),//0 +// c_t(eve::inf(as()),eve::zero(as())), //1 +// c_t(eve::minf(as()),eve::zero(as())),//2 +// c_t(eve::nan(as()),eve::zero(as())), //3 +// c_t(eve::zero(as()),eve::inf(as())), //4 +// c_t(eve::inf(as()),eve::inf(as())), //5 +// c_t(eve::minf(as()),eve::inf(as())), //6 +// c_t(eve::nan(as()),eve::inf(as())), //7 +// c_t(eve::zero(as()),eve::minf(as())),//8 +// c_t(eve::inf(as()),eve::minf(as())), //9 +// c_t(eve::minf(as()),eve::minf(as())),//10 +// c_t(eve::nan(as()),eve::minf(as())), //11 +// c_t(eve::zero(as()),eve::nan(as())), //12 +// c_t(eve::inf(as()),eve::nan(as())), //13 +// c_t(eve::minf(as()),eve::nan(as())), //14 +// c_t(eve::nan(as()),eve::nan(as())), //15 +// c_t(eve::zero(as()),pid), //16 +// c_t(eve::inf(as()),pid), //17 +// c_t(eve::minf(as()),pid), //18 +// c_t(eve::nan(as()),pid), //19 +// c_t(eve::zero(as()),piu), //20 +// c_t(eve::inf(as()),piu), //21 +// c_t(eve::minf(as()),piu), //22 +// c_t(eve::nan(as()),piu), //23 +// }; + +// auto atanine = eve::pedantic(eve::atan); +// auto tatanine= [](auto z){return eve::pedantic(eve::atanh)(eve::mul_i(z));}; +// for(int i=0; i < N; ++i) +// { +// TTS_IEEE_EQUAL(atanine(-inputs[i]), atanine(inputs[i])); +// TTS_IEEE_EQUAL(atanine(inputs[i]), tatanine(inputs[i])); +// } +// }; diff --git a/old/complex_test/atanh.cpp b/old/complex_test/atanh.cpp new file mode 100644 index 00000000000..d8a2b4a680f --- /dev/null +++ b/old/complex_test/atanh.cpp @@ -0,0 +1,56 @@ +//================================================================================================== +/** + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +**/ +//================================================================================================== +#include "test.hpp" +#include "measures.hpp" +#include +#include +#include +#include + +EVE_TEST( "Check behavior of atanh on scalar" + , eve::test::scalar::ieee_reals + , eve::test::generate( eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using c_t = std::complex; + using z_t = eve::complex; + for(auto e : a0) + { + for(auto f : a1) + { + TTS_ULP_EQUAL(eve::atanh(eve::complex(e, f)), z_t(std::atanh(c_t(e, f))), 2.0); + } + } +}; + +EVE_TEST( "Check behavior of atanh on wide" + , eve::test::simd::ieee_reals + , eve::test::generate(eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using ce_t = eve::complex; + using z_t = eve::wide, typename T::cardinal_type>; + using c_t = std::complex; + auto std_ch = [](auto x, auto y){return std::atanh(c_t(x, y)); }; + auto init_with_std = [std_ch](auto a0, auto a1){ + z_t b; + for(int i = 0; i != eve::cardinal_v; ++i) + { + ce_t z(std_ch(a0.get(i), a1.get(i))); + b.set(i, z); + } + return b; + }; + TTS_ULP_EQUAL(eve::atanh(z_t{a0,a1}), init_with_std(a0, a1), 2); +}; diff --git a/old/complex_test/cos.cpp b/old/complex_test/cos.cpp new file mode 100644 index 00000000000..eeda2374fb8 --- /dev/null +++ b/old/complex_test/cos.cpp @@ -0,0 +1,125 @@ +//================================================================================================== +/** + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +**/ +//================================================================================================== +#include "test.hpp" +#include "measures.hpp" +#include +#include +#include +#include + +EVE_TEST( "Check behavior of cos on scalar" + , eve::test::scalar::ieee_reals + , eve::test::generate( eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using c_t = std::complex; + using z_t = eve::complex; + for(auto e : a0) + { + for(auto f : a1) + { + std::cout << "e = " << e << " f = " << f << std::endl; + TTS_ULP_EQUAL(eve::cos(eve::complex(e, f)), z_t(std::cos(c_t(e, f))), 2); + TTS_ULP_EQUAL(eve::pedantic(eve::cos)(eve::complex(e, f)), z_t(std::cos(c_t(e, f))), 2); + TTS_ULP_EQUAL(eve::cos(eve::complex(e, f)), z_t(std::cos(c_t(e, f))), 2.0); + } + } +}; + +EVE_TEST( "Check behavior of cos on wide" + , eve::test::simd::ieee_reals + , eve::test::generate(eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using ce_t = eve::complex; + using z_t = eve::wide, typename T::cardinal_type>; + using c_t = std::complex; + auto std_ch = [](auto x, auto y){return std::cos(c_t(x, y)); }; + auto init_with_std = [std_ch](auto a0, auto a1){ + z_t b; + for(int i = 0; i != eve::cardinal_v; ++i) + { + ce_t z(std_ch(a0.get(i), a1.get(i))); + b.set(i, z); + } + return b; + }; + TTS_ULP_EQUAL(eve::cos(z_t{a0,a1}), init_with_std(a0, a1), 2); +}; + + +EVE_TEST( "Check behavior of pedantic(cos) on wide" + , eve::test::simd::ieee_reals + , eve::test::generate(eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using ce_t = eve::complex; + using z_t = eve::wide, typename T::cardinal_type>; + using c_t = std::complex; + z_t b; + for(int i = 0; i != eve::cardinal_v; ++i) + { + ce_t z(std::cos(c_t(a0.get(i), a1.get(i)))); + b.set(i, z); + } + TTS_ULP_EQUAL(eve::pedantic(eve::cos)(z_t{a0,a1}), b, 2.0); +}; + +EVE_TEST_TYPES( "Check return types of eve::abs", eve::test::scalar::ieee_reals) + (eve::as) +{ + using e_t = eve::element_type_t; + using c_t = eve::complex; + using eve::as; + const int N = 24; + e_t pid = eve::downward(eve::pi)(as()); // nearest pi representation less than mathematical pi + e_t piu = eve::upward(eve::pi)(as()); // nearest pi representation greater than mathematical pi + std::array inputs = + { c_t(eve::zero(as()),eve::zero(as())),//0 + c_t(eve::inf(as()),eve::zero(as())), //1 + c_t(eve::minf(as()),eve::zero(as())),//2 + c_t(eve::nan(as()),eve::zero(as())), //3 + c_t(eve::zero(as()),eve::inf(as())), //4 + c_t(eve::inf(as()),eve::inf(as())), //5 + c_t(eve::minf(as()),eve::inf(as())), //6 + c_t(eve::nan(as()),eve::inf(as())), //7 + c_t(eve::zero(as()),eve::minf(as())),//8 + c_t(eve::inf(as()),eve::minf(as())), //9 + c_t(eve::minf(as()),eve::minf(as())),//10 + c_t(eve::nan(as()),eve::minf(as())), //11 + c_t(eve::zero(as()),eve::nan(as())), //12 + c_t(eve::inf(as()),eve::nan(as())), //13 + c_t(eve::minf(as()),eve::nan(as())), //14 + c_t(eve::nan(as()),eve::nan(as())), //15 + c_t(eve::zero(as()),pid), //16 + c_t(eve::inf(as()),pid), //17 + c_t(eve::minf(as()),pid), //18 + c_t(eve::nan(as()),pid), //19 + c_t(eve::zero(as()),piu), //20 + c_t(eve::inf(as()),piu), //21 + c_t(eve::minf(as()),piu), //22 + c_t(eve::nan(as()),piu), //23 + }; + + auto cosine = eve::pedantic(eve::cos); + auto tcosine= [](auto z){return eve::pedantic(eve::cosh)(eve::mul_i(z));}; + for(int i=0; i < N; ++i) + { + TTS_IEEE_EQUAL(cosine(-inputs[i]), cosine(inputs[i])); + TTS_IEEE_EQUAL(cosine(inputs[i]), tcosine(inputs[i])); + } +}; diff --git a/old/complex_test/cosh.cpp b/old/complex_test/cosh.cpp new file mode 100644 index 00000000000..48dd1c966e7 --- /dev/null +++ b/old/complex_test/cosh.cpp @@ -0,0 +1,152 @@ +//================================================================================================== +/** + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +**/ +//================================================================================================== +#include "test.hpp" +#include "measures.hpp" +#include +#include +#include +#include + +EVE_TEST( "Check behavior of cosh on scalar" + , eve::test::scalar::ieee_reals + , eve::test::generate( eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using c_t = std::complex; + using z_t = eve::complex; + for(auto e : a0) + { + for(auto f : a1) + { + std::cout << "e = " << e << " f = " << f << std::endl; + TTS_ULP_EQUAL(eve::cosh(eve::complex(e, f)), z_t(std::cosh(c_t(e, f))), 2); + TTS_ULP_EQUAL(eve::pedantic(eve::cosh)(eve::complex(e, f)), z_t(std::cosh(c_t(e, f))), 2); + TTS_ULP_EQUAL(eve::cosh(eve::complex(e, f)), z_t(std::cosh(c_t(e, f))), 2.0); + } + } +}; + +EVE_TEST( "Check behavior of cosh on wide" + , eve::test::simd::ieee_reals + , eve::test::generate(eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using ce_t = eve::complex; + using z_t = eve::wide, typename T::cardinal_type>; + using c_t = std::complex; + auto std_ch = [](auto x, auto y){return std::cosh(c_t(x, y)); }; + auto init_with_std = [std_ch](auto a0, auto a1){ + z_t b; + for(int i = 0; i != eve::cardinal_v; ++i) + { + ce_t z(std_ch(a0.get(i), a1.get(i))); + b.set(i, z); + } + return b; + }; + TTS_ULP_EQUAL(eve::cosh(z_t{a0,a1}), init_with_std(a0, a1), 2); +}; + + +EVE_TEST( "Check behavior of pedantic(cosh) on wide" + , eve::test::simd::ieee_reals + , eve::test::generate(eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using ce_t = eve::complex; + using z_t = eve::wide, typename T::cardinal_type>; + using c_t = std::complex; + z_t b; + for(int i = 0; i != eve::cardinal_v; ++i) + { + ce_t z(std::cosh(c_t(a0.get(i), a1.get(i)))); + b.set(i, z); + } + TTS_ULP_EQUAL(eve::pedantic(eve::cosh)(z_t{a0,a1}), b, 2.0); +}; + +EVE_TEST_TYPES( "Check return types of eve::abs", eve::test::scalar::ieee_reals) + (eve::as) +{ + using e_t = eve::element_type_t; + using c_t = eve::complex; + using eve::as; + const int N = 24; + e_t pid = eve::downward(eve::pi)(as()); // nearest pi representation less than mathematical pi + e_t piu = eve::upward(eve::pi)(as()); // nearest pi representation greater than mathematical pi + std::array inputs = + { c_t(eve::zero(as()),eve::zero(as())),//0 + c_t(eve::inf(as()),eve::zero(as())), //1 + c_t(eve::minf(as()),eve::zero(as())),//2 + c_t(eve::nan(as()),eve::zero(as())), //3 + c_t(eve::zero(as()),eve::inf(as())), //4 + c_t(eve::inf(as()),eve::inf(as())), //5 + c_t(eve::minf(as()),eve::inf(as())), //6 + c_t(eve::nan(as()),eve::inf(as())), //7 + c_t(eve::zero(as()),eve::minf(as())),//8 + c_t(eve::inf(as()),eve::minf(as())), //9 + c_t(eve::minf(as()),eve::minf(as())),//10 + c_t(eve::nan(as()),eve::minf(as())), //11 + c_t(eve::zero(as()),eve::nan(as())), //12 + c_t(eve::inf(as()),eve::nan(as())), //13 + c_t(eve::minf(as()),eve::nan(as())), //14 + c_t(eve::nan(as()),eve::nan(as())), //15 + c_t(eve::zero(as()),pid), //16 + c_t(eve::inf(as()),pid), //17 + c_t(eve::minf(as()),pid), //18 + c_t(eve::nan(as()),pid), //19 + c_t(eve::zero(as()),piu), //20 + c_t(eve::inf(as()),piu), //21 + c_t(eve::minf(as()),piu), //22 + c_t(eve::nan(as()),piu), //23 + }; + + std::array results = + { c_t(eve::one(as()), eve::zero(as())),//0 + c_t(eve::inf(as()),eve::zero(as())), //1 + c_t(eve::inf(as()),eve::zero(as())), //2 + c_t(eve::nan(as()),eve::zero(as())), //3 + c_t(eve::nan(as()), eve::zero(as())),//4 + c_t(eve::inf(as()),eve::nan(as())), //5 + c_t(eve::inf(as()),eve::nan(as())), //6 + c_t(eve::nan(as()),eve::nan(as())), //7 + c_t(eve::nan(as()), eve::zero(as())),//8 + c_t(eve::inf(as()),eve::nan(as())), //9 + c_t(eve::inf(as()),eve::nan(as())), //10 + c_t(eve::nan(as()),eve::nan(as())), //11 + c_t(eve::nan(as()),eve::zero(as())), //12 + c_t(eve::inf(as()),eve::nan(as())), //13 + c_t(eve::inf(as()),eve::nan(as())), //14 + c_t(eve::nan(as()),eve::nan(as())), //15 + c_t(eve::mone(as()),eve::zero(as())),//16 + c_t(eve::minf(as()),eve::inf(as())), //17 + c_t(eve::minf(as()),eve::minf(as())),//18 + c_t(eve::nan(as()),eve::nan (as())), //19 + c_t(eve::mone(as()),eve::zero(as())),//20 + c_t(eve::minf(as()),eve::minf(as())),//21 + c_t(eve::minf(as()),eve::inf(as())), //22 + c_t(eve::nan(as()),eve::nan (as())), //23 + }; + + auto ch = eve::pedantic(eve::cosh); + for(int i=0; i < N; ++i) + { + TTS_IEEE_EQUAL(ch(inputs[i]), results[i]); + TTS_IEEE_EQUAL(ch(-inputs[i]), ch(inputs[i])); + TTS_IEEE_EQUAL(ch(inputs[i]), eve::pedantic(eve::cos)(eve::mul_i(inputs[i]))); + } +}; diff --git a/old/complex_test/div.cpp b/old/complex_test/div.cpp new file mode 100644 index 00000000000..e8df44879e7 --- /dev/null +++ b/old/complex_test/div.cpp @@ -0,0 +1,49 @@ +//================================================================================================== +/** + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +**/ +//================================================================================================== +#include "test.hpp" +#include +#include + +EVE_TEST_TYPES( "Check complex::operator+", eve::test::scalar::ieee_reals) +(eve::as) +{ + using w_t = eve::wide; + + std::complex c_s1(T{1}, T{5}), c_s2(T{2}, T{1}), c_m(T{1.4}, T{1.8}); + eve::complex z_s1(c_s1), z_s2(c_s2), z_m(c_m); + TTS_EQUAL(std::real(c_s1/c_s2), std::real(c_m)); + TTS_EQUAL(std::imag(c_s1/c_s2), std::imag(c_m)); + + TTS_EXPECT(eve::ulpdist(eve::real(z_s1/z_s2), eve::real(z_m)) <= 0.5); + TTS_EXPECT(eve::ulpdist(eve::imag(z_s1/z_s2), eve::imag(z_m)) <= 0.5); + + std::cout << std::setprecision(15) << z_s1/z_s2 << std::endl; + std::cout << std::setprecision(15) << c_s1/c_s2 << std::endl; + auto fill_r = [](auto e, auto) { return T(1+e); }; + auto fill_i = [](auto e, auto) { return T(1)/T(1+3*e); }; + auto fill_r1 = [](auto e, auto) { return T(1-e/2); }; + auto fill_i1 = [](auto e, auto) { return T(-1+3.5*e); }; + + using w_t = eve::wide; + using cw_t = eve::wide>; + w_t wr(fill_r); + w_t wi(fill_i); + w_t wr1(fill_r1); + w_t wi1(fill_i1); + + eve::wide> z(wr, wi); + eve::wide> zbar(wr, -wi); + eve::wide> z1(wr1, wi1); + auto std_div = [](eve::complex a, eve::complex b) -> eve::complex { + return std::complex(eve::real(a), eve::imag(a))/std::complex(eve::real(b), eve::imag(b)); + }; + auto my_div = [std_div](cw_t a, cw_t b) -> cw_t { return map(std_div, a, b); }; + + TTS_EXPECT(eve::all(eve::ulpdist( z/zbar, my_div(z, zbar)) <= 2)); + TTS_EXPECT(eve::all(eve::ulpdist( z/z1, my_div(z, z1) ) <= 2)); +}; diff --git a/old/complex_test/exp.cpp b/old/complex_test/exp.cpp new file mode 100644 index 00000000000..beea25854a9 --- /dev/null +++ b/old/complex_test/exp.cpp @@ -0,0 +1,102 @@ +//================================================================================================== +/** + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +**/ +//================================================================================================== +#include "test.hpp" +#include "measures.hpp" +#include +#include +#include +#include + +EVE_TEST( "Check behavior of exp on scalar" + , eve::test::scalar::ieee_reals + , eve::test::generate( eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using c_t = std::complex; + using z_t = eve::complex; + for(auto e : a0) + { + for(auto f : a1) + { + TTS_ULP_EQUAL(eve::exp(eve::complex(e, f)), z_t(std::exp(c_t(e, f))), 2); + TTS_ULP_EQUAL(eve::exp(eve::complex(e, f)), z_t(std::exp(c_t(e, f))), 2.0); + } + } +}; + +EVE_TEST( "Check behavior of exp on wide" + , eve::test::simd::ieee_reals + , eve::test::generate(eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using ce_t = eve::complex; + using z_t = eve::wide, typename T::cardinal_type>; + using c_t = std::complex; + auto std_ch = [](auto x, auto y){return std::exp(c_t(x, y)); }; + auto init_with_std = [std_ch](auto a0, auto a1){ + z_t b; + for(int i = 0; i != eve::cardinal_v; ++i) + { + ce_t z(std_ch(a0.get(i), a1.get(i))); + b.set(i, z); + } + return b; + }; + TTS_ULP_EQUAL(eve::exp(z_t{a0,a1}), init_with_std(a0, a1), 2); +}; + +EVE_TEST_TYPES( "Check return types of eve::exp", eve::test::scalar::ieee_reals) + (eve::as) +{ + using e_t = eve::element_type_t; + using c_t = eve::complex; + using eve::as; + using eve::exp; + TTS_ULP_EQUAL(exp(c_t(eve::inf(as()))), c_t(eve::inf(as())), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::minf(as()))), c_t(eve::zero(as())), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::nan(as()))), c_t(eve::nan(as()), eve::zero(as())), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::inf (as()), eve::zero(as()))), c_t(eve::inf(as()), eve::zero(as())), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::nan (as()), eve::zero(as()))), c_t(eve::nan (as()), eve::zero(as())), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::one (as()), eve::inf (as()))), c_t(eve::nan(as()), eve::nan(as())), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::one (as()), eve::nan (as()))), c_t(eve::nan(as()), eve::nan(as())), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::minf (as()), eve::one (as()))), c_t(eve::zero(as())), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::minf (as()), eve::mone(as()))), c_t(eve::zero(as())), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::inf (as()), eve::one (as()))), c_t(eve::inf (as())*exp(c_t(eve::zero(as()), eve::one (as())))), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::inf (as()), eve::mone(as()))), c_t(eve::inf (as())*exp(c_t(eve::zero(as()), eve::mone(as())))), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::minf (as()), eve::inf(as()))), c_t(eve::zero(as())), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::inf (as()), eve::inf(as()))), c_t(eve::nan (as()), eve::nan(as())), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::minf (as()), eve::nan(as()))), c_t(eve::zero(as())), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::inf (as()), eve::nan(as()))), c_t(eve::nan (as()), eve::nan(as())), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::nan (as()), eve::one(as()))), c_t(eve::nan (as()), eve::nan(as())), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::nan (as()), eve::nan(as()))), c_t(eve::nan (as()), eve::nan(as())), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::one (as()), -eve::inf (as()))), c_t(eve::nan(as()), eve::nan(as())), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::one (as()), -eve::nan (as()))), c_t(eve::nan(as()), eve::nan(as())), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::minf (as()), -eve::one (as()))), c_t(eve::zero(as())), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::minf (as()), -eve::mone(as()))), c_t(eve::zero(as())), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::inf (as()), -eve::one (as()))), c_t(eve::inf (as())*exp(c_t(eve::zero(as()), -eve::one (as())))), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::inf (as()), -eve::mone(as()))), c_t(eve::inf (as())*exp(c_t(eve::zero(as()), -eve::mone(as())))), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::minf (as()), -eve::inf(as()))), c_t(eve::zero(as())), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::inf (as()), -eve::inf(as()))), c_t(eve::nan (as()), -eve::nan(as())), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::minf (as()), -eve::nan(as()))), c_t(eve::zero(as())), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::inf (as()), -eve::nan(as()))), c_t(eve::nan (as()), -eve::nan(as())), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::nan (as()), -eve::one(as()))), c_t(eve::nan (as()), -eve::nan(as())), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::nan (as()), -eve::nan(as()))), c_t(eve::nan (as()), -eve::nan(as())), 0.5); + + TTS_ULP_EQUAL(exp(c_t(eve::mone(as()))), c_t(eve::one(as())/eve::euler(as())), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::one(as()))), c_t(eve::euler(as())), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::zero(as()))), c_t(eve::one(as())), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::zero(as()), eve::zero(as()))), c_t(eve::one(as())), 0.5); + TTS_ULP_EQUAL(exp(c_t(eve::mzero(as()), eve::zero(as()))), c_t(eve::one(as())), 0.5); + +}; diff --git a/old/complex_test/exp_i.cpp b/old/complex_test/exp_i.cpp new file mode 100644 index 00000000000..bbf70f628d8 --- /dev/null +++ b/old/complex_test/exp_i.cpp @@ -0,0 +1,57 @@ +//================================================================================================== +/** + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +**/ +//================================================================================================== +#include "test.hpp" +#include "measures.hpp" +#include +#include +#include +#include + +EVE_TEST( "Check behavior of exp_i on scalar" + , eve::test::scalar::ieee_reals + , eve::test::generate( eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using c_t = std::complex; + using z_t = eve::complex; + for(auto e : a0) + { + for(auto f : a1) + { + TTS_ULP_EQUAL(eve::exp_i(eve::complex(e, f)), z_t(std::exp(c_t(-f, e))), 2); + TTS_ULP_EQUAL(eve::exp_i(eve::complex(e, f)), z_t(std::exp(c_t(-f, e))), 2.0); + } + } +}; + +EVE_TEST( "Check behavior of exp_i on wide" + , eve::test::simd::ieee_reals + , eve::test::generate(eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using ce_t = eve::complex; + using z_t = eve::wide, typename T::cardinal_type>; + using c_t = std::complex; + auto std_ch = [](auto x, auto y){return std::exp(c_t(-y, x)); }; + auto init_with_std = [std_ch](auto a0, auto a1){ + z_t b; + for(int i = 0; i != eve::cardinal_v; ++i) + { + ce_t z(std_ch(a0.get(i), a1.get(i))); + b.set(i, z); + } + return b; + }; + TTS_ULP_EQUAL(eve::exp_i(z_t{a0,a1}), init_with_std(a0, a1), 2); +}; diff --git a/old/complex_test/exp_ipi.cpp b/old/complex_test/exp_ipi.cpp new file mode 100644 index 00000000000..a0af1d8798d --- /dev/null +++ b/old/complex_test/exp_ipi.cpp @@ -0,0 +1,60 @@ +//================================================================================================== +/** + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +**/ +//================================================================================================== +#include "test.hpp" +#include "measures.hpp" +#include +#include +#include +#include + +EVE_TEST( "Check behavior of exp_ipi on scalar" + , eve::test::scalar::ieee_reals + , eve::test::generate( eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using c_t = std::complex; + using z_t = eve::complex; + using eve::as; + auto pis = eve::pi(as()); + for(auto e : a0) + { + for(auto f : a1) + { + TTS_ULP_EQUAL(eve::exp_ipi(eve::complex(e, f)), z_t(std::exp(c_t(-pis*f, pis*e))), 300.0); + TTS_ULP_EQUAL(eve::exp_ipi(eve::complex(e, f)), z_t(std::exp(c_t(-pis*f, pis*e))), 300.0); + } + } +}; + +EVE_TEST( "Check behavior of exp_ipi on wide" + , eve::test::simd::ieee_reals + , eve::test::generate(eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using ce_t = eve::complex; + using z_t = eve::wide, typename T::cardinal_type>; + using c_t = std::complex; + auto pis = eve::pi(eve::as()); + auto std_ch = [pis](auto x, auto y){return std::exp(c_t(-pis*y, pis*x)); }; + auto init_with_std = [std_ch](auto a0, auto a1){ + z_t b; + for(int i = 0; i != eve::cardinal_v; ++i) + { + ce_t z(std_ch(a0.get(i), a1.get(i))); + b.set(i, z); + } + return b; + }; + TTS_ULP_EQUAL(eve::exp_ipi(z_t{a0,a1}), init_with_std(a0, a1), 300.0); +}; diff --git a/old/complex_test/log.cpp b/old/complex_test/log.cpp new file mode 100644 index 00000000000..c8373fc3c1e --- /dev/null +++ b/old/complex_test/log.cpp @@ -0,0 +1,108 @@ +//================================================================================================== +/** + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +**/ +//================================================================================================== +#include "test.hpp" +#include "measures.hpp" +#include +#include +#include +#include + +EVE_TEST( "Check behavior of log on scalar" + , eve::test::scalar::ieee_reals + , eve::test::generate( eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using c_t = std::complex; + using z_t = eve::complex; + for(auto e : a0) + { + for(auto f : a1) + { + TTS_ULP_EQUAL(eve::log(eve::complex(e, f)), z_t(std::log(c_t(e, f))), 2); + TTS_ULP_EQUAL(eve::log(eve::complex(e, f)), z_t(std::log(c_t(e, f))), 2.0); + } + } +}; + +EVE_TEST( "Check behavior of log on wide" + , eve::test::simd::ieee_reals + , eve::test::generate(eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using ce_t = eve::complex; + using z_t = eve::wide, typename T::cardinal_type>; + using c_t = std::complex; + auto std_ch = [](auto x, auto y){return std::log(c_t(x, y)); }; + auto init_with_std = [std_ch](auto a0, auto a1){ + z_t b; + for(int i = 0; i != eve::cardinal_v; ++i) + { + ce_t z(std_ch(a0.get(i), a1.get(i))); + b.set(i, z); + } + return b; + }; + TTS_ULP_EQUAL(eve::log(z_t{a0,a1}), init_with_std(a0, a1), 2); +}; + +EVE_TEST_TYPES( "Check return types of eve::log", eve::test::scalar::ieee_reals) + (eve::as) +{ + using eve::as; + using e_t = eve::element_type_t; + using c_t = eve::complex; + + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::minf (as()), eve::mone(as()))), c_t(eve::inf(as()), -eve::pi(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::inf(as()), 0)), c_t(eve::inf(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::minf(as()), 0)), c_t(eve::inf(as()), eve::pi(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::nan(as()), eve::nan(as()))), c_t(eve::nan(as()), eve::nan(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::inf (as()), eve::zero(as()))), c_t(eve::inf(as()), eve::zero(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::minf (as()), eve::zero(as()))), c_t(eve::inf(as()), eve::pi(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::inf (as()), eve::zero(as()))), c_t(eve::inf (as()), eve::zero (as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::one (as()), eve::inf (as()))), c_t(eve::inf(as()), eve::pio_2(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::one (as()), eve::nan (as()))), c_t(eve::nan(as()), eve::nan(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::inf (as()), eve::one (as()))), c_t(eve::inf(as()), eve::zero(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::minf (as()), eve::one(as()))), c_t(eve::inf(as()), eve::pi(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::inf (as()), eve::one (as()))), c_t(eve::inf (as()), eve::zero (as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::nan (as()), eve::one(as()))), c_t(eve::nan (as()), eve::nan(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::nan (as()), eve::mone(as()))), c_t(eve::nan (as()), eve::nan(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::nan (as()), eve::nan(as()))), c_t(eve::nan (as()), eve::nan(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::one (as()), -eve::inf (as()))), c_t(eve::inf(as()), -eve::pio_2(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::one (as()), -eve::nan (as()))), c_t(eve::nan(as()), -eve::nan(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::inf (as()), -eve::one (as()))), c_t(eve::inf(as()), -eve::zero(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::minf (as()), -eve::one(as()))), c_t(eve::inf(as()), -eve::pi(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::inf (as()), -eve::one (as()))), c_t(eve::inf (as()), -eve::zero (as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::nan (as()), -eve::one(as()))), c_t(eve::nan (as()), -eve::nan(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::nan (as()), -eve::mone(as()))), c_t(eve::nan (as()), -eve::nan(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::nan (as()), -eve::nan(as()))), c_t(eve::nan (as()), -eve::nan(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::nan(as()), eve::zero(as()))), c_t(eve::nan(as()), eve::nan(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::zero(as()))), c_t(eve::minf(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::zero(as()), eve::zero(as()))), c_t(eve::minf(as()), eve::zero(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::minf (as()), eve::inf(as()))), c_t(eve::inf (as()), 3*eve::pio_4(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::inf (as()), eve::inf(as()))), c_t(eve::inf (as()), eve::pi(as())/4), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::minf (as()), -eve::inf(as()))), c_t(eve::inf (as()), -3*eve::pio_4(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::inf (as()), -eve::inf(as()))), c_t(eve::inf (as()), -eve::pi(as())/4), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::mzero(as()))), c_t(eve::minf(as()), eve::pi(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::nan (as()), eve::inf(as()))), c_t(eve::inf (as()), eve::nan(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::nan (as()), -eve::inf(as()))), c_t(eve::inf (as()), -eve::nan(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::minf (as()), eve::nan(as()))), c_t(eve::inf (as()), eve::nan(as())), 0.5); + + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::mone(as()))), c_t(eve::zero(as()), eve::pi(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::one(as()))), c_t(eve::zero(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log)(c_t(eve::zero(as()), eve::one(as()))),c_t(eve::zero(as()), eve::pio_2(as())), 0.5); + + TTS_ULP_EQUAL(eve::log(c_t(-4)), c_t(eve::log(T(4)), eve::pi(as())), 0); + TTS_ULP_EQUAL(eve::log(T(-4)), eve::nan(as()), 0); + TTS_ULP_EQUAL(eve::cmplx(eve::log)(T(-4)), c_t(eve::log(T(4)), eve::pi(as())), 0); +}; diff --git a/old/complex_test/log10.cpp b/old/complex_test/log10.cpp new file mode 100644 index 00000000000..ef9058da011 --- /dev/null +++ b/old/complex_test/log10.cpp @@ -0,0 +1,111 @@ +//================================================================================================== +/** + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +**/ +//================================================================================================== +#include "test.hpp" +#include "measures.hpp" +#include +#include +#include +#include + +EVE_TEST( "Check behavior of log10 on scalar" + , eve::test::scalar::ieee_reals + , eve::test::generate( eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using c_t = std::complex; + using z_t = eve::complex; + for(auto e : a0) + { + for(auto f : a1) + { + TTS_ULP_EQUAL(eve::log10(eve::complex(e, f)), z_t(std::log10(c_t(e, f))), 2); + TTS_ULP_EQUAL(eve::log10(eve::complex(e, f)), z_t(std::log10(c_t(e, f))), 2.0); + } + } +}; + +EVE_TEST( "Check behavior of log10 on wide" + , eve::test::simd::ieee_reals + , eve::test::generate(eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using ce_t = eve::complex; + using z_t = eve::wide, typename T::cardinal_type>; + using c_t = std::complex; + auto std_ch = [](auto x, auto y){return std::log10(c_t(x, y)); }; + auto init_with_std = [std_ch](auto a0, auto a1){ + z_t b; + for(int i = 0; i != eve::cardinal_v; ++i) + { + ce_t z(std_ch(a0.get(i), a1.get(i))); + b.set(i, z); + } + return b; + }; + TTS_ULP_EQUAL(eve::log10(z_t{a0,a1}), init_with_std(a0, a1), 2); +}; + +EVE_TEST_TYPES( "Check return types of eve::log10", eve::test::scalar::ieee_reals) + (eve::as) +{ + using eve::as; + using e_t = eve::element_type_t; + using c_t = eve::complex; + auto mypi = eve::pi(as())*eve::invlog_10(as()); + auto mypio4 = eve::pio_4(as())*eve::invlog_10(as()); + auto mypio2 = eve::pio_2(as())*eve::invlog_10(as()); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::minf (as()), eve::mone(as()))), c_t(eve::inf(as()), -mypi), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::inf(as()), 0)), c_t(eve::inf(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::minf(as()), 0)), c_t(eve::inf(as()), mypi), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::nan(as()), eve::nan(as()))), c_t(eve::nan(as()), eve::nan(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::inf (as()), eve::zero(as()))), c_t(eve::inf(as()), eve::zero(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::minf (as()), eve::zero(as()))), c_t(eve::inf(as()), mypi), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::inf (as()), eve::zero(as()))), c_t(eve::inf (as()), eve::zero (as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::one (as()), eve::inf (as()))), c_t(eve::inf(as()), mypio2), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::one (as()), eve::nan (as()))), c_t(eve::nan(as()), eve::nan(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::inf (as()), eve::one (as()))), c_t(eve::inf(as()), eve::zero(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::minf (as()), eve::one(as()))), c_t(eve::inf(as()), mypi), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::inf (as()), eve::one (as()))), c_t(eve::inf (as()), eve::zero (as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::nan (as()), eve::one(as()))), c_t(eve::nan (as()), eve::nan(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::nan (as()), eve::mone(as()))), c_t(eve::nan (as()), eve::nan(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::nan (as()), eve::nan(as()))), c_t(eve::nan (as()), eve::nan(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::one (as()), -eve::inf (as()))), c_t(eve::inf(as()), -mypio2), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::one (as()), -eve::nan (as()))), c_t(eve::nan(as()), -eve::nan(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::inf (as()), -eve::one (as()))), c_t(eve::inf(as()), -eve::zero(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::minf (as()), -eve::one(as()))), c_t(eve::inf(as()), -mypi), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::inf (as()), -eve::one (as()))), c_t(eve::inf (as()), -eve::zero (as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::nan (as()), -eve::one(as()))), c_t(eve::nan (as()), -eve::nan(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::nan (as()), -eve::mone(as()))), c_t(eve::nan (as()), -eve::nan(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::nan (as()), -eve::nan(as()))), c_t(eve::nan (as()), -eve::nan(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::nan(as()), eve::zero(as()))), c_t(eve::nan(as()), eve::nan(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::zero(as()))), c_t(eve::minf(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::zero(as()), eve::zero(as()))), c_t(eve::minf(as()), eve::zero(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::minf (as()), eve::inf(as()))), c_t(eve::inf (as()), 3*mypio4), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::inf (as()), eve::inf(as()))), c_t(eve::inf (as()), mypi/4), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::minf (as()), -eve::inf(as()))), c_t(eve::inf (as()), -3*mypio4), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::inf (as()), -eve::inf(as()))), c_t(eve::inf (as()), -mypi/4), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::mzero(as()))), c_t(eve::minf(as()), mypi), 0.5); + + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::nan (as()), eve::inf(as()))), c_t(eve::inf (as()), eve::nan(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::nan (as()), -eve::inf(as()))), c_t(eve::inf (as()), -eve::nan(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::minf (as()), eve::nan(as()))), c_t(eve::inf (as()), eve::nan(as())), 0.5); + + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::mone(as()))), c_t(eve::zero(as()), mypi), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::one(as()))), c_t(eve::zero(as())), 0.5); + TTS_ULP_EQUAL(eve::pedantic(eve::log10)(c_t(eve::zero(as()), eve::one(as()))),c_t(eve::zero(as()), mypio2), 0.5); + + TTS_ULP_EQUAL(eve::log10(c_t(-100)), c_t(T(2), T(1.364376353841841)), 0.5); + TTS_ULP_EQUAL(eve::log10(T(-4)), eve::nan(as()), 0); + TTS_ULP_EQUAL(eve::cmplx(eve::log10)(T(-100)), c_t(T(2), T(1.364376353841841)), 0.5); +}; diff --git a/old/complex_test/log_abs.cpp b/old/complex_test/log_abs.cpp new file mode 100644 index 00000000000..b02179ecbd5 --- /dev/null +++ b/old/complex_test/log_abs.cpp @@ -0,0 +1,43 @@ +//================================================================================================== +/** + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +**/ +//================================================================================================== +#include "test.hpp" +#include + +auto vmin = -1000.0; +auto vmax = 1000.0; + +EVE_TEST( "Check behavior of log_abs on scalar" + , eve::test::scalar::ieee_reals + , eve::test::generate(eve::test::randoms(vmin, vmax) + , eve::test::randoms(vmin, vmax)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + for(auto e : a0) + { + for(auto f : a1) + { + TTS_EQUAL( eve::log_abs(eve::complex(e, f)), eve::log(eve::abs(eve::complex{e,f}) )); + } + } +}; + +EVE_TEST( "Check behavior of log_abs on wide" + , eve::test::simd::ieee_reals + , eve::test::generate(eve::test::randoms(vmin, vmax) + , eve::test::randoms(vmin, vmax)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using z_t = eve::wide, typename T::cardinal_type>; + + TTS_EQUAL( eve::log_abs(z_t{a0,a1}), eve::log(eve::abs(z_t{a0,a1})) ); + TTS_EQUAL( eve::pedantic(eve::log_abs)(z_t{a0,a1}), eve::pedantic(eve::log)(eve::abs(z_t{a0,a1})) ); +}; diff --git a/old/complex_test/mul.cpp b/old/complex_test/mul.cpp new file mode 100644 index 00000000000..15f10bbdcbf --- /dev/null +++ b/old/complex_test/mul.cpp @@ -0,0 +1,47 @@ +//================================================================================================== +/** + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +**/ +//================================================================================================== +#include "test.hpp" +#include "measures.hpp" +#include +#include + +EVE_TEST_TYPES( "Check complex::operator*", eve::test::scalar::ieee_reals) +(eve::as) +{ + using w_t = eve::wide; + std::complex c_s1(T{1}, T{5}), c_s2(T{2}, T{1}), c_m(T{-3}, T{11}); + eve::complex z_s1(c_s1), z_s2(c_s2), z_m(c_m); + TTS_EQUAL(std::real(c_s1*c_s2), std::real(c_m)); + TTS_EQUAL(std::imag(c_s1*c_s2), std::imag(c_m)); + + TTS_EQUAL(eve::real(z_s1*z_s2), eve::real(z_m)); + TTS_EQUAL(eve::imag(z_s1*z_s2), eve::imag(z_m)); + + auto fill_r = [](auto e, auto) { return T(1+e); }; + auto fill_i = [](auto e, auto) { return T(1)/T(1+3*e); }; + auto fill_r1 = [](auto e, auto) { return T(1-e/2); }; + auto fill_i1 = [](auto e, auto) { return T(-1+3.5*e); }; + + using w_t = eve::wide; + using cw_t = eve::wide>; + w_t wr(fill_r); + w_t wi(fill_i); + w_t wr1(fill_r1); + w_t wi1(fill_i1); + + eve::wide> z(wr, wi); + eve::wide> zbar(wr, -wi); + eve::wide> z1(wr1, wi1); + auto std_mul = [](eve::complex a, eve::complex b) -> eve::complex { + return std::complex(eve::real(a), eve::imag(a))*std::complex(eve::real(b), eve::imag(b)); + }; + auto my_mul = [std_mul](cw_t a, cw_t b) -> cw_t { return map(std_mul, a, b); }; + TTS_ULP_EQUAL(z*zbar, my_mul(z, zbar), 0.5); + TTS_ULP_EQUAL( z*zbar, my_mul(z, zbar), 0.5); + TTS_ULP_EQUAL(z*z1, my_mul(z, z1), 0.5); +}; diff --git a/old/complex_test/mul_i.cpp b/old/complex_test/mul_i.cpp new file mode 100644 index 00000000000..360a4cf353d --- /dev/null +++ b/old/complex_test/mul_i.cpp @@ -0,0 +1,48 @@ +//================================================================================================== +/** + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +**/ +//================================================================================================== +#include "test.hpp" +#include "measures.hpp" +#include +#include +#include +#include + +EVE_TEST( "Check behavior of mul_i on scalar" + , eve::test::scalar::ieee_reals + , eve::test::generate( eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using z_t = eve::complex; + for(auto e : a0) + { + for(auto f : a1) + { + TTS_ULP_EQUAL(eve::mul_i(z_t(e, f)), z_t(-f, e), 2); + TTS_ULP_EQUAL(eve::mul_i(z_t(e, f)), z_t(-f, e), 2.0); + } + } +}; + +EVE_TEST( "Check behavior of mul_i on wide" + , eve::test::simd::ieee_reals + , eve::test::generate(eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using z_t = eve::wide, typename T::cardinal_type>; + TTS_ULP_EQUAL(eve::mul_i(z_t{a0,a1}), z_t(-a1, a0), 0); + TTS_ULP_EQUAL(eve::mul(z_t(a0,a1), eve::i), z_t(-a1, a0), 0); + TTS_ULP_EQUAL(eve::mul(eve::i, z_t(a0,a1)), z_t(-a1, a0), 0); + TTS_ULP_EQUAL( eve::i* z_t(a0,a1) , z_t(-a1, a0), 0); + TTS_ULP_EQUAL(z_t(a0,a1)*eve::i, z_t(-a1, a0), 0); +}; diff --git a/old/complex_test/mul_mi.cpp b/old/complex_test/mul_mi.cpp new file mode 100644 index 00000000000..4289a5213c7 --- /dev/null +++ b/old/complex_test/mul_mi.cpp @@ -0,0 +1,44 @@ +//================================================================================================== +/** + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +**/ +//================================================================================================== +#include "test.hpp" +#include "measures.hpp" +#include +#include +#include +#include + +EVE_TEST( "Check behavior of mul_mi on scalar" + , eve::test::scalar::ieee_reals + , eve::test::generate( eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using z_t = eve::complex; + for(auto e : a0) + { + for(auto f : a1) + { + TTS_ULP_EQUAL(eve::mul_mi(eve::complex(e, f)), z_t(f, -e), 2); + TTS_ULP_EQUAL(eve::mul_mi(eve::complex(e, f)), z_t(f, -e), 2.0); + } + } +}; + +EVE_TEST( "Check behavior of mul_mi on wide" + , eve::test::simd::ieee_reals + , eve::test::generate(eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using z_t = eve::wide, typename T::cardinal_type>; + TTS_ULP_EQUAL(eve::mul_mi(z_t{a0,a1}), z_t(a1, -a0), 2); +}; diff --git a/old/complex_test/polar.cpp b/old/complex_test/polar.cpp new file mode 100644 index 00000000000..c55fc6f59e0 --- /dev/null +++ b/old/complex_test/polar.cpp @@ -0,0 +1,43 @@ +//================================================================================================== +/** + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +**/ +//================================================================================================== +#include "test.hpp" +#include +#include + +EVE_TEST( "Check behavior of polar on scalar" + , eve::test::scalar::ieee_reals + , eve::test::generate(eve::test::randoms(eve::zero, eve::valmax) + , eve::test::randoms(eve::zero, eve::valmax)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using z_t = eve::complex; + for(auto e : a0) + { + for(auto f : a1) + { + auto [s, c] = eve::sincos(f); + TTS_EQUAL( eve::polar(e, f), eve::mul(z_t(c, s), e) ); + } + } +}; + +EVE_TEST( "Check behavior of polar on wide" + , eve::test::simd::ieee_reals + , eve::test::generate(eve::test::randoms(eve::valmin, eve::valmax) + , eve::test::randoms(eve::valmin, eve::valmax)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + auto [s, c] = eve::sincos(a1); + using z_t = eve::wide, typename T::cardinal_type>; + + TTS_EQUAL( eve::polar(a0,a1), eve::mul(z_t(c, s), a0) ); +}; diff --git a/old/complex_test/pow.cpp b/old/complex_test/pow.cpp new file mode 100644 index 00000000000..ba3c056554e --- /dev/null +++ b/old/complex_test/pow.cpp @@ -0,0 +1,57 @@ +//================================================================================================== +/** + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +**/ +//================================================================================================== +#include "test.hpp" +#include "measures.hpp" +#include +#include +#include + +EVE_TEST( "Check behavior of pow on scalar" + , eve::test::scalar::ieee_reals + , eve::test::generate( eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1, T const& a2, T const& a3 ) +{ + using e_t = typename T::value_type; + using c_t = eve::complex; + for(auto e : a0) + { + for(auto f : a1) + { + for(auto g : a2) + { + for(auto h : a3) + { + auto evep = eve::pow(c_t(e, f), c_t(g, h)); + auto stdpd = std::pow(std::complex(e, f), std::complex(g, h)); + auto stdp = c_t(stdpd.real(), stdpd.imag()); + TTS_ULP_EQUAL( evep, stdp, 2.0e6); + } + } + } + } +}; + +EVE_TEST( "Check behavior of pow on wide" + , eve::test::simd::ieee_reals + , eve::test::generate( eve::test::randoms(-1, 1) + , eve::test::randoms(-1, 1) + , eve::test::randoms(-1, 1) + , eve::test::randoms(-1, 1)) + ) + (T const& a0, T const& a1, T const& a2, T const& a3) +{ + using e_t = typename T::value_type; + using c_t = eve::complex; + using z_t = eve::wide; +// std::cout << z_t{a0,a1} << " " << z_t{a2,a3} << std::endl; + TTS_ULP_EQUAL( eve::pow(z_t{a0,a1}, z_t{a2,a3}), eve::exp(eve::mul(eve::log(z_t{a0,a1}), z_t{a2,a3}) ), 2.0e5); +}; diff --git a/old/complex_test/rec.cpp b/old/complex_test/rec.cpp new file mode 100644 index 00000000000..4f61e1db858 --- /dev/null +++ b/old/complex_test/rec.cpp @@ -0,0 +1,48 @@ +//================================================================================================== +/** + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +**/ +//================================================================================================== +#include "test.hpp" +#include "measures.hpp" +#include +#include + +auto vmin = -1000.0; +auto vmax = 1000.0; + +EVE_TEST( "Check behavior of rec on scalar" + , eve::test::scalar::ieee_reals + , eve::test::generate(eve::test::randoms(vmin, vmax) + , eve::test::randoms(vmin, vmax)) + ) +(T const& a0, T const & a1) +{ + using e_t = typename T::value_type; + using c_t = eve::complex; + for(auto e : a0) + { + TTS_EQUAL( eve::rec(e), e_t(1)/e ); + for(auto f : a1) + { + auto z1= c_t(e, f); + TTS_ULP_EQUAL( eve::rec(z1), c_t(1)/z1, 2.0); + } + } +}; + + +EVE_TEST( "Check behavior of rec on wide" + , eve::test::simd::ieee_reals + , eve::test::generate(eve::test::randoms(vmin, vmax) + , eve::test::randoms(vmin, vmax)) + ) +(T const& a0, T const & a1 ) +{ + using e_t = typename T::value_type; + using z_t = eve::wide, typename T::cardinal_type>; + + TTS_ULP_EQUAL( eve::rec(z_t{a0,a1}), (z_t(1)/(z_t{a0,a1})), 2.0); +}; diff --git a/old/complex_test/sin.cpp b/old/complex_test/sin.cpp new file mode 100644 index 00000000000..3b350a07501 --- /dev/null +++ b/old/complex_test/sin.cpp @@ -0,0 +1,125 @@ +//================================================================================================== +/** + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +**/ +//================================================================================================== +#include "test.hpp" +#include "measures.hpp" +#include +#include +#include +#include + +EVE_TEST( "Check behavior of sin on scalar" + , eve::test::scalar::ieee_reals + , eve::test::generate( eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using c_t = std::complex; + using z_t = eve::complex; + for(auto e : a0) + { + for(auto f : a1) + { + std::cout << "e = " << e << " f = " << f << std::endl; + TTS_ULP_EQUAL(eve::sin(eve::complex(e, f)), z_t(std::sin(c_t(e, f))), 2); + TTS_ULP_EQUAL(eve::pedantic(eve::sin)(eve::complex(e, f)), z_t(std::sin(c_t(e, f))), 2); + TTS_ULP_EQUAL(eve::sin(eve::complex(e, f)), z_t(std::sin(c_t(e, f))), 2.0); + } + } +}; + +EVE_TEST( "Check behavior of sin on wide" + , eve::test::simd::ieee_reals + , eve::test::generate(eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using ce_t = eve::complex; + using z_t = eve::wide, typename T::cardinal_type>; + using c_t = std::complex; + auto std_ch = [](auto x, auto y){return std::sin(c_t(x, y)); }; + auto init_with_std = [std_ch](auto a0, auto a1){ + z_t b; + for(int i = 0; i != eve::cardinal_v; ++i) + { + ce_t z(std_ch(a0.get(i), a1.get(i))); + b.set(i, z); + } + return b; + }; + TTS_ULP_EQUAL(eve::sin(z_t{a0,a1}), init_with_std(a0, a1), 2); +}; + + +EVE_TEST( "Check behavior of pedantic(sin) on wide" + , eve::test::simd::ieee_reals + , eve::test::generate(eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using ce_t = eve::complex; + using z_t = eve::wide, typename T::cardinal_type>; + using c_t = std::complex; + z_t b; + for(int i = 0; i != eve::cardinal_v; ++i) + { + ce_t z(std::sin(c_t(a0.get(i), a1.get(i)))); + b.set(i, z); + } + TTS_ULP_EQUAL(eve::pedantic(eve::sin)(z_t{a0,a1}), b, 2.0); +}; + +EVE_TEST_TYPES( "Check return types of eve::abs", eve::test::scalar::ieee_reals) + (eve::as) +{ + using e_t = eve::element_type_t; + using c_t = eve::complex; + using eve::as; + const int N = 24; + e_t pid = eve::downward(eve::pi)(as()); // nearest pi representation less than mathematical pi + e_t piu = eve::upward(eve::pi)(as()); // nearest pi representation greater than mathematical pi + std::array inputs = + { c_t(eve::zero(as()),eve::zero(as())),//0 + c_t(eve::inf(as()),eve::zero(as())), //1 + c_t(eve::minf(as()),eve::zero(as())),//2 + c_t(eve::nan(as()),eve::zero(as())), //3 + c_t(eve::zero(as()),eve::inf(as())), //4 + c_t(eve::inf(as()),eve::inf(as())), //5 + c_t(eve::minf(as()),eve::inf(as())), //6 + c_t(eve::nan(as()),eve::inf(as())), //7 + c_t(eve::zero(as()),eve::minf(as())),//8 + c_t(eve::inf(as()),eve::minf(as())), //9 + c_t(eve::minf(as()),eve::minf(as())),//10 + c_t(eve::nan(as()),eve::minf(as())), //11 + c_t(eve::zero(as()),eve::nan(as())), //12 + c_t(eve::inf(as()),eve::nan(as())), //13 + c_t(eve::minf(as()),eve::nan(as())), //14 + c_t(eve::nan(as()),eve::nan(as())), //15 + c_t(eve::zero(as()),pid), //16 + c_t(eve::inf(as()),pid), //17 + c_t(eve::minf(as()),pid), //18 + c_t(eve::nan(as()),pid), //19 + c_t(eve::zero(as()),piu), //20 + c_t(eve::inf(as()),piu), //21 + c_t(eve::minf(as()),piu), //22 + c_t(eve::nan(as()),piu), //23 + }; + + auto sine = eve::pedantic(eve::sin); + auto tsine= [](auto z){return eve::mul_mi(eve::pedantic(eve::sinh)(eve::mul_i(z)));}; + for(int i=0; i < N; ++i) + { + TTS_IEEE_EQUAL(sine(-inputs[i]), -sine(inputs[i])); + TTS_IEEE_EQUAL(sine(inputs[i]), tsine(inputs[i])); + } +}; diff --git a/old/complex_test/sinh.cpp b/old/complex_test/sinh.cpp new file mode 100644 index 00000000000..4b86a723db7 --- /dev/null +++ b/old/complex_test/sinh.cpp @@ -0,0 +1,113 @@ +//================================================================================================== +/** + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +**/ +//================================================================================================== +#include "test.hpp" +#include "measures.hpp" +#include +#include +#include +#include + +EVE_TEST( "Check behavior of sinh on scalar" + , eve::test::scalar::ieee_reals + , eve::test::generate( eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using c_t = std::complex; + using z_t = eve::complex; + for(auto e : a0) + { + for(auto f : a1) + { + std::cout << "e = " << e << " f = " << f << std::endl; + TTS_ULP_EQUAL(eve::sinh(eve::complex(e, f)), z_t(std::sinh(c_t(e, f))), 2); + TTS_ULP_EQUAL(eve::pedantic(eve::sinh)(eve::complex(e, f)), z_t(std::sinh(c_t(e, f))), 2); + TTS_ULP_EQUAL(eve::sinh(eve::complex(e, f)), z_t(std::sinh(c_t(e, f))), 2.0); + } + } +}; + +EVE_TEST( "Check behavior of sinh on wide" + , eve::test::simd::ieee_reals + , eve::test::generate(eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using ce_t = eve::complex; + using z_t = eve::wide, typename T::cardinal_type>; + using c_t = std::complex; + auto std_ch = [](auto x, auto y){return std::sinh(c_t(x, y)); }; + auto init_with_std = [std_ch](auto a0, auto a1){ + z_t b; + for(int i = 0; i != eve::cardinal_v; ++i) + { + ce_t z(std_ch(a0.get(i), a1.get(i))); + b.set(i, z); + } + return b; + }; + TTS_ULP_EQUAL(eve::sinh(z_t{a0,a1}), init_with_std(a0, a1), 2); +}; + + +EVE_TEST( "Check behavior of pedantic(sinh) on wide" + , eve::test::simd::ieee_reals + , eve::test::generate(eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using ce_t = eve::complex; + using z_t = eve::wide, typename T::cardinal_type>; + using c_t = std::complex; + z_t b; + for(int i = 0; i != eve::cardinal_v; ++i) + { + ce_t z(std::sinh(c_t(a0.get(i), a1.get(i)))); + b.set(i, z); + } + TTS_ULP_EQUAL(eve::pedantic(eve::sinh)(z_t{a0,a1}), b, 2.0); +}; + +EVE_TEST_TYPES( "Check return types of eve::abs", eve::test::scalar::ieee_reals) + (eve::as) +{ + using e_t = eve::element_type_t; + using c_t = eve::complex; + using eve::as; + + const int N = 21; + std::array inputs = + { c_t(eve::zero(as()),eve::zero(as())),c_t(eve::inf(as()),eve::zero(as())),c_t(eve::minf(as()),eve::zero(as())),c_t(eve::nan(as()),eve::zero(as())), + c_t(eve::zero(as()),eve::inf(as())), c_t(eve::inf(as()),eve::inf(as())), c_t(eve::minf(as()),eve::inf(as())), c_t(eve::nan(as()),eve::inf(as())), + c_t(eve::zero(as()),eve::minf(as())),c_t(eve::inf(as()),eve::minf(as())),c_t(eve::minf(as()),eve::minf(as())),c_t(eve::nan(as()),eve::minf(as())), + c_t(eve::zero(as()),eve::nan(as())), c_t(eve::inf(as()),eve::nan(as())), c_t(eve::minf(as()),eve::nan(as())), c_t(eve::nan(as()),eve::nan(as())), + c_t(eve::nan(as()),eve::zero(as())), c_t(eve::one(as()),eve::nan(as())), + c_t(eve::one(as()),eve::inf(as())), c_t(eve::nan(as()),eve::one(as())), c_t(eve::inf(as()),eve::one(as())) + }; + + std::array results = + { c_t(eve::zero(as()),eve::zero(as())),c_t(eve::inf(as()),eve::zero(as())),c_t(eve::minf(as()),eve::zero(as())),c_t(eve::nan(as()),eve::zero(as())), + c_t(eve::zero(as()),eve::nan(as())),c_t(eve::inf(as()),eve::nan(as())), c_t(eve::minf(as()),eve::nan(as())), c_t(eve::nan(as()),eve::nan(as())), + c_t(eve::zero(as()),eve::nan(as())),c_t(eve::inf(as()),eve::nan(as())), c_t(eve::minf(as()),eve::nan(as())), c_t(eve::nan(as()),eve::nan(as())), + c_t(eve::zero(as()),eve::nan(as())), c_t(eve::inf(as()),eve::nan(as())), c_t(eve::minf(as()),eve::nan(as())),c_t(eve::nan(as()),eve::nan(as())), + c_t(eve::nan(as()),eve::zero(as())),c_t(eve::nan(as()),eve::nan(as())), + c_t(eve::nan(as()),eve::nan(as())), c_t(eve::nan(as()),eve::nan(as())), c_t(eve::inf(as()),eve::inf(as())) + }; + + for(int i=0; i < N; i++) + { + TTS_ULP_EQUAL(eve::pedantic(eve::sinh)(inputs[i]), results[i], 1); + TTS_ULP_EQUAL(eve::pedantic(eve::sinh)(-inputs[i]), -results[i], 1); + } +}; diff --git a/old/complex_test/sqr.cpp b/old/complex_test/sqr.cpp new file mode 100644 index 00000000000..f4a6414a091 --- /dev/null +++ b/old/complex_test/sqr.cpp @@ -0,0 +1,42 @@ +//================================================================================================== +/** + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +**/ +//================================================================================================== +#include "test.hpp" +#include +#include +#include "measures.hpp" + +EVE_TEST( "Check behavior of sqr on scalar" + , eve::test::scalar::ieee_reals + , eve::test::generate ( eve::test::randoms(-1000.0, 1000.0) + , eve::test::randoms(-1000.0, 1000.0) + ) + ) +(T const& a0, T const & a1) +{ + for(auto e : a0) + { + TTS_EQUAL( eve::sqr(e), e*e ); + for(auto f : a1) + { + auto z1= eve::complex(e, f); + TTS_ULP_EQUAL( eve::sqr(z1), z1*z1, 2.0); + } + } +}; + +EVE_TEST( "Check behavior of sqr on wide" + , eve::test::simd::ieee_reals + , eve::test::generate ( eve::test::randoms(-1000.0, 1000.0) + , eve::test::randoms(-1000.0, 1000.0) + ) + ) +(T const& a0, T const & a1 ) +{ + using z_t = eve::as_complex_t; + TTS_ULP_EQUAL( eve::sqr(z_t{a0,a1}), (z_t{a0,a1} * z_t{a0,a1})/*eve::pedantic(eve::mul)(z_t{a0,a1}, z_t{a0,a1})*/, 2.0); +}; diff --git a/old/complex_test/sqr_abs.cpp b/old/complex_test/sqr_abs.cpp new file mode 100644 index 00000000000..8138c93e1fc --- /dev/null +++ b/old/complex_test/sqr_abs.cpp @@ -0,0 +1,42 @@ +//================================================================================================== +/** + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +**/ +//================================================================================================== +#include "test.hpp" +#include + +auto vmin = -1000.0; +auto vmax = 1000.0; + +EVE_TEST( "Check behavior of sqr_abs on scalar" + , eve::test::scalar::ieee_reals + , eve::test::generate(eve::test::randoms(vmin, vmax) + , eve::test::randoms(vmin, vmax)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + for(auto e : a0) + { + for(auto f : a1) + { + TTS_EQUAL( eve::sqr_abs(eve::complex(e, f)), eve::sum_of_prod(e, e, f, f) ); + } + } +}; + +EVE_TEST( "Check behavior of sqr_abs on wide" + , eve::test::simd::ieee_reals + , eve::test::generate(eve::test::randoms(vmin, vmax) + , eve::test::randoms(vmin, vmax)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using z_t = eve::wide, typename T::cardinal_type>; + + TTS_EQUAL( eve::sqr_abs(z_t{a0,a1}), eve::sum_of_prod(a0, a0, a1, a1) ); +}; diff --git a/old/complex_test/sqrt.cpp b/old/complex_test/sqrt.cpp new file mode 100644 index 00000000000..4947f42f07b --- /dev/null +++ b/old/complex_test/sqrt.cpp @@ -0,0 +1,151 @@ +//================================================================================================== +/** + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +**/ +//================================================================================================== +#include "test.hpp" +#include "measures.hpp" +#include +#include +#include +#include + +EVE_TEST( "Check behavior of sqrt on scalar" + , eve::test::scalar::ieee_reals + , eve::test::generate( eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using c_t = std::complex; + using z_t = eve::complex; + for(auto e : a0) + { + for(auto f : a1) + { + TTS_ULP_EQUAL(eve::sqrt(eve::complex(e, f)), z_t(std::sqrt(c_t(e, f))), 2); +// TTS_ULP_EQUAL(eve::pedantic(eve::sqrt)(eve::complex(e, f)), z_t(std::sqrt(c_t(e, f))), 2); + TTS_ULP_EQUAL(eve::sqrt(eve::complex(e, f)), z_t(std::sqrt(c_t(e, f))), 2.0); + } + } +}; + +EVE_TEST( "Check behavior of sqrt on wide" + , eve::test::simd::ieee_reals + , eve::test::generate(eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using ce_t = eve::complex; + using z_t = eve::wide, typename T::cardinal_type>; + using c_t = std::complex; + auto std_ch = [](auto x, auto y){return std::sqrt(c_t(x, y)); }; + auto init_with_std = [std_ch](auto a0, auto a1){ + z_t b; + for(int i = 0; i != eve::cardinal_v; ++i) + { + ce_t z(std_ch(a0.get(i), a1.get(i))); + b.set(i, z); + } + return b; + }; + TTS_ULP_EQUAL(eve::sqrt(z_t{a0,a1}), init_with_std(a0, a1), 2); +}; + + +// EVE_TEST( "Check behavior of pedantic(sqrt) on wide" +// , eve::test::simd::ieee_reals +// , eve::test::generate(eve::test::randoms(-10, 10) +// , eve::test::randoms(-10, 10)) +// ) +// (T const& a0, T const& a1 ) +// { +// using e_t = typename T::value_type; +// using ce_t = eve::complex; +// using z_t = eve::wide, typename T::cardinal_type>; +// using c_t = std::complex; +// z_t b; +// for(int i = 0; i != eve::cardinal_v; ++i) +// { +// ce_t z(std::sqrt(c_t(a0.get(i), a1.get(i)))); +// b.set(i, z); +// } +// TTS_ULP_EQUAL(eve::pedantic(eve::sqrt)(z_t{a0,a1}), b, 2.0); +// }; + +EVE_TEST_TYPES( "Check return types of eve::sqrt", eve::test::scalar::ieee_reals) + (eve::as) +{ + using e_t = eve::element_type_t; + using c_t = eve::complex; + using eve::as; +// using sqt = eve::sqrt; + // specific values tests + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::inf(as()))), c_t(eve::inf(as())), 0.5); + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::minf(as()),eve::zero(as()))), c_t(eve::zero(as()),eve::inf(as())),0.5); + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::nan(as()),eve::nan(as()))),c_t(eve::nan(as()),eve::nan(as())),0.5); + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::inf(as()),eve::nan(as()))),c_t(eve::nan(as()),eve::nan(as())),0.5); + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::minf(as()))), c_t(0, eve::inf(as())),0.5); + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::nan (as()),eve::inf(as()))), c_t(eve::nan(as()),eve::nan(as())),0.5); + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::one(as()), eve::nan(as()))), c_t(eve::nan(as()),eve::nan(as())),0.5); + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::inf(as()), eve::nan(as()))), c_t(eve::nan(as()),eve::nan(as())),0.5); + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::minf(as()),eve::nan(as()))), c_t(eve::nan(as()),eve::nan(as())),0.5); + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::nan (as()),eve::nan(as()))), c_t(eve::nan(as()),eve::nan(as())),0.5); + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::minf(as()),eve::one(as()))), c_t(eve::zero(as()),eve::inf(as())),0.5); + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::minf(as()),eve::mone(as()))),c_t(eve::zero(as()),eve::minf(as())),0.5); + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::inf(as()),eve::nan(as()))), c_t(eve::nan(as()),eve::nan(as())),0.5); + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::nan(as()),eve::one(as()))), c_t(eve::nan(as()),eve::nan(as())),0.5); + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::nan(as()),eve::nan(as()))), c_t(eve::nan(as()),eve::nan(as())),0.5); + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::one(as()), -eve::nan(as()))), c_t(eve::nan(as()),-eve::nan(as())),0.5); + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::inf(as()), -eve::nan(as()))), c_t(eve::nan(as()),-eve::nan(as())),0.5); + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::minf(as()),-eve::nan(as()))), c_t(eve::nan(as()),-eve::nan(as())),0.5); + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::nan (as()),-eve::nan(as()))), c_t(eve::nan(as()),-eve::nan(as())),0.5); + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::minf(as()),-eve::one(as()))), c_t(eve::zero(as()),-eve::inf(as())),0.5); + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::minf(as()),-eve::mone(as()))),c_t(eve::zero(as()),-eve::minf(as())),0.5); + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::inf(as()), -eve::nan(as()))), c_t(eve::nan(as()),eve::nan(as())),0.5); + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::nan(as()), -eve::one(as()))), c_t(eve::nan(as()),-eve::nan(as())),0.5); + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::nan(as()), -eve::nan(as()))), c_t(eve::nan(as()),-eve::nan(as())),0.5); + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::nan (as()),-eve::inf(as()))), c_t(eve::nan(as()),-eve::nan(as())),0.5); + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::one(as()), eve::nan(as()))), c_t(eve::nan(as()),-eve::nan(as())),0.5); + + auto psqrt = eve::pedantic(eve::sqrt); + TTS_ULP_EQUAL(psqrt(c_t(eve::inf(as()),eve::inf(as()))),c_t(eve::inf(as()),eve::inf(as())),0.5); + TTS_ULP_EQUAL(psqrt(c_t(eve::zero(as()),eve::inf(as()))),c_t(eve::inf(as()),eve::inf(as())),0.5); + TTS_ULP_EQUAL(psqrt(c_t(eve::nan(as()),eve::zero(as()))), c_t(eve::nan(as()),eve::nan(as())),0.5); + TTS_ULP_EQUAL(psqrt(c_t(eve::one(as()), eve::inf(as()))), c_t(eve::inf(as()),eve::inf(as())),0.5); + TTS_ULP_EQUAL(psqrt(c_t(eve::inf(as()), eve::inf(as()))), c_t(eve::inf(as()),eve::inf(as())),0.5); + TTS_ULP_EQUAL(psqrt(c_t(eve::minf(as()),eve::inf(as()))), c_t(eve::inf(as()),eve::inf(as())),0.5); + TTS_ULP_EQUAL(psqrt(c_t(eve::inf(as()), -eve::inf(as()))), c_t(eve::inf(as()),-eve::inf(as())),0.5); + TTS_ULP_EQUAL(psqrt(c_t(eve::minf(as()),-eve::inf(as()))), c_t(eve::inf(as()),-eve::inf(as())),0.5); + TTS_ULP_EQUAL(psqrt(c_t(eve::one(as()),eve::nan(as()))), c_t(eve::nan(as()),eve::nan(as())),0.5); + TTS_ULP_EQUAL(psqrt(c_t(eve::one(as()),eve::zero(as()))), c_t(eve::one(as()),eve::zero(as())),0.5); + + + + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::one(as()), -eve::inf(as()))), c_t(eve::inf(as()),-eve::inf(as())),0.5); + + TTS_ULP_EQUAL(eve::sqrt(c_t(1)), c_t(1), 0); + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::mone(as()))), c_t(0, eve::one(as())),0.5); + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::one(as()))), c_t(eve::one(as())),0.5); + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::zero(as()))), c_t(eve::zero(as())),0.5); + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::zero(as()),eve::zero(as()))), c_t(eve::zero(as()),eve::zero(as())),0.5); + TTS_ULP_EQUAL(eve::sqrt(c_t(eve::mzero(as()),eve::zero(as()))),c_t(eve::zero(as()),eve::zero(as())),0.5); + TTS_ULP_EQUAL(eve::sqrt(c_t(0, 2)), c_t(1, 1), 1); + for(T i=-5; i <= T(5) ; i+= T(0.6)) + { + for(T j =-5; j < T(5); j+= T(0.5)) + { + std::cout << c_t(i, j) << std::endl; + TTS_ULP_EQUAL(eve::sqr(eve::sqrt(c_t(i, j))), c_t(i, j), 30.0); + } + } + TTS_ULP_EQUAL(eve::sqrt(c_t(-4)), c_t(0, 2), 0); + TTS_ULP_EQUAL(eve::sqrt(T(-4)), eve::nan(as()), 0); + TTS_ULP_EQUAL(eve::cmplx(eve::sqrt)(T(-4)), c_t(0, 2), 0); + +}; diff --git a/old/complex_test/tan.cpp b/old/complex_test/tan.cpp new file mode 100644 index 00000000000..6f3838b1ae6 --- /dev/null +++ b/old/complex_test/tan.cpp @@ -0,0 +1,104 @@ +//================================================================================================== +/** + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +**/ +//================================================================================================== +#include "test.hpp" +#include "measures.hpp" +#include +#include +#include +#include + +EVE_TEST( "Check behavior of tan on scalar" + , eve::test::scalar::ieee_reals + , eve::test::generate( eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using c_t = std::complex; + using z_t = eve::complex; + for(auto e : a0) + { + for(auto f : a1) + { + TTS_ULP_EQUAL(eve::tan(eve::complex(e, f)), z_t(std::tan(c_t(e, f))), 3.0); + TTS_ULP_EQUAL(eve::tan(eve::complex(e, f)), z_t(std::tan(c_t(e, f))), 3.0); + } + } +}; + +EVE_TEST( "Check behavior of tan on wide" + , eve::test::simd::ieee_reals + , eve::test::generate(eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using ce_t = eve::complex; + using z_t = eve::wide, typename T::cardinal_type>; + using c_t = std::complex; + auto std_ch = [](auto x, auto y){return std::tan(c_t(x, y)); }; + auto init_with_std = [std_ch](auto a0, auto a1){ + z_t b; + for(int i = 0; i != eve::cardinal_v; ++i) + { + ce_t z(std_ch(a0.get(i), a1.get(i))); + b.set(i, z); + } + return b; + }; + TTS_ULP_EQUAL(eve::tan(z_t{a0,a1}), init_with_std(a0, a1), 2); +}; + + + +EVE_TEST_TYPES( "Check return types of eve::abs", eve::test::scalar::ieee_reals) + (eve::as) +{ + using e_t = eve::element_type_t; + using c_t = eve::complex; + using eve::as; + const int N = 24; + e_t pid = eve::downward(eve::pi)(as()); // nearest pi representation less than mathematical pi + e_t piu = eve::upward(eve::pi)(as()); // nearest pi representation greater than mathematical pi + std::array inputs = + { c_t(eve::zero(as()),eve::zero(as())),//0 + c_t(eve::inf(as()),eve::zero(as())), //1 + c_t(eve::minf(as()),eve::zero(as())),//2 + c_t(eve::nan(as()),eve::zero(as())), //3 + c_t(eve::zero(as()),eve::inf(as())), //4 + c_t(eve::inf(as()),eve::inf(as())), //5 + c_t(eve::minf(as()),eve::inf(as())), //6 + c_t(eve::nan(as()),eve::inf(as())), //7 + c_t(eve::zero(as()),eve::minf(as())),//8 + c_t(eve::inf(as()),eve::minf(as())), //9 + c_t(eve::minf(as()),eve::minf(as())),//10 + c_t(eve::nan(as()),eve::minf(as())), //11 + c_t(eve::zero(as()),eve::nan(as())), //12 + c_t(eve::inf(as()),eve::nan(as())), //13 + c_t(eve::minf(as()),eve::nan(as())), //14 + c_t(eve::nan(as()),eve::nan(as())), //15 + c_t(eve::zero(as()),pid), //16 + c_t(eve::inf(as()),pid), //17 + c_t(eve::minf(as()),pid), //18 + c_t(eve::nan(as()),pid), //19 + c_t(eve::zero(as()),piu), //20 + c_t(eve::inf(as()),piu), //21 + c_t(eve::minf(as()),piu), //22 + c_t(eve::nan(as()),piu), //23 + }; + + auto tangent = eve::tan; + auto ttangent= [](auto z){return eve::mul_mi(eve::tanh(eve::mul_i(z)));}; + for(int i=0; i < N; ++i) + { + TTS_IEEE_EQUAL(tangent(-inputs[i]), -tangent(inputs[i])); + TTS_IEEE_EQUAL(tangent(inputs[i]), ttangent(inputs[i])); + } +}; diff --git a/old/complex_test/tanh.cpp b/old/complex_test/tanh.cpp new file mode 100644 index 00000000000..13e160f38ca --- /dev/null +++ b/old/complex_test/tanh.cpp @@ -0,0 +1,117 @@ +//================================================================================================== +/** + EVE - Expressive Vector Engine + Copyright : EVE Contributors & Maintainers + SPDX-License-Identifier: MIT +**/ +//================================================================================================== +#include "test.hpp" +#include "measures.hpp" +#include +#include +#include +#include + +EVE_TEST( "Check behavior of tanh on scalar" + , eve::test::scalar::ieee_reals + , eve::test::generate( eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using c_t = std::complex; + using z_t = eve::complex; + for(auto e : a0) + { + for(auto f : a1) + { + TTS_ULP_EQUAL(eve::tanh(eve::complex(e, f)), z_t(std::tanh(c_t(e, f))), 3.0); + TTS_ULP_EQUAL(eve::tanh(eve::complex(e, f)), z_t(std::tanh(c_t(e, f))), 3.0); + } + } +}; + +EVE_TEST( "Check behavior of tanh on wide" + , eve::test::simd::ieee_reals + , eve::test::generate(eve::test::randoms(-10, 10) + , eve::test::randoms(-10, 10)) + ) + (T const& a0, T const& a1 ) +{ + using e_t = typename T::value_type; + using ce_t = eve::complex; + using z_t = eve::wide, typename T::cardinal_type>; + using c_t = std::complex; + auto std_ch = [](auto x, auto y){return std::tanh(c_t(x, y)); }; + auto init_with_std = [std_ch](auto a0, auto a1){ + z_t b; + for(int i = 0; i != eve::cardinal_v; ++i) + { + ce_t z(std_ch(a0.get(i), a1.get(i))); + b.set(i, z); + } + return b; + }; + TTS_ULP_EQUAL(eve::tanh(z_t{a0,a1}), init_with_std(a0, a1), 3); +}; + +EVE_TEST_TYPES( "Check return types of eve::abs", eve::test::scalar::ieee_reals) + (eve::as) +{ + using e_t = eve::element_type_t; + using c_t = eve::complex; + using eve::as; + + const int N = 19; + std::array inputs = + { c_t(eve::zero(as()),eve::zero(as())), //0 + c_t(eve::inf(as()),eve::zero(as())), //1 + c_t(eve::minf(as()),eve::zero(as())), //2 + c_t(eve::nan(as()),eve::zero(as())), //3 + c_t(eve::zero(as()),eve::inf(as())), //4 + c_t(eve::inf(as()),eve::inf(as())), //5 + c_t(eve::minf(as()),eve::inf(as())), //6 + c_t(eve::nan(as()),eve::inf(as())), //7 + c_t(eve::zero(as()),eve::minf(as())), //8 + c_t(eve::inf(as()),eve::minf(as())), //9 + c_t(eve::minf(as()),eve::minf(as())), //10 + c_t(eve::nan(as()),eve::minf(as())), //11 + c_t(eve::zero(as()),eve::nan(as())), //12 + c_t(eve::inf(as()),eve::nan(as())), //13 + c_t(eve::minf(as()),eve::nan(as())), //14 + c_t(eve::nan(as()),eve::nan(as())), //15 + c_t(eve::inf(as()),eve::pi (as())), //16 + c_t(eve::minf(as()),eve::pi (as())), //17 + c_t(eve::nan(as()),eve::pi (as())), //18 + }; + + std::array results = + { c_t(eve::zero(as()),eve::zero(as())),//0 + c_t(eve::nan(as()),eve::zero(as())), //1 + c_t(eve::nan(as()),eve::zero(as())), //2 + c_t(eve::nan(as()),eve::zero(as())), //3 + c_t(eve::zero(as()),eve::nan(as())), //4 + c_t(eve::nan(as()),eve::nan(as())), //5 + c_t(eve::nan(as()),eve::nan(as())), //6 + c_t(eve::nan(as()),eve::nan(as())), //7 + c_t(eve::zero(as()),eve::nan(as())), //8 + c_t(eve::nan(as()),eve::nan(as())), //9 + c_t(eve::nan(as()),eve::nan(as())), //10 + c_t(eve::nan(as()),eve::nan(as())), //11 + c_t(eve::zero(as()),eve::nan(as())), //12 + c_t(eve::nan(as()),eve::nan(as())), //13 + c_t(eve::nan(as()),eve::nan(as())), //14 + c_t(eve::nan(as()),eve::nan(as())), //15 + c_t(eve::nan(as()),eve::zero(as())), //16 + c_t(eve::nan(as()),eve::zero(as())), //17 + c_t(eve::nan(as()),eve::nan (as())), //18 + }; + + for(int i=0; i < N; i++) + { + std::cout << i << std::endl; + TTS_ULP_EQUAL((eve::tanh)(inputs[i]), results[i], 1); + TTS_ULP_EQUAL((eve::tanh)(-inputs[i]), -results[i], 1); + } +};