LCOV - code coverage report
Current view: top level - core/core/utils - SPHalfFloat.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 25 28 89.3 %
Date: 2024-05-12 00:16:13 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /**
       2             : Copyright (c) 2022 Roman Katuntsev <sbkarr@stappler.org>
       3             : Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
       4             : 
       5             : Permission is hereby granted, free of charge, to any person obtaining a copy
       6             : of this software and associated documentation files (the "Software"), to deal
       7             : in the Software without restriction, including without limitation the rights
       8             : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       9             : copies of the Software, and to permit persons to whom the Software is
      10             : furnished to do so, subject to the following conditions:
      11             : 
      12             : The above copyright notice and this permission notice shall be included in
      13             : all copies or substantial portions of the Software.
      14             : 
      15             : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      16             : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      17             : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      18             : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      19             : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      20             : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      21             : THE SOFTWARE.
      22             : **/
      23             : 
      24             : #ifndef STAPPLER_CORE_UTILS_SPHALFFLOAT_H_
      25             : #define STAPPLER_CORE_UTILS_SPHALFFLOAT_H_
      26             : 
      27             : #include "SPCore.h"
      28             : 
      29             : namespace STAPPLER_VERSIONIZED stappler::halffloat {
      30             : 
      31             : // see https://en.wikipedia.org/wiki/Half_precision_floating-point_format
      32             : 
      33          25 : constexpr uint16_t nan() { return (uint16_t)0x7e00; }
      34          25 : constexpr uint16_t posinf() { return (uint16_t)(31 << 10); }
      35          25 : constexpr uint16_t neginf() { return (uint16_t)(63 << 10); }
      36             : 
      37     3769597 : inline constexpr float decode(uint16_t half)  {
      38     3769597 :         uint16_t exp = (half >> 10) & 0x1f;
      39     3769597 :         uint16_t mant = half & 0x3ff;
      40     7538818 :     double val = (exp == 0) ? std::ldexp(mant, -24)
      41     3769372 :                 : ((exp != 31) ? std::ldexp(mant + 1024, exp - 25)
      42         150 :                                 : (mant == 0 ? NumericLimits<float>::infinity() : stappler::nan()));
      43             : 
      44     3769596 :     return (half & 0x8000) ? -val : val;
      45             : }
      46             : 
      47       52689 : inline constexpr uint16_t encode(float val)  {
      48             :     union {
      49             :         float f;
      50             :         uint32_t i;
      51       52689 :     } u32 = { val };
      52             : 
      53       52689 :     uint16_t bits = (u32.i >> 16) & 0x8000; /* Get the sign */
      54       52689 :     uint16_t m = (u32.i >> 12) & 0x07ff; /* Keep one extra bit for rounding */
      55       52689 :     uint32_t e = (u32.i >> 23) & 0xff; /* Using int is faster here */
      56             : 
      57             :     /* If zero, or denormal, or exponent underflows too much for a denormal
      58             :      * half, return signed zero. */
      59       52689 :     if (e < 103) {
      60          25 :         return bits;
      61             :     }
      62             : 
      63             :     /* If NaN, return NaN. If Inf or exponent overflow, return Inf. */
      64       52664 :     if (e > 142) {
      65          75 :         bits |= 0x7c00u;
      66             :         /* If exponent was 0xff and one mantissa bit was set, it means NaN,
      67             :          * not Inf, so make sure we set one mantissa bit too. */
      68          75 :         bits |= (e == 255) && (u32.i & 0x007fffffu);
      69          75 :         return bits;
      70             :     }
      71             : 
      72             :     /* If exponent underflows but not too much, return a denormal */
      73       52589 :     if (e < 113) {
      74           0 :         m |= 0x0800u;
      75             :         /* Extra rounding may overflow and set mantissa to 0 and exponent
      76             :          * to 1, which is OK. */
      77           0 :         bits |= (m >> (114 - e)) + ((m >> (113 - e)) & 1);
      78           0 :         return bits;
      79             :     }
      80             : 
      81       52589 :     bits |= ((e - 112) << 10) | (m >> 1);
      82             :     /* Extra rounding. An overflow will set mantissa to 0 and increment
      83             :      * the exponent, which is OK. */
      84       52589 :     bits += m & 1;
      85       52589 :     return bits;
      86             : }
      87             : 
      88             : }
      89             : 
      90             : #endif /* STAPPLER_CORE_UTILS_SPHALFFLOAT_H_ */

Generated by: LCOV version 1.14