|
25 | 25 | #pragma once
|
26 | 26 | #include <complex>
|
27 | 27 | #include <cstddef>
|
| 28 | +#include <cstdint> |
28 | 29 | #include <stdexcept>
|
29 | 30 | #include <sycl/sycl.hpp>
|
30 | 31 | #include <type_traits>
|
@@ -55,26 +56,45 @@ template <typename T> inline constexpr bool is_complex_v = is_complex<T>::value;
|
55 | 56 |
|
56 | 57 | template <typename dstTy, typename srcTy> dstTy convert_impl(const srcTy &v)
|
57 | 58 | {
|
58 |
| - if constexpr (std::is_same<dstTy, srcTy>::value) { |
| 59 | + if constexpr (std::is_same_v<dstTy, srcTy>) { |
59 | 60 | return v;
|
60 | 61 | }
|
61 |
| - else if constexpr (std::is_same_v<dstTy, bool> && is_complex<srcTy>::value) |
62 |
| - { |
63 |
| - // bool(complex_v) == (complex_v.real() != 0) && (complex_v.imag() !=0) |
64 |
| - return (convert_impl<bool, typename srcTy::value_type>(v.real()) || |
65 |
| - convert_impl<bool, typename srcTy::value_type>(v.imag())); |
| 62 | + else if constexpr (std::is_same_v<dstTy, bool>) { |
| 63 | + if constexpr (is_complex_v<srcTy>) { |
| 64 | + // bool(complex_v) == |
| 65 | + // (complex_v.real() != 0) && (complex_v.imag() !=0) |
| 66 | + return (convert_impl<bool, typename srcTy::value_type>(v.real()) || |
| 67 | + convert_impl<bool, typename srcTy::value_type>(v.imag())); |
| 68 | + } |
| 69 | + else { |
| 70 | + return static_cast<dstTy>(v != srcTy{0}); |
| 71 | + } |
| 72 | + } |
| 73 | + else if constexpr (std::is_same_v<srcTy, bool>) { |
| 74 | + // C++ interprets a byte of storage behind bool by only |
| 75 | + // testing is least significant bit, leading to both |
| 76 | + // 0x00 and 0x02 interpreted as False, while 0x01 and 0xFF |
| 77 | + // interpreted as True. NumPy's interpretation of underlying |
| 78 | + // storage is different: any bit set is interpreted as True, |
| 79 | + // no bits set as False, see gh-2121 |
| 80 | + const std::uint8_t &u = sycl::bit_cast<std::uint8_t>(v); |
| 81 | + if constexpr (is_complex_v<dstTy>) { |
| 82 | + return (u == 0) ? dstTy{} : dstTy{1, 0}; |
| 83 | + } |
| 84 | + else { |
| 85 | + return (u == 0) ? dstTy{} : dstTy{1}; |
| 86 | + } |
66 | 87 | }
|
67 |
| - else if constexpr (is_complex<srcTy>::value && !is_complex<dstTy>::value) { |
| 88 | + else if constexpr (is_complex_v<srcTy> && !is_complex_v<dstTy>) { |
68 | 89 | // real_t(complex_v) == real_t(complex_v.real())
|
69 | 90 | return convert_impl<dstTy, typename srcTy::value_type>(v.real());
|
70 | 91 | }
|
71 |
| - else if constexpr (!std::is_integral<srcTy>::value && |
72 |
| - !std::is_same<dstTy, bool>::value && |
73 |
| - std::is_integral<dstTy>::value && |
74 |
| - std::is_unsigned<dstTy>::value) |
| 92 | + else if constexpr (!std::is_integral_v<srcTy> && |
| 93 | + !std::is_same_v<dstTy, bool> && |
| 94 | + std::is_integral_v<dstTy> && std::is_unsigned_v<dstTy>) |
75 | 95 | {
|
76 | 96 | // first cast to signed variant, the cast to unsigned one
|
77 |
| - using signedT = typename std::make_signed<dstTy>::type; |
| 97 | + using signedT = typename std::make_signed_t<dstTy>; |
78 | 98 | return static_cast<dstTy>(convert_impl<signedT, srcTy>(v));
|
79 | 99 | }
|
80 | 100 | else {
|
|
0 commit comments