|
28 | 28 | #include <complex>
|
29 | 29 | #include <cstddef>
|
30 | 30 | #include <cstdint>
|
| 31 | +#include <limits> |
31 | 32 | #include <type_traits>
|
32 | 33 |
|
33 | 34 | #include "kernels/elementwise_functions/common.hpp"
|
|
37 | 38 | #include "utils/type_utils.hpp"
|
38 | 39 | #include <pybind11/pybind11.h>
|
39 | 40 |
|
40 |
| -#include <iostream> |
41 |
| - |
42 | 41 | namespace dpctl
|
43 | 42 | {
|
44 | 43 | namespace tensor
|
@@ -76,21 +75,56 @@ template <typename argT, typename resT> struct AbsFunctor
|
76 | 75 | if constexpr (is_complex<argT>::value) {
|
77 | 76 | return cabs(x);
|
78 | 77 | }
|
| 78 | + else if constexpr (std::is_same_v<argT, sycl::half> || |
| 79 | + std::is_floating_point_v<argT>) |
| 80 | + { |
| 81 | + return (std::signbit(x) ? -x : x); |
| 82 | + } |
79 | 83 | else {
|
80 | 84 | return std::abs(x);
|
81 | 85 | }
|
82 | 86 | }
|
83 | 87 | }
|
84 | 88 |
|
85 | 89 | private:
|
86 |
| - template <typename realT> realT cabs(std::complex<realT> const &z) |
| 90 | + template <typename realT> realT cabs(std::complex<realT> const &z) const |
87 | 91 | {
|
88 |
| -#ifdef _WINDOWS |
89 |
| - // work-around for gh-1279 |
90 |
| - return std::hypot(std::real(z), std::imag(z)); |
| 92 | + // Special values for cabs( x + y * 1j): |
| 93 | + // * If x is either +infinity or -infinity and y is any value |
| 94 | + // (including NaN), the result is +infinity. |
| 95 | + // * If x is any value (including NaN) and y is either +infinity or |
| 96 | + // -infinity, the result is +infinity. |
| 97 | + // * If x is either +0 or -0, the result is equal to abs(y). |
| 98 | + // * If y is either +0 or -0, the result is equal to abs(x). |
| 99 | + // * If x is NaN and y is a finite number, the result is NaN. |
| 100 | + // * If x is a finite number and y is NaN, the result is NaN. |
| 101 | + // * If x is NaN and y is NaN, the result is NaN. |
| 102 | + |
| 103 | + const realT x = std::real(z); |
| 104 | + const realT y = std::imag(z); |
| 105 | + |
| 106 | + constexpr realT q_nan = std::numeric_limits<realT>::quiet_NaN(); |
| 107 | + constexpr realT p_inf = std::numeric_limits<realT>::infinity(); |
| 108 | + |
| 109 | + if (std::isinf(x)) { |
| 110 | + return p_inf; |
| 111 | + } |
| 112 | + else if (std::isinf(y)) { |
| 113 | + return p_inf; |
| 114 | + } |
| 115 | + else if (std::isnan(x)) { |
| 116 | + return q_nan; |
| 117 | + } |
| 118 | + else if (std::isnan(y)) { |
| 119 | + return q_nan; |
| 120 | + } |
| 121 | + else { |
| 122 | +#ifdef USE_STD_ABS_FOR_COMPLEX_TYPES |
| 123 | + return std::abs(z); |
91 | 124 | #else
|
92 |
| - return std::abs(z); |
| 125 | + return std::hypot(std::real(z), std::imag(z)); |
93 | 126 | #endif
|
| 127 | + } |
94 | 128 | }
|
95 | 129 | };
|
96 | 130 |
|
|
0 commit comments