|
5 | 5 |
|
6 | 6 | #pragma once |
7 | 7 |
|
| 8 | +#include "alpaka/core/BitCast.hpp" |
8 | 9 | #include "alpaka/core/Decay.hpp" |
| 10 | +#include "alpaka/core/Unreachable.hpp" |
9 | 11 | #include "alpaka/math/Traits.hpp" |
10 | 12 |
|
| 13 | +#include <cstdint> |
| 14 | +#include <type_traits> |
| 15 | + |
11 | 16 | namespace alpaka::math |
12 | 17 | { |
13 | 18 | //! The standard library abs, implementation covered by the general template. |
@@ -294,6 +299,99 @@ namespace alpaka::math |
294 | 299 | ALPAKA_UNREACHABLE(std::common_type_t<Tx, Ty>{}); |
295 | 300 | } |
296 | 301 | }; |
| 302 | + |
| 303 | + //! Custom IEEE 754 bitwise implementation of isfinite. |
| 304 | + //! std counterpart does not work correctly for some compiler flags at CPU backend |
| 305 | + template<typename TArg> |
| 306 | + struct Isfinite<IsfiniteStdLib, TArg, std::enable_if_t<std::is_floating_point_v<TArg>>> |
| 307 | + { |
| 308 | + auto operator()(IsfiniteStdLib const& /* ctx */, TArg const& arg) -> bool |
| 309 | + { |
| 310 | + if constexpr(std::is_same_v<TArg, float>) |
| 311 | + { |
| 312 | + constexpr std::uint32_t expMask = 0x7F80'0000; |
| 313 | + std::uint32_t bits = alpaka::core::bit_cast<std::uint32_t>(arg); |
| 314 | + bool result = (bits & expMask) != expMask; |
| 315 | + return result; |
| 316 | + } |
| 317 | + else if constexpr(std::is_same_v<TArg, double>) |
| 318 | + { |
| 319 | + constexpr std::uint64_t expMask = 0x7FF0'0000'0000'0000ULL; |
| 320 | + std::uint64_t bits = alpaka::core::bit_cast<std::uint64_t>(arg); |
| 321 | + bool result = (bits & expMask) != expMask; |
| 322 | + return result; |
| 323 | + } |
| 324 | + else |
| 325 | + { |
| 326 | + static_assert(!sizeof(TArg), "Unsupported floating-point type"); |
| 327 | + } |
| 328 | + ALPAKA_UNREACHABLE(false); |
| 329 | + } |
| 330 | + }; |
| 331 | + |
| 332 | + //! Custom IEEE 754 bitwise implementation of isinf |
| 333 | + //! std counterpart does not work correctly for some compiler flags at CPU backend |
| 334 | + template<typename TArg> |
| 335 | + struct Isinf<IsinfStdLib, TArg, std::enable_if_t<std::is_floating_point_v<TArg>>> |
| 336 | + { |
| 337 | + auto operator()(IsinfStdLib const& /* ctx */, TArg const& arg) -> bool |
| 338 | + { |
| 339 | + if constexpr(std::is_same_v<TArg, float>) |
| 340 | + { |
| 341 | + constexpr std::uint32_t expMask = 0x7F80'0000; |
| 342 | + constexpr std::uint32_t fracMask = 0x007F'FFFF; |
| 343 | + std::uint32_t bits = alpaka::core::bit_cast<std::uint32_t>(arg); |
| 344 | + bool result = ((bits & expMask) == expMask) && !(bits & fracMask); |
| 345 | + return result; |
| 346 | + } |
| 347 | + else if constexpr(std::is_same_v<TArg, double>) |
| 348 | + { |
| 349 | + constexpr std::uint64_t expMask = 0x7FF0'0000'0000'0000ULL; |
| 350 | + constexpr std::uint64_t fracMask = 0x000F'FFFF'FFFF'FFFFULL; |
| 351 | + std::uint64_t bits = alpaka::core::bit_cast<std::uint64_t>(arg); |
| 352 | + bool result = ((bits & expMask) == expMask) && !(bits & fracMask); |
| 353 | + return result; |
| 354 | + } |
| 355 | + else |
| 356 | + { |
| 357 | + static_assert(!sizeof(TArg), "Unsupported floating-point type"); |
| 358 | + } |
| 359 | + ALPAKA_UNREACHABLE(false); |
| 360 | + } |
| 361 | + }; |
| 362 | + |
| 363 | + //! Custom IEEE 754 bitwise implementation of isnan |
| 364 | + //! std counterpart does not work correctly for some compiler flags at CPU backend |
| 365 | + template<typename TArg> |
| 366 | + struct Isnan<IsnanStdLib, TArg, std::enable_if_t<std::is_floating_point_v<TArg>>> |
| 367 | + { |
| 368 | + auto operator()(IsnanStdLib const& /* ctx */, TArg const& arg) -> bool |
| 369 | + { |
| 370 | + if constexpr(std::is_same_v<TArg, float>) |
| 371 | + { |
| 372 | + constexpr std::uint32_t expMask = 0x7F80'0000; |
| 373 | + constexpr std::uint32_t fracMask = 0x007F'FFFF; |
| 374 | + std::uint32_t bits = alpaka::core::bit_cast<std::uint32_t>(arg); |
| 375 | + bool result = ((bits & expMask) == expMask) && (bits & fracMask); |
| 376 | + return result; |
| 377 | + } |
| 378 | + else if constexpr(std::is_same_v<TArg, double>) |
| 379 | + { |
| 380 | + constexpr std::uint64_t expMask = 0x7FF0'0000'0000'0000ULL; |
| 381 | + constexpr std::uint64_t fracMask = 0x000F'FFFF'FFFF'FFFFULL; |
| 382 | + std::uint64_t bits = alpaka::core::bit_cast<std::uint64_t>(arg); |
| 383 | + bool result = ((bits & expMask) == expMask) && (bits & fracMask); |
| 384 | + return result; |
| 385 | + } |
| 386 | + else |
| 387 | + { |
| 388 | + static_assert(!sizeof(TArg), "Unsupported floating-point type"); |
| 389 | + } |
| 390 | + ALPAKA_UNREACHABLE(false); |
| 391 | + } |
| 392 | + }; |
| 393 | + |
| 394 | + |
297 | 395 | } // namespace trait |
298 | 396 |
|
299 | 397 | } // namespace alpaka::math |
0 commit comments