MCPcopy Create free account
hub / github.com/NVIDIA-RTX/Donut / UpConvert

Function UpConvert

src/core/math/float.cpp:344–392  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

342 outExponent = OUT_TYPE(adjustedExponent) << OUT_FORMAT::EXPONENT_SHIFT;
343 outMantissa = OUT_TYPE(mantissa);
344 }
345
346 return outSign | outExponent | outMantissa;
347 }
348
349 template<typename IN_FORMAT, typename IN_TYPE>
350 float UpConvert(IN_TYPE const bits)
351 {
352 using OUT_FORMAT = HELPER<FLOAT32>;
353
354 static_assert(OUT_FORMAT::MANTISSA_WIDTH > IN_FORMAT::MANTISSA_WIDTH);
355 static_assert(OUT_FORMAT::EXPONENT_WIDTH > IN_FORMAT::EXPONENT_WIDTH);
356 static_assert(OUT_FORMAT::EXPONENT_BIAS > IN_FORMAT::EXPONENT_BIAS + IN_FORMAT::MANTISSA_WIDTH);
357 static_assert(IN_FORMAT::TOTAL_WIDTH == sizeof(IN_TYPE) * 8);
358
359 IN_TYPE const inSign = bits & IN_FORMAT::SIGN_BIT;
360 IN_TYPE const inExponent = bits & IN_FORMAT::EXPONENT_MASK;
361 IN_TYPE const inMantissa = bits & IN_FORMAT::MANTISSA_MASK;
362
363 uint32_t const outSign = uint32_t(inSign) << (OUT_FORMAT::SIGN_BIT_SHIFT - IN_FORMAT::SIGN_BIT_SHIFT);
364 uint32_t outExponent = uint32_t(inExponent) << (OUT_FORMAT::EXPONENT_SHIFT - IN_FORMAT::EXPONENT_SHIFT);
365 outExponent += (OUT_FORMAT::EXPONENT_BIAS - IN_FORMAT::EXPONENT_BIAS) << OUT_FORMAT::EXPONENT_SHIFT;
366 uint32_t outMantissa = uint32_t(inMantissa) << (OUT_FORMAT::MANTISSA_WIDTH - IN_FORMAT::MANTISSA_WIDTH);
367
368 if (inExponent == IN_FORMAT::EXPONENT_MASK && (IN_FORMAT::SUPPORTS_INF || inMantissa == IN_FORMAT::MANTISSA_MASK)) // Inf or NaN
369 {
370 outExponent = OUT_FORMAT::EXPONENT_MASK;
371 }
372 else if (inExponent == 0) // Denormal
373 {
374 if (inMantissa != 0) // Non-zero denormal - convert to a normal number, there must be enough exponent bits for that
375 {
376 // TODO: When Donut moves to C++20, replace this platform-specific
377 // leading-zero-count block with std::countl_zero (<bit>):
378 // https://en.cppreference.com/cpp/numeric/countl_zero
379#ifdef _MSC_VER
380#if defined(_M_ARM64) || defined(_M_ARM64EC)
381 // __lzcnt is x86-only; use _BitScanReverse on ARM64.
382 // inMantissa is guaranteed non-zero here (checked above).
383 unsigned long msbIndex;
384 _BitScanReverse(&msbIndex, uint32_t(inMantissa));
385 uint32_t leadingZeros = 31u - uint32_t(msbIndex);
386#else
387 uint32_t leadingZeros = __lzcnt(uint32_t(inMantissa));
388#endif
389#else
390 uint32_t leadingZeros = __builtin_clz(uint32_t(inMantissa));
391#endif
392 // Don't count the bits from uint32_t higher than the mantissa
393 leadingZeros -= 32 - IN_FORMAT::MANTISSA_WIDTH;
394
395 // Shift the mantissa so that its highest "one" bit becomes the hidden "one"

Callers

nothing calls this directly

Calls 1

asfloatFunction · 0.85

Tested by

no test coverage detected