|
7 | 7 | #include <nbl/builtin/hlsl/spirv_intrinsics/core.hlsl> |
8 | 8 | #include <nbl/builtin/hlsl/spirv_intrinsics/glsl.std.450.hlsl> |
9 | 9 | #include <nbl/builtin/hlsl/ieee754.hlsl> |
| 10 | +#include <nbl/builtin/hlsl/tgmath/output_structs.hlsl> |
10 | 11 |
|
11 | 12 | // C++ includes |
12 | 13 | #ifndef __HLSL_VERSION |
@@ -79,6 +80,10 @@ template<typename T NBL_STRUCT_CONSTRAINABLE> |
79 | 80 | struct fma_helper; |
80 | 81 | template<typename T, typename U NBL_STRUCT_CONSTRAINABLE> |
81 | 82 | struct ldexp_helper; |
| 83 | +template<typename T NBL_STRUCT_CONSTRAINABLE> |
| 84 | +struct modfStruct_helper; |
| 85 | +template<typename T NBL_STRUCT_CONSTRAINABLE> |
| 86 | +struct frexpStruct_helper; |
82 | 87 |
|
83 | 88 | #ifdef __HLSL_VERSION |
84 | 89 |
|
@@ -118,6 +123,8 @@ template<typename T> AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(ceil_helper, ceil, (T), |
118 | 123 | template<typename T> AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(pow_helper, pow, (T), (T)(T), T) |
119 | 124 | template<typename T> AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(fma_helper, fma, (T), (T)(T)(T), T) |
120 | 125 | template<typename T, typename U> AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(ldexp_helper, ldexp, (T)(U), (T)(U), T) |
| 126 | +template<typename T> AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(modfStruct_helper, modfStruct, (T), (T), ModfOutput<T>) |
| 127 | +template<typename T> AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(frexpStruct_helper, frexpStruct, (T), (T), FrexpOutput<T>) |
121 | 128 |
|
122 | 129 | #define ISINF_AND_ISNAN_RETURN_TYPE conditional_t<is_vector_v<T>, vector<bool, vector_traits<T>::Dimension>, bool> |
123 | 130 | template<typename T> AUTO_SPECIALIZE_TRIVIAL_CASE_HELPER(isinf_helper, isInf, (T), (T), ISINF_AND_ISNAN_RETURN_TYPE) |
@@ -327,6 +334,34 @@ struct ldexp_helper<T, U NBL_PARTIAL_REQ_BOT(concepts::FloatingPointScalar<T> && |
327 | 334 | } |
328 | 335 | }; |
329 | 336 |
|
| 337 | +template<typename T> |
| 338 | +requires concepts::FloatingPointScalar<T> |
| 339 | +struct modfStruct_helper<T> |
| 340 | +{ |
| 341 | + using return_t = ModfOutput<T>; |
| 342 | + static inline return_t __call(const T val) |
| 343 | + { |
| 344 | + return_t output; |
| 345 | + output.fractionalPart = std::modf(val, &output.wholeNumberPart); |
| 346 | + |
| 347 | + return output; |
| 348 | + } |
| 349 | +}; |
| 350 | + |
| 351 | +template<typename T> |
| 352 | +requires concepts::FloatingPointScalar<T> |
| 353 | +struct frexpStruct_helper<T> |
| 354 | +{ |
| 355 | + using return_t = FrexpOutput<T>; |
| 356 | + static inline return_t __call(const T val) |
| 357 | + { |
| 358 | + return_t output; |
| 359 | + output.significand = std::frexp(val, &output.exponent); |
| 360 | + |
| 361 | + return output; |
| 362 | + } |
| 363 | +}; |
| 364 | + |
330 | 365 | #endif // C++ only specializations |
331 | 366 |
|
332 | 367 | // C++ and HLSL specializations |
@@ -480,6 +515,67 @@ struct ldexp_helper<T, U NBL_PARTIAL_REQ_BOT(VECTOR_SPECIALIZATION_CONCEPT && (v |
480 | 515 | } |
481 | 516 | }; |
482 | 517 |
|
| 518 | +template<typename T> |
| 519 | +NBL_PARTIAL_REQ_TOP(VECTOR_SPECIALIZATION_CONCEPT) |
| 520 | +struct modfStruct_helper<T NBL_PARTIAL_REQ_BOT(VECTOR_SPECIALIZATION_CONCEPT) > |
| 521 | +{ |
| 522 | + using return_t = ModfOutput<T>; |
| 523 | + static return_t __call(NBL_CONST_REF_ARG(T) x) |
| 524 | + { |
| 525 | + using traits = hlsl::vector_traits<T>; |
| 526 | + array_get<T, typename traits::scalar_type> getter; |
| 527 | + array_set<T, typename traits::scalar_type> setter; |
| 528 | + |
| 529 | + T fracPartOut; |
| 530 | + T intPartOut; |
| 531 | + for (uint32_t i = 0; i < traits::Dimension; ++i) |
| 532 | + { |
| 533 | + using component_return_t = ModfOutput<typename vector_traits<T>::scalar_type>; |
| 534 | + component_return_t result = modfStruct_helper<typename traits::scalar_type>::__call(getter(x, i)); |
| 535 | + |
| 536 | + setter(fracPartOut, i, result.fractionalPart); |
| 537 | + setter(intPartOut, i, result.wholeNumberPart); |
| 538 | + } |
| 539 | + |
| 540 | + return_t output; |
| 541 | + output.fractionalPart = fracPartOut; |
| 542 | + output.wholeNumberPart = intPartOut; |
| 543 | + |
| 544 | + return output; |
| 545 | + } |
| 546 | +}; |
| 547 | + |
| 548 | +template<typename T> |
| 549 | +NBL_PARTIAL_REQ_TOP(VECTOR_SPECIALIZATION_CONCEPT) |
| 550 | +struct frexpStruct_helper<T NBL_PARTIAL_REQ_BOT(VECTOR_SPECIALIZATION_CONCEPT) > |
| 551 | +{ |
| 552 | + using return_t = FrexpOutput<T>; |
| 553 | + static return_t __call(NBL_CONST_REF_ARG(T) x) |
| 554 | + { |
| 555 | + using traits = hlsl::vector_traits<T>; |
| 556 | + array_get<T, typename traits::scalar_type> getter; |
| 557 | + array_set<T, typename traits::scalar_type> significandSetter; |
| 558 | + array_set<T, typename traits::scalar_type> exponentSetter; |
| 559 | + |
| 560 | + T significandOut; |
| 561 | + T exponentOut; |
| 562 | + for (uint32_t i = 0; i < traits::Dimension; ++i) |
| 563 | + { |
| 564 | + using component_return_t = FrexpOutput<typename vector_traits<T>::scalar_type>; |
| 565 | + component_return_t result = frexpStruct_helper<typename traits::scalar_type>::__call(getter(x, i)); |
| 566 | + |
| 567 | + significandSetter(significandOut, i, result.significand); |
| 568 | + exponentSetter(exponentOut, i, result.exponent); |
| 569 | + } |
| 570 | + |
| 571 | + return_t output; |
| 572 | + output.significand = significandOut; |
| 573 | + output.exponent = exponentOut; |
| 574 | + |
| 575 | + return output; |
| 576 | + } |
| 577 | +}; |
| 578 | + |
483 | 579 | #undef VECTOR_SPECIALIZATION_CONCEPT |
484 | 580 |
|
485 | 581 | } |
|
0 commit comments