LCOV - code coverage report
Current view: top level - eq/client - half.cpp (source / functions) Hit Total Coverage
Test: lcov2.info Lines: 74 404 18.3 %
Date: 2014-06-18 Functions: 13 38 34.2 %

          Line data    Source code
       1             : // Branch-free implementation of half-precision (16 bit) floating point
       2             : // Copyright 2006 Mike Acton <macton@gmail.com>
       3             : //
       4             : // Permission is hereby granted, free of charge, to any person obtaining a
       5             : // copy of this software and associated documentation files (the "Software"),
       6             : // to deal in the Software without restriction, including without limitation
       7             : // the rights to use, copy, modify, merge, publish, distribute, sublicense,
       8             : // and/or sell copies of the Software, and to permit persons to whom the
       9             : // Software is furnished to do so, subject to the following conditions:
      10             : //
      11             : // The above copyright notice and this permission notice shall be included
      12             : // in all copies or substantial portions of the Software.
      13             : //
      14             : // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      15             : // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      16             : // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      17             : // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      18             : // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      19             : // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      20             : // THE SOFTWARE
      21             : //
      22             : // Half-precision floating point format
      23             : // ------------------------------------
      24             : //
      25             : //   | Field    | Last | First | Note
      26             : //   |----------|------|-------|----------
      27             : //   | Sign     | 15   | 15    |
      28             : //   | Exponent | 14   | 10    | Bias = 15
      29             : //   | Mantissa | 9    | 0     |
      30             : //
      31             : // Compiling
      32             : // ---------
      33             : //
      34             : //  Preferred compile flags for GCC:
      35             : //     -O3 -fstrict-aliasing -std=c99 -pedantic -Wall -Wstrict-aliasing
      36             : //
      37             : //     This file is a C99 source file, intended to be compiled with a C99
      38             : //     compliant compiler. However, for the moment it remains combatible
      39             : //     with C++98. Therefore if you are using a compiler that poorly implements
      40             : //     C standards (e.g. MSVC), it may be compiled as C++. This is not
      41             : //     guaranteed for future versions.
      42             : //
      43             : 
      44             : #include "half.h"
      45             : 
      46             : // Load immediate
      47    27648000 : static inline uint32_t _uint32_li( uint32_t a )
      48             : {
      49    27648000 :   return (a);
      50             : }
      51             : 
      52             : // Decrement
      53     2304000 : static inline uint32_t _uint32_dec( uint32_t a )
      54             : {
      55     2304000 :   return (a - 1);
      56             : }
      57             : 
      58             : // Increment
      59           0 : static inline uint32_t _uint32_inc( uint32_t a )
      60             : {
      61           0 :   return (a + 1);
      62             : }
      63             : 
      64             : // Complement
      65           0 : static inline uint32_t _uint32_not( uint32_t a )
      66             : {
      67           0 :   return (~a);
      68             : }
      69             : 
      70             : // Negate
      71     4608000 : static inline uint32_t _uint32_neg( uint32_t a )
      72             : {
      73             : #pragma warning (disable: 4146)
      74     4608000 :   return (-a);
      75             : #pragma warning( default: 4146)
      76             : }
      77             : 
      78             : // Extend sign
      79    11520000 : static inline uint32_t _uint32_ext( uint32_t a )
      80             : {
      81    11520000 :   return (((int32_t)a)>>31);
      82             : }
      83             : 
      84             : // And
      85    23040000 : static inline uint32_t _uint32_and( uint32_t a, uint32_t b )
      86             : {
      87    23040000 :   return (a & b);
      88             : }
      89             : 
      90             : // Exclusive Or
      91           0 : static inline uint32_t _uint32_xor( uint32_t a, uint32_t b )
      92             : {
      93           0 :   return (a ^ b);
      94             : }
      95             : 
      96             : // And with Complement
      97    16128000 : static inline uint32_t _uint32_andc( uint32_t a, uint32_t b )
      98             : {
      99    16128000 :   return (a & ~b);
     100             : }
     101             : 
     102             : // Or
     103    18432000 : static inline uint32_t _uint32_or( uint32_t a, uint32_t b )
     104             : {
     105    18432000 :   return (a | b);
     106             : }
     107             : 
     108             : // Shift Right Logical
     109           0 : static inline uint32_t _uint32_srl( uint32_t a, int sa )
     110             : {
     111           0 :   return (a >> sa);
     112             : }
     113             : 
     114             : // Shift Left Logical
     115    11520000 : static inline uint32_t _uint32_sll( uint32_t a, int sa )
     116             : {
     117    11520000 :   return (a << sa);
     118             : }
     119             : 
     120             : // Add
     121     2304000 : static inline uint32_t _uint32_add( uint32_t a, uint32_t b )
     122             : {
     123     2304000 :   return (a + b);
     124             : }
     125             : 
     126             : // Subtract
     127     6912000 : static inline uint32_t _uint32_sub( uint32_t a, uint32_t b )
     128             : {
     129     6912000 :   return (a - b);
     130             : }
     131             : 
     132             : // Multiply
     133           0 : static inline uint32_t _uint32_mul( uint32_t a, uint32_t b )
     134             : {
     135           0 :   return (a * b);
     136             : }
     137             : 
     138             : // Select on Sign bit
     139     9216000 : static inline uint32_t _uint32_sels( uint32_t test, uint32_t a, uint32_t b )
     140             : {
     141     9216000 :   const uint32_t mask   = _uint32_ext( test );
     142     9216000 :   const uint32_t sel_a  = _uint32_and(  a,     mask  );
     143     9216000 :   const uint32_t sel_b  = _uint32_andc( b,     mask  );
     144     9216000 :   const uint32_t result = _uint32_or(   sel_a, sel_b );
     145             : 
     146     9216000 :   return (result);
     147             : }
     148             : 
     149             : // Select Bits on mask
     150           0 : static inline uint32_t _uint32_selb( uint32_t mask, uint32_t a, uint32_t b )
     151             : {
     152           0 :   const uint32_t sel_a  = _uint32_and(  a,     mask  );
     153           0 :   const uint32_t sel_b  = _uint32_andc( b,     mask  );
     154           0 :   const uint32_t result = _uint32_or(   sel_a, sel_b );
     155             : 
     156           0 :   return (result);
     157             : }
     158             : 
     159             : // Load Immediate
     160           0 : static inline uint16_t _uint16_li( uint16_t a )
     161             : {
     162           0 :   return (a);
     163             : }
     164             : 
     165             : // Extend sign
     166           0 : static inline uint16_t _uint16_ext( uint16_t a )
     167             : {
     168           0 :   return (((int16_t)a)>>15);
     169             : }
     170             : 
     171             : // Negate
     172           0 : static inline uint16_t _uint16_neg( uint16_t a )
     173             : {
     174           0 :   return (-a);
     175             : }
     176             : 
     177             : #ifndef __GNUC__
     178             : // Complement
     179             : static inline uint16_t _uint16_not( uint16_t a )
     180             : {
     181             :   return (~a);
     182             : }
     183             : // Add then Mask
     184             : static inline uint16_t _uint16_addm( uint16_t a, uint16_t b, uint16_t mask )
     185             : {
     186             :   return ((a + b) & mask);
     187             : }
     188             : #endif
     189             : 
     190             : // Decrement
     191           0 : static inline uint16_t _uint16_dec( uint16_t a )
     192             : {
     193           0 :   return (a - 1);
     194             : }
     195             : 
     196             : // Shift Left Logical
     197           0 : static inline uint16_t _uint16_sll( uint16_t a, int sa )
     198             : {
     199           0 :   return (a << sa);
     200             : }
     201             : 
     202             : // Shift Right Logical
     203           0 : static inline uint16_t _uint16_srl( uint16_t a, int sa )
     204             : {
     205           0 :   return (a >> sa);
     206             : }
     207             : 
     208             : // Add
     209           0 : static inline uint16_t _uint16_add( uint16_t a, uint16_t b )
     210             : {
     211           0 :   return (a + b);
     212             : }
     213             : 
     214             : // Subtract
     215           0 : static inline uint16_t _uint16_sub( uint16_t a, uint16_t b )
     216             : {
     217           0 :   return (a - b);
     218             : }
     219             : 
     220             : // And
     221           0 : static inline uint16_t _uint16_and( uint16_t a, uint16_t b )
     222             : {
     223           0 :   return (a & b);
     224             : }
     225             : 
     226             : // Or
     227           0 : static inline uint16_t _uint16_or( uint16_t a, uint16_t b )
     228             : {
     229           0 :   return (a | b);
     230             : }
     231             : 
     232             : // Exclusive Or
     233           0 : static inline uint16_t _uint16_xor( uint16_t a, uint16_t b )
     234             : {
     235           0 :   return (a ^ b);
     236             : }
     237             : 
     238             : // And with Complement
     239           0 : static inline uint16_t _uint16_andc( uint16_t a, uint16_t b )
     240             : {
     241           0 :   return (a & ~b);
     242             : }
     243             : 
     244             : // And then Shift Right Logical
     245           0 : static inline uint16_t _uint16_andsrl( uint16_t a, uint16_t b, int sa )
     246             : {
     247           0 :   return ((a & b) >> sa);
     248             : }
     249             : 
     250             : // Shift Right Logical then Mask
     251           0 : static inline uint16_t _uint16_srlm( uint16_t a, int sa, uint16_t mask )
     252             : {
     253           0 :   return ((a >> sa) & mask);
     254             : }
     255             : 
     256             : // Select on Sign bit
     257           0 : static inline uint16_t _uint16_sels( uint16_t test, uint16_t a, uint16_t b )
     258             : {
     259           0 :   const uint16_t mask   = _uint16_ext( test );
     260           0 :   const uint16_t sel_a  = _uint16_and(  a,     mask  );
     261           0 :   const uint16_t sel_b  = _uint16_andc( b,     mask  );
     262           0 :   const uint16_t result = _uint16_or(   sel_a, sel_b );
     263             : 
     264           0 :   return (result);
     265             : }
     266             : 
     267             : // Count Leading Zeros
     268     2304000 : static inline uint32_t _uint32_cntlz( uint32_t x )
     269             : {
     270             : #ifdef __GNUC__
     271             :   /* NOTE: __builtin_clz is undefined for x == 0 */
     272             :   /* On PowerPC, this will map to insn: cntlzw   */
     273             :   /* On Pentium, this will map to insn: clz      */
     274     2304000 :   uint32_t is_x_nez_msb = _uint32_neg( x );
     275     2304000 :   uint32_t nlz          = __builtin_clz( x );
     276     2304000 :   uint32_t result       = _uint32_sels( is_x_nez_msb, nlz, 0x00000020 );
     277     2304000 :   return (result);
     278             : #else
     279             :   const uint32_t x0  = _uint32_srl(  x,  1 );
     280             :   const uint32_t x1  = _uint32_or(   x,  x0 );
     281             :   const uint32_t x2  = _uint32_srl(  x1, 2 );
     282             :   const uint32_t x3  = _uint32_or(   x1, x2 );
     283             :   const uint32_t x4  = _uint32_srl(  x3, 4 );
     284             :   const uint32_t x5  = _uint32_or(   x3, x4 );
     285             :   const uint32_t x6  = _uint32_srl(  x5, 8 );
     286             :   const uint32_t x7  = _uint32_or(   x5, x6 );
     287             :   const uint32_t x8  = _uint32_srl(  x7, 16 );
     288             :   const uint32_t x9  = _uint32_or(   x7, x8 );
     289             :   const uint32_t xA  = _uint32_not(  x9 );
     290             :   const uint32_t xB  = _uint32_srl(  xA, 1 );
     291             :   const uint32_t xC  = _uint32_and(  xB, 0x55555555 );
     292             :   const uint32_t xD  = _uint32_sub(  xA, xC );
     293             :   const uint32_t xE  = _uint32_and(  xD, 0x33333333 );
     294             :   const uint32_t xF  = _uint32_srl(  xD, 2 );
     295             :   const uint32_t x10 = _uint32_and(  xF, 0x33333333 );
     296             :   const uint32_t x11 = _uint32_add(  xE, x10 );
     297             :   const uint32_t x12 = _uint32_srl(  x11, 4 );
     298             :   const uint32_t x13 = _uint32_add(  x11, x12 );
     299             :   const uint32_t x14 = _uint32_and(  x13, 0x0f0f0f0f );
     300             :   const uint32_t x15 = _uint32_srl(  x14, 8 );
     301             :   const uint32_t x16 = _uint32_add(  x14, x15 );
     302             :   const uint32_t x17 = _uint32_srl(  x16, 16 );
     303             :   const uint32_t x18 = _uint32_add(  x16, x17 );
     304             :   const uint32_t x19 = _uint32_and(  x18, 0x0000003f );
     305             :   return ( x19 );
     306             : #endif
     307             : }
     308             : 
     309             : // Count Leading Zeros
     310           0 : static inline uint16_t _uint16_cntlz( uint16_t x )
     311             : {
     312             : #ifdef __GNUC__
     313           0 :   uint16_t nlz32 = (uint16_t)_uint32_cntlz( (uint32_t)x );
     314           0 :   uint32_t nlz   = _uint32_sub( nlz32, 16 );
     315           0 :   return (nlz);
     316             : #else
     317             :   const uint16_t x0  = _uint16_srl(  x,  1 );
     318             :   const uint16_t x1  = _uint16_or(   x,  x0 );
     319             :   const uint16_t x2  = _uint16_srl(  x1, 2 );
     320             :   const uint16_t x3  = _uint16_or(   x1, x2 );
     321             :   const uint16_t x4  = _uint16_srl(  x3, 4 );
     322             :   const uint16_t x5  = _uint16_or(   x3, x4 );
     323             :   const uint16_t x6  = _uint16_srl(  x5, 8 );
     324             :   const uint16_t x7  = _uint16_or(   x5, x6 );
     325             :   const uint16_t x8  = _uint16_not(  x7 );
     326             :   const uint16_t x9  = _uint16_srlm( x8, 1, 0x5555 );
     327             :   const uint16_t xA  = _uint16_sub(  x8, x9 );
     328             :   const uint16_t xB  = _uint16_and(  xA, 0x3333 );
     329             :   const uint16_t xC  = _uint16_srlm( xA, 2, 0x3333 );
     330             :   const uint16_t xD  = _uint16_add(  xB, xC );
     331             :   const uint16_t xE  = _uint16_srl(  xD, 4 );
     332             :   const uint16_t xF  = _uint16_addm( xD, xE, 0x0f0f );
     333             :   const uint16_t x10 = _uint16_srl(  xF, 8 );
     334             :   const uint16_t x11 = _uint16_addm( xF, x10, 0x001f );
     335             :   return ( x11 );
     336             : #endif
     337             : }
     338             : 
     339             : uint16_t
     340           0 : half_from_float( float f_ )
     341             : {
     342           0 :   const uint32_t f = *reinterpret_cast< uint32_t* >( &f_ );
     343           0 :   const uint32_t one                        = _uint32_li( 0x00000001 );
     344           0 :   const uint32_t f_s_mask                   = _uint32_li( 0x80000000 );
     345           0 :   const uint32_t f_e_mask                   = _uint32_li( 0x7f800000 );
     346           0 :   const uint32_t f_m_mask                   = _uint32_li( 0x007fffff );
     347           0 :   const uint32_t f_m_hidden_bit             = _uint32_li( 0x00800000 );
     348           0 :   const uint32_t f_m_round_bit              = _uint32_li( 0x00001000 );
     349           0 :   const uint32_t f_snan_mask                = _uint32_li( 0x7fc00000 );
     350           0 :   const uint32_t f_e_pos                    = _uint32_li( 0x00000017 );
     351           0 :   const uint32_t h_e_pos                    = _uint32_li( 0x0000000a );
     352           0 :   const uint32_t h_e_mask                   = _uint32_li( 0x00007c00 );
     353           0 :   const uint32_t h_snan_mask                = _uint32_li( 0x00007e00 );
     354           0 :   const uint32_t h_e_mask_value             = _uint32_li( 0x0000001f );
     355           0 :   const uint32_t f_h_s_pos_offset           = _uint32_li( 0x00000010 );
     356           0 :   const uint32_t f_h_bias_offset            = _uint32_li( 0x00000070 );
     357           0 :   const uint32_t f_h_m_pos_offset           = _uint32_li( 0x0000000d );
     358           0 :   const uint32_t h_nan_min                  = _uint32_li( 0x00007c01 );
     359           0 :   const uint32_t f_h_e_biased_flag          = _uint32_li( 0x0000008f );
     360           0 :   const uint32_t f_s                        = _uint32_and( f,               f_s_mask         );
     361           0 :   const uint32_t f_e                        = _uint32_and( f,               f_e_mask         );
     362           0 :   const uint16_t h_s                        = _uint32_srl( f_s,             f_h_s_pos_offset );
     363           0 :   const uint32_t f_m                        = _uint32_and( f,               f_m_mask         );
     364           0 :   const uint16_t f_e_amount                 = _uint32_srl( f_e,             f_e_pos          );
     365           0 :   const uint32_t f_e_half_bias              = _uint32_sub( f_e_amount,      f_h_bias_offset  );
     366           0 :   const uint32_t f_snan                     = _uint32_and( f,               f_snan_mask      );
     367           0 :   const uint32_t f_m_round_mask             = _uint32_and( f_m,             f_m_round_bit    );
     368           0 :   const uint32_t f_m_round_offset           = _uint32_sll( f_m_round_mask,  one              );
     369           0 :   const uint32_t f_m_rounded                = _uint32_add( f_m,             f_m_round_offset );
     370           0 :   const uint32_t f_m_denorm_sa              = _uint32_sub( one,             f_e_half_bias    );
     371           0 :   const uint32_t f_m_with_hidden            = _uint32_or(  f_m_rounded,     f_m_hidden_bit   );
     372           0 :   const uint32_t f_m_denorm                 = _uint32_srl( f_m_with_hidden, f_m_denorm_sa    );
     373           0 :   const uint32_t h_m_denorm                 = _uint32_srl( f_m_denorm,      f_h_m_pos_offset );
     374           0 :   const uint32_t f_m_rounded_overflow       = _uint32_and( f_m_rounded,     f_m_hidden_bit   );
     375           0 :   const uint32_t m_nan                      = _uint32_srl( f_m,             f_h_m_pos_offset );
     376           0 :   const uint32_t h_em_nan                   = _uint32_or(  h_e_mask,        m_nan            );
     377           0 :   const uint32_t h_e_norm_overflow_offset   = _uint32_inc( f_e_half_bias );
     378           0 :   const uint32_t h_e_norm_overflow          = _uint32_sll( h_e_norm_overflow_offset, h_e_pos          );
     379           0 :   const uint32_t h_e_norm                   = _uint32_sll( f_e_half_bias,            h_e_pos          );
     380           0 :   const uint32_t h_m_norm                   = _uint32_srl( f_m_rounded,              f_h_m_pos_offset );
     381           0 :   const uint32_t h_em_norm                  = _uint32_or(  h_e_norm,                 h_m_norm         );
     382           0 :   const uint32_t is_h_ndenorm_msb           = _uint32_sub( f_h_bias_offset,   f_e_amount    );
     383           0 :   const uint32_t is_f_e_flagged_msb         = _uint32_sub( f_h_e_biased_flag, f_e_half_bias );
     384           0 :   const uint32_t is_h_denorm_msb            = _uint32_not( is_h_ndenorm_msb );
     385           0 :   const uint32_t is_f_m_eqz_msb             = _uint32_dec( f_m   );
     386           0 :   const uint32_t is_h_nan_eqz_msb           = _uint32_dec( m_nan );
     387           0 :   const uint32_t is_f_inf_msb               = _uint32_and( is_f_e_flagged_msb, is_f_m_eqz_msb   );
     388           0 :   const uint32_t is_f_nan_underflow_msb     = _uint32_and( is_f_e_flagged_msb, is_h_nan_eqz_msb );
     389           0 :   const uint32_t is_e_overflow_msb          = _uint32_sub( h_e_mask_value,     f_e_half_bias    );
     390           0 :   const uint32_t is_h_inf_msb               = _uint32_or(  is_e_overflow_msb,  is_f_inf_msb     );
     391           0 :   const uint32_t is_f_nsnan_msb             = _uint32_sub( f_snan,             f_snan_mask      );
     392           0 :   const uint32_t is_m_norm_overflow_msb     = _uint32_neg( f_m_rounded_overflow );
     393           0 :   const uint32_t is_f_snan_msb              = _uint32_not( is_f_nsnan_msb );
     394           0 :   const uint32_t h_em_overflow_result       = _uint32_sels( is_m_norm_overflow_msb, h_e_norm_overflow, h_em_norm                 );
     395           0 :   const uint32_t h_em_nan_result            = _uint32_sels( is_f_e_flagged_msb,     h_em_nan,          h_em_overflow_result      );
     396           0 :   const uint32_t h_em_nan_underflow_result  = _uint32_sels( is_f_nan_underflow_msb, h_nan_min,         h_em_nan_result           );
     397           0 :   const uint32_t h_em_inf_result            = _uint32_sels( is_h_inf_msb,           h_e_mask,          h_em_nan_underflow_result );
     398           0 :   const uint32_t h_em_denorm_result         = _uint32_sels( is_h_denorm_msb,        h_m_denorm,        h_em_inf_result           );
     399           0 :   const uint32_t h_em_snan_result           = _uint32_sels( is_f_snan_msb,          h_snan_mask,       h_em_denorm_result        );
     400           0 :   const uint32_t h_result                   = _uint32_or( h_s, h_em_snan_result );
     401             : 
     402           0 :   return (uint16_t)(h_result);
     403             : }
     404             : 
     405     2304000 : float half_to_float( uint16_t h )
     406             : {
     407     2304000 :   const uint32_t h_e_mask              = _uint32_li( 0x00007c00 );
     408     2304000 :   const uint32_t h_m_mask              = _uint32_li( 0x000003ff );
     409     2304000 :   const uint32_t h_s_mask              = _uint32_li( 0x00008000 );
     410     2304000 :   const uint32_t h_f_s_pos_offset      = _uint32_li( 0x00000010 );
     411     2304000 :   const uint32_t h_f_e_pos_offset      = _uint32_li( 0x0000000d );
     412     2304000 :   const uint32_t h_f_bias_offset       = _uint32_li( 0x0001c000 );
     413     2304000 :   const uint32_t f_e_mask              = _uint32_li( 0x7f800000 );
     414     2304000 :   const uint32_t f_m_mask              = _uint32_li( 0x007fffff );
     415     2304000 :   const uint32_t h_f_e_denorm_bias     = _uint32_li( 0x0000007e );
     416     2304000 :   const uint32_t h_f_m_denorm_sa_bias  = _uint32_li( 0x00000008 );
     417     2304000 :   const uint32_t f_e_pos               = _uint32_li( 0x00000017 );
     418     2304000 :   const uint32_t h_e_mask_minus_one    = _uint32_li( 0x00007bff );
     419     2304000 :   const uint32_t h_e                   = _uint32_and( h, h_e_mask );
     420     2304000 :   const uint32_t h_m                   = _uint32_and( h, h_m_mask );
     421     2304000 :   const uint32_t h_s                   = _uint32_and( h, h_s_mask );
     422     2304000 :   const uint32_t h_e_f_bias            = _uint32_add( h_e, h_f_bias_offset );
     423     2304000 :   const uint32_t h_m_nlz               = _uint32_cntlz( h_m );
     424     2304000 :   const uint32_t f_s                   = _uint32_sll( h_s,        h_f_s_pos_offset );
     425     2304000 :   const uint32_t f_e                   = _uint32_sll( h_e_f_bias, h_f_e_pos_offset );
     426     2304000 :   const uint32_t f_m                   = _uint32_sll( h_m,        h_f_e_pos_offset );
     427     2304000 :   const uint32_t f_em                  = _uint32_or(  f_e,        f_m              );
     428     2304000 :   const uint32_t h_f_m_sa              = _uint32_sub( h_m_nlz,             h_f_m_denorm_sa_bias );
     429     2304000 :   const uint32_t f_e_denorm_unpacked   = _uint32_sub( h_f_e_denorm_bias,   h_f_m_sa             );
     430     2304000 :   const uint32_t h_f_m                 = _uint32_sll( h_m,                 h_f_m_sa             );
     431     2304000 :   const uint32_t f_m_denorm            = _uint32_and( h_f_m,               f_m_mask             );
     432     2304000 :   const uint32_t f_e_denorm            = _uint32_sll( f_e_denorm_unpacked, f_e_pos              );
     433     2304000 :   const uint32_t f_em_denorm           = _uint32_or(  f_e_denorm,          f_m_denorm           );
     434     2304000 :   const uint32_t f_em_nan              = _uint32_or(  f_e_mask,            f_m                  );
     435     2304000 :   const uint32_t is_e_eqz_msb          = _uint32_dec(  h_e );
     436     2304000 :   const uint32_t is_m_nez_msb          = _uint32_neg(  h_m );
     437     2304000 :   const uint32_t is_e_flagged_msb      = _uint32_sub(  h_e_mask_minus_one, h_e );
     438     2304000 :   const uint32_t is_zero_msb           = _uint32_andc( is_e_eqz_msb,       is_m_nez_msb );
     439     2304000 :   const uint32_t is_inf_msb            = _uint32_andc( is_e_flagged_msb,   is_m_nez_msb );
     440     2304000 :   const uint32_t is_denorm_msb         = _uint32_and(  is_m_nez_msb,       is_e_eqz_msb );
     441     2304000 :   const uint32_t is_nan_msb            = _uint32_and(  is_e_flagged_msb,   is_m_nez_msb );
     442     2304000 :   const uint32_t is_zero               = _uint32_ext(  is_zero_msb );
     443     2304000 :   const uint32_t f_zero_result         = _uint32_andc( f_em, is_zero );
     444     2304000 :   const uint32_t f_denorm_result       = _uint32_sels( is_denorm_msb, f_em_denorm, f_zero_result );
     445     2304000 :   const uint32_t f_inf_result          = _uint32_sels( is_inf_msb,    f_e_mask,    f_denorm_result );
     446     2304000 :   const uint32_t f_nan_result          = _uint32_sels( is_nan_msb,    f_em_nan,    f_inf_result    );
     447     2304000 :   const uint32_t f_result              = _uint32_or( f_s, f_nan_result );
     448             : 
     449     2304000 :   return *reinterpret_cast< const float* >( &f_result );
     450             : }
     451             : 
     452             : // half_add
     453             : // --------
     454             : //
     455             : //  (SUM)        uint16_t z = half_add( x, y );
     456             : //  (DIFFERENCE) uint16_t z = half_add( x, -y );
     457             : //
     458             : //  * Difference of ZEROs is always +ZERO
     459             : //  * Sum round with guard + round + sticky bit (grs)
     460             : //  * QNaN + <x>  = QNaN
     461             : //  * <x>  + +INF = +INF
     462             : //  * <x>  - -INF = -INF
     463             : //  * INF  - INF  = SNaN
     464             : //
     465             : //  Will have exactly (0 ulps difference) the same result as:
     466             : //  (Round up)
     467             : //
     468             : //     union FLOAT_32
     469             : //     {
     470             : //       float    f32;
     471             : //       uint32_t u32;
     472             : //     };
     473             : //
     474             : //     union FLOAT_32 fx = { .u32 = half_to_float( x ) };
     475             : //     union FLOAT_32 fy = { .u32 = half_to_float( y ) };
     476             : //     union FLOAT_32 fz = { .f32 = fx.f32 + fy.f32    };
     477             : //     uint16_t       z  = float_to_half( fz );
     478             : //
     479             : uint16_t
     480           0 : half_add( uint16_t x, uint16_t y )
     481             : {
     482           0 :   const uint16_t one                       = _uint16_li( 0x0001 );
     483           0 :   const uint16_t msb_to_lsb_sa             = _uint16_li( 0x000f );
     484           0 :   const uint16_t h_s_mask                  = _uint16_li( 0x8000 );
     485           0 :   const uint16_t h_e_mask                  = _uint16_li( 0x7c00 );
     486           0 :   const uint16_t h_m_mask                  = _uint16_li( 0x03ff );
     487           0 :   const uint16_t h_m_msb_mask              = _uint16_li( 0x2000 );
     488           0 :   const uint16_t h_m_msb_sa                = _uint16_li( 0x000d );
     489           0 :   const uint16_t h_m_hidden                = _uint16_li( 0x0400 );
     490           0 :   const uint16_t h_e_pos                   = _uint16_li( 0x000a );
     491           0 :   const uint16_t h_e_bias_minus_one        = _uint16_li( 0x000e );
     492           0 :   const uint16_t h_m_grs_carry             = _uint16_li( 0x4000 );
     493           0 :   const uint16_t h_m_grs_carry_pos         = _uint16_li( 0x000e );
     494           0 :   const uint16_t h_grs_size                = _uint16_li( 0x0003 );
     495           0 :   const uint16_t h_snan                    = _uint16_li( 0xfe00 );
     496           0 :   const uint16_t h_e_mask_minus_one        = _uint16_li( 0x7bff );
     497           0 :   const uint16_t h_grs_round_carry         = _uint16_sll( one, h_grs_size );
     498           0 :   const uint16_t h_grs_round_mask          = _uint16_sub( h_grs_round_carry, one );
     499           0 :   const uint16_t x_e                       = _uint16_and( x, h_e_mask );
     500           0 :   const uint16_t y_e                       = _uint16_and( y, h_e_mask );
     501           0 :   const uint16_t is_y_e_larger_msb         = _uint16_sub( x_e, y_e );
     502           0 :   const uint16_t a                         = _uint16_sels( is_y_e_larger_msb, y, x);
     503           0 :   const uint16_t a_s                       = _uint16_and( a, h_s_mask );
     504           0 :   const uint16_t a_e                       = _uint16_and( a, h_e_mask );
     505           0 :   const uint16_t a_m_no_hidden_bit         = _uint16_and( a, h_m_mask );
     506           0 :   const uint16_t a_em_no_hidden_bit        = _uint16_or( a_e, a_m_no_hidden_bit );
     507           0 :   const uint16_t b                         = _uint16_sels( is_y_e_larger_msb, x, y);
     508           0 :   const uint16_t b_s                       = _uint16_and( b, h_s_mask );
     509           0 :   const uint16_t b_e                       = _uint16_and( b, h_e_mask );
     510           0 :   const uint16_t b_m_no_hidden_bit         = _uint16_and( b, h_m_mask );
     511           0 :   const uint16_t b_em_no_hidden_bit        = _uint16_or( b_e, b_m_no_hidden_bit );
     512           0 :   const uint16_t is_diff_sign_msb          = _uint16_xor( a_s, b_s );
     513           0 :   const uint16_t is_a_inf_msb              = _uint16_sub( h_e_mask_minus_one, a_em_no_hidden_bit );
     514           0 :   const uint16_t is_b_inf_msb              = _uint16_sub( h_e_mask_minus_one, b_em_no_hidden_bit );
     515           0 :   const uint16_t is_undenorm_msb           = _uint16_dec( a_e );
     516           0 :   const uint16_t is_undenorm               = _uint16_ext( is_undenorm_msb );
     517           0 :   const uint16_t is_both_inf_msb           = _uint16_and( is_a_inf_msb, is_b_inf_msb );
     518           0 :   const uint16_t is_invalid_inf_op_msb     = _uint16_and( is_both_inf_msb, b_s );
     519           0 :   const uint16_t is_a_e_nez_msb            = _uint16_neg( a_e );
     520           0 :   const uint16_t is_b_e_nez_msb            = _uint16_neg( b_e );
     521           0 :   const uint16_t is_a_e_nez                = _uint16_ext( is_a_e_nez_msb );
     522           0 :   const uint16_t is_b_e_nez                = _uint16_ext( is_b_e_nez_msb );
     523           0 :   const uint16_t a_m_hidden_bit            = _uint16_and( is_a_e_nez, h_m_hidden );
     524           0 :   const uint16_t b_m_hidden_bit            = _uint16_and( is_b_e_nez, h_m_hidden );
     525           0 :   const uint16_t a_m_no_grs                = _uint16_or( a_m_no_hidden_bit, a_m_hidden_bit );
     526           0 :   const uint16_t b_m_no_grs                = _uint16_or( b_m_no_hidden_bit, b_m_hidden_bit );
     527           0 :   const uint16_t diff_e                    = _uint16_sub( a_e,        b_e );
     528           0 :   const uint16_t a_e_unbias                = _uint16_sub( a_e,        h_e_bias_minus_one );
     529           0 :   const uint16_t a_m                       = _uint16_sll( a_m_no_grs, h_grs_size );
     530           0 :   const uint16_t a_e_biased                = _uint16_srl( a_e,        h_e_pos );
     531           0 :   const uint16_t m_sa_unbias               = _uint16_srl( a_e_unbias, h_e_pos );
     532           0 :   const uint16_t m_sa_default              = _uint16_srl( diff_e,     h_e_pos );
     533           0 :   const uint16_t m_sa_unbias_mask          = _uint16_andc( is_a_e_nez_msb,   is_b_e_nez_msb );
     534           0 :   const uint16_t m_sa                      = _uint16_sels( m_sa_unbias_mask, m_sa_unbias, m_sa_default );
     535           0 :   const uint16_t b_m_no_sticky             = _uint16_sll( b_m_no_grs,        h_grs_size );
     536           0 :   const uint16_t sh_m                      = _uint16_srl( b_m_no_sticky,     m_sa );
     537           0 :   const uint16_t sticky_overflow           = _uint16_sll( one,               m_sa );
     538           0 :   const uint16_t sticky_mask               = _uint16_dec( sticky_overflow );
     539           0 :   const uint16_t sticky_collect            = _uint16_and( b_m_no_sticky, sticky_mask );
     540           0 :   const uint16_t is_sticky_set_msb         = _uint16_neg( sticky_collect );
     541           0 :   const uint16_t sticky                    = _uint16_srl( is_sticky_set_msb, msb_to_lsb_sa);
     542           0 :   const uint16_t b_m                       = _uint16_or( sh_m, sticky );
     543           0 :   const uint16_t is_c_m_ab_pos_msb         = _uint16_sub( b_m, a_m );
     544           0 :   const uint16_t c_inf                     = _uint16_or( a_s, h_e_mask );
     545           0 :   const uint16_t c_m_sum                   = _uint16_add( a_m, b_m );
     546           0 :   const uint16_t c_m_diff_ab               = _uint16_sub( a_m, b_m );
     547           0 :   const uint16_t c_m_diff_ba               = _uint16_sub( b_m, a_m );
     548           0 :   const uint16_t c_m_smag_diff             = _uint16_sels( is_c_m_ab_pos_msb, c_m_diff_ab, c_m_diff_ba );
     549           0 :   const uint16_t c_s_diff                  = _uint16_sels( is_c_m_ab_pos_msb, a_s,         b_s         );
     550           0 :   const uint16_t c_s                       = _uint16_sels( is_diff_sign_msb,  c_s_diff,    a_s         );
     551           0 :   const uint16_t c_m_smag_diff_nlz         = _uint16_cntlz( c_m_smag_diff );
     552           0 :   const uint16_t diff_norm_sa              = _uint16_sub( c_m_smag_diff_nlz, one );
     553           0 :   const uint16_t is_diff_denorm_msb        = _uint16_sub( a_e_biased, diff_norm_sa );
     554           0 :   const uint16_t is_diff_denorm            = _uint16_ext( is_diff_denorm_msb );
     555           0 :   const uint16_t is_a_or_b_norm_msb        = _uint16_neg( a_e_biased );
     556           0 :   const uint16_t diff_denorm_sa            = _uint16_dec( a_e_biased );
     557           0 :   const uint16_t c_m_diff_denorm           = _uint16_sll( c_m_smag_diff, diff_denorm_sa );
     558           0 :   const uint16_t c_m_diff_norm             = _uint16_sll( c_m_smag_diff, diff_norm_sa );
     559           0 :   const uint16_t c_e_diff_norm             = _uint16_sub( a_e_biased,  diff_norm_sa );
     560           0 :   const uint16_t c_m_diff_ab_norm          = _uint16_sels( is_diff_denorm_msb, c_m_diff_denorm, c_m_diff_norm );
     561           0 :   const uint16_t c_e_diff_ab_norm          = _uint16_andc( c_e_diff_norm, is_diff_denorm );
     562           0 :   const uint16_t c_m_diff                  = _uint16_sels( is_a_or_b_norm_msb, c_m_diff_ab_norm, c_m_smag_diff );
     563           0 :   const uint16_t c_e_diff                  = _uint16_sels( is_a_or_b_norm_msb, c_e_diff_ab_norm, a_e_biased    );
     564           0 :   const uint16_t is_diff_eqz_msb           = _uint16_dec( c_m_diff );
     565           0 :   const uint16_t is_diff_exactly_zero_msb  = _uint16_and( is_diff_sign_msb, is_diff_eqz_msb );
     566           0 :   const uint16_t is_diff_exactly_zero      = _uint16_ext( is_diff_exactly_zero_msb );
     567           0 :   const uint16_t c_m_added                 = _uint16_sels( is_diff_sign_msb, c_m_diff, c_m_sum );
     568           0 :   const uint16_t c_e_added                 = _uint16_sels( is_diff_sign_msb, c_e_diff, a_e_biased );
     569           0 :   const uint16_t c_m_carry                 = _uint16_and( c_m_added, h_m_grs_carry );
     570           0 :   const uint16_t is_c_m_carry_msb          = _uint16_neg( c_m_carry );
     571           0 :   const uint16_t c_e_hidden_offset         = _uint16_andsrl( c_m_added, h_m_grs_carry, h_m_grs_carry_pos );
     572           0 :   const uint16_t c_m_sub_hidden            = _uint16_srl( c_m_added, one );
     573           0 :   const uint16_t c_m_no_hidden             = _uint16_sels( is_c_m_carry_msb, c_m_sub_hidden, c_m_added );
     574           0 :   const uint16_t c_e_no_hidden             = _uint16_add( c_e_added,         c_e_hidden_offset  );
     575           0 :   const uint16_t c_m_no_hidden_msb         = _uint16_and( c_m_no_hidden,     h_m_msb_mask       );
     576           0 :   const uint16_t undenorm_m_msb_odd        = _uint16_srl( c_m_no_hidden_msb, h_m_msb_sa         );
     577           0 :   const uint16_t undenorm_fix_e            = _uint16_and( is_undenorm,       undenorm_m_msb_odd );
     578           0 :   const uint16_t c_e_fixed                 = _uint16_add( c_e_no_hidden,     undenorm_fix_e     );
     579           0 :   const uint16_t c_m_round_amount          = _uint16_and( c_m_no_hidden,     h_grs_round_mask   );
     580           0 :   const uint16_t c_m_rounded               = _uint16_add( c_m_no_hidden,     c_m_round_amount   );
     581           0 :   const uint16_t c_m_round_overflow        = _uint16_andsrl( c_m_rounded, h_m_grs_carry, h_m_grs_carry_pos );
     582           0 :   const uint16_t c_e_rounded               = _uint16_add( c_e_fixed, c_m_round_overflow );
     583           0 :   const uint16_t c_m_no_grs                = _uint16_srlm( c_m_rounded, h_grs_size,  h_m_mask );
     584           0 :   const uint16_t c_e                       = _uint16_sll( c_e_rounded, h_e_pos );
     585           0 :   const uint16_t c_em                      = _uint16_or( c_e, c_m_no_grs );
     586           0 :   const uint16_t c_normal                  = _uint16_or( c_s, c_em );
     587           0 :   const uint16_t c_inf_result              = _uint16_sels( is_a_inf_msb, c_inf, c_normal );
     588           0 :   const uint16_t c_zero_result             = _uint16_andc( c_inf_result, is_diff_exactly_zero );
     589           0 :   const uint16_t c_result                  = _uint16_sels( is_invalid_inf_op_msb, h_snan, c_zero_result );
     590             : 
     591           0 :   return (c_result);
     592             : }
     593             : 
     594             : // half_mul
     595             : // --------
     596             : //
     597             : //  May have 0 or 1 ulp difference from the following result:
     598             : //  (Round to nearest)
     599             : //  NOTE: Rounding mode differs between conversion and multiply
     600             : //
     601             : //     union FLOAT_32
     602             : //     {
     603             : //       float    f32;
     604             : //       uint32_t u32;
     605             : //     };
     606             : //
     607             : //     union FLOAT_32 fx = { .u32 = half_to_float( x ) };
     608             : //     union FLOAT_32 fy = { .u32 = half_to_float( y ) };
     609             : //     union FLOAT_32 fz = { .f32 = fx.f32 * fy.f32    };
     610             : //     uint16_t       z  = float_to_half( fz );
     611             : //
     612             : uint16_t
     613           0 : half_mul( uint16_t x, uint16_t y )
     614             : {
     615           0 :   const uint32_t one                                = _uint32_li( 0x00000001 );
     616           0 :   const uint32_t h_s_mask                           = _uint32_li( 0x00008000 );
     617           0 :   const uint32_t h_e_mask                           = _uint32_li( 0x00007c00 );
     618           0 :   const uint32_t h_m_mask                           = _uint32_li( 0x000003ff );
     619           0 :   const uint32_t h_m_hidden                         = _uint32_li( 0x00000400 );
     620           0 :   const uint32_t h_e_pos                            = _uint32_li( 0x0000000a );
     621           0 :   const uint32_t h_e_bias                           = _uint32_li( 0x0000000f );
     622           0 :   const uint32_t h_m_bit_count                      = _uint32_li( 0x0000000a );
     623           0 :   const uint32_t h_m_bit_half_count                 = _uint32_li( 0x00000005 );
     624           0 :   const uint32_t h_nan_min                          = _uint32_li( 0x00007c01 );
     625           0 :   const uint32_t h_e_mask_minus_one                 = _uint32_li( 0x00007bff );
     626           0 :   const uint32_t h_snan                             = _uint32_li( 0x0000fe00 );
     627           0 :   const uint32_t m_round_overflow_bit               = _uint32_li( 0x00000020 );
     628           0 :   const uint32_t m_hidden_bit                       = _uint32_li( 0x00100000 );
     629           0 :   const uint32_t a_s                                = _uint32_and(  x,   h_s_mask );
     630           0 :   const uint32_t b_s                                = _uint32_and(  y,   h_s_mask );
     631           0 :   const uint32_t c_s                                = _uint32_xor(  a_s, b_s      );
     632           0 :   const uint32_t x_e                                = _uint32_and(  x,   h_e_mask );
     633           0 :   const uint32_t x_e_eqz_msb                        = _uint32_dec(  x_e );
     634           0 :   const uint32_t a                                  = _uint32_sels( x_e_eqz_msb, y, x );
     635           0 :   const uint32_t b                                  = _uint32_sels( x_e_eqz_msb, x, y );
     636           0 :   const uint32_t a_e                                = _uint32_and(  a,   h_e_mask );
     637           0 :   const uint32_t b_e                                = _uint32_and(  b,   h_e_mask );
     638           0 :   const uint32_t a_m                                = _uint32_and(  a,   h_m_mask );
     639           0 :   const uint32_t b_m                                = _uint32_and(  b,   h_m_mask );
     640           0 :   const uint32_t a_e_amount                         = _uint32_srl(  a_e,                 h_e_pos                 );
     641           0 :   const uint32_t b_e_amount                         = _uint32_srl(  b_e,                 h_e_pos                 );
     642           0 :   const uint32_t a_m_with_hidden                    = _uint32_or(   a_m,                 h_m_hidden              );
     643           0 :   const uint32_t b_m_with_hidden                    = _uint32_or(   b_m,                 h_m_hidden              );
     644           0 :   const uint32_t c_m_normal                         = _uint32_mul(  a_m_with_hidden,     b_m_with_hidden         );
     645           0 :   const uint32_t c_m_denorm_biased                  = _uint32_mul(  a_m_with_hidden,     b_m                     );
     646           0 :   const uint32_t c_e_denorm_unbias_e                = _uint32_sub(  h_e_bias,            a_e_amount              );
     647           0 :   const uint32_t c_m_denorm_round_amount            = _uint32_and(  c_m_denorm_biased,   h_m_mask                );
     648           0 :   const uint32_t c_m_denorm_rounded                 = _uint32_add(  c_m_denorm_biased,   c_m_denorm_round_amount );
     649           0 :   const uint32_t c_m_denorm_inplace                 = _uint32_srl(  c_m_denorm_rounded,  h_m_bit_count           );
     650           0 :   const uint32_t c_m_denorm_unbiased                = _uint32_srl(  c_m_denorm_inplace,  c_e_denorm_unbias_e     );
     651           0 :   const uint32_t c_m_denorm                         = _uint32_and(  c_m_denorm_unbiased, h_m_mask                );
     652           0 :   const uint32_t c_e_amount_biased                  = _uint32_add(  a_e_amount,          b_e_amount              );
     653           0 :   const uint32_t c_e_amount_unbiased                = _uint32_sub(  c_e_amount_biased,   h_e_bias                );
     654           0 :   const uint32_t is_c_e_unbiased_underflow          = _uint32_ext(  c_e_amount_unbiased );
     655           0 :   const uint32_t c_e_underflow_half_sa              = _uint32_neg(  c_e_amount_unbiased );
     656           0 :   const uint32_t c_e_underflow_sa                   = _uint32_sll(  c_e_underflow_half_sa,     one );
     657           0 :   const uint32_t c_m_underflow                      = _uint32_srl(  c_m_normal,                c_e_underflow_sa );
     658           0 :   const uint32_t c_e_underflow_added                = _uint32_andc( c_e_amount_unbiased,       is_c_e_unbiased_underflow );
     659           0 :   const uint32_t c_m_underflow_added                = _uint32_selb( is_c_e_unbiased_underflow, c_m_underflow, c_m_normal );
     660           0 :   const uint32_t is_mul_overflow_test               = _uint32_and(  c_e_underflow_added, m_round_overflow_bit );
     661           0 :   const uint32_t is_mul_overflow_msb                = _uint32_neg(  is_mul_overflow_test );
     662           0 :   const uint32_t c_e_norm_radix_corrected           = _uint32_inc(  c_e_underflow_added );
     663           0 :   const uint32_t c_m_norm_radix_corrected           = _uint32_srl(  c_m_underflow_added, one );
     664           0 :   const uint32_t c_m_norm_hidden_bit                = _uint32_and(  c_m_norm_radix_corrected,  m_hidden_bit );
     665           0 :   const uint32_t is_c_m_norm_no_hidden_msb          = _uint32_dec(  c_m_norm_hidden_bit );
     666           0 :   const uint32_t c_m_norm_lo                        = _uint32_srl(  c_m_norm_radix_corrected, h_m_bit_half_count );
     667           0 :   const uint32_t c_m_norm_lo_nlz                    = _uint16_cntlz( c_m_norm_lo );
     668           0 :   const uint32_t is_c_m_hidden_nunderflow_msb       = _uint32_sub(  c_m_norm_lo_nlz, c_e_norm_radix_corrected );
     669           0 :   const uint32_t is_c_m_hidden_underflow_msb        = _uint32_not(  is_c_m_hidden_nunderflow_msb );
     670           0 :   const uint32_t is_c_m_hidden_underflow            = _uint32_ext(  is_c_m_hidden_underflow_msb  );
     671           0 :   const uint32_t c_m_hidden_underflow_normalized_sa = _uint32_srl(  c_m_norm_lo_nlz, one );
     672           0 :   const uint32_t c_m_hidden_underflow_normalized    = _uint32_sll(  c_m_norm_radix_corrected, c_m_hidden_underflow_normalized_sa );
     673           0 :   const uint32_t c_m_hidden_normalized              = _uint32_sll(  c_m_norm_radix_corrected, c_m_norm_lo_nlz );
     674           0 :   const uint32_t c_e_hidden_normalized              = _uint32_sub(  c_e_norm_radix_corrected, c_m_norm_lo_nlz );
     675           0 :   const uint32_t c_e_hidden                         = _uint32_andc( c_e_hidden_normalized, is_c_m_hidden_underflow );
     676           0 :   const uint32_t c_m_hidden                         = _uint32_sels( is_c_m_hidden_underflow_msb, c_m_hidden_underflow_normalized, c_m_hidden_normalized );
     677           0 :   const uint32_t c_m_normalized                     = _uint32_sels( is_c_m_norm_no_hidden_msb, c_m_hidden, c_m_norm_radix_corrected );
     678           0 :   const uint32_t c_e_normalized                     = _uint32_sels( is_c_m_norm_no_hidden_msb, c_e_hidden, c_e_norm_radix_corrected );
     679           0 :   const uint32_t c_m_norm_round_amount              = _uint32_and(  c_m_normalized, h_m_mask );
     680           0 :   const uint32_t c_m_norm_rounded                   = _uint32_add(  c_m_normalized, c_m_norm_round_amount );
     681           0 :   const uint32_t is_round_overflow_test             = _uint32_and(  c_e_normalized, m_round_overflow_bit  );
     682           0 :   const uint32_t is_round_overflow_msb              = _uint32_neg(  is_round_overflow_test );
     683           0 :   const uint32_t c_m_norm_inplace                   = _uint32_srl(  c_m_norm_rounded,    h_m_bit_count );
     684           0 :   const uint32_t c_m                                = _uint32_and(  c_m_norm_inplace,    h_m_mask      );
     685           0 :   const uint32_t c_e_norm_inplace                   = _uint32_sll(  c_e_normalized, h_e_pos       );
     686           0 :   const uint32_t c_e                                = _uint32_and(  c_e_norm_inplace,    h_e_mask      );
     687           0 :   const uint32_t c_em_nan                           = _uint32_or(   h_e_mask,  a_m        );
     688           0 :   const uint32_t c_nan                              = _uint32_or(   a_s,       c_em_nan   );
     689           0 :   const uint32_t c_denorm                           = _uint32_or(   c_s,       c_m_denorm );
     690           0 :   const uint32_t c_inf                              = _uint32_or(   c_s,       h_e_mask   );
     691           0 :   const uint32_t c_em_norm                          = _uint32_or(   c_e,       c_m        );
     692           0 :   const uint32_t is_a_e_flagged_msb                 = _uint32_sub(  h_e_mask_minus_one, a_e );
     693           0 :   const uint32_t is_b_e_flagged_msb                 = _uint32_sub(  h_e_mask_minus_one, b_e );
     694           0 :   const uint32_t is_a_e_eqz_msb                     = _uint32_dec(  a_e );
     695           0 :   const uint32_t is_a_m_eqz_msb                     = _uint32_dec(  a_m );
     696           0 :   const uint32_t is_b_e_eqz_msb                     = _uint32_dec(  b_e );
     697           0 :   const uint32_t is_b_m_eqz_msb                     = _uint32_dec(  b_m );
     698           0 :   const uint32_t is_b_eqz_msb                       = _uint32_and(  is_b_e_eqz_msb,          is_b_m_eqz_msb         );
     699           0 :   const uint32_t is_a_eqz_msb                       = _uint32_and(  is_a_e_eqz_msb,          is_a_m_eqz_msb         );
     700           0 :   const uint32_t is_c_nan_via_a_msb                 = _uint32_andc( is_a_e_flagged_msb,      is_b_e_flagged_msb     );
     701           0 :   const uint32_t is_c_nan_via_b_msb                 = _uint32_andc( is_b_e_flagged_msb,      is_b_m_eqz_msb         );
     702           0 :   const uint32_t is_c_nan_msb                       = _uint32_or(   is_c_nan_via_a_msb,      is_c_nan_via_b_msb     );
     703           0 :   const uint32_t is_c_denorm_msb                    = _uint32_andc( is_b_e_eqz_msb,          is_a_e_flagged_msb     );
     704           0 :   const uint32_t is_a_inf_msb                       = _uint32_and(  is_a_e_flagged_msb,      is_a_m_eqz_msb         );
     705           0 :   const uint32_t is_c_snan_msb                      = _uint32_and(  is_a_inf_msb,            is_b_eqz_msb           );
     706           0 :   const uint32_t is_c_nan_min_via_a_msb             = _uint32_and(  is_a_e_flagged_msb,      is_b_eqz_msb           );
     707           0 :   const uint32_t is_c_nan_min_via_b_msb             = _uint32_and(  is_b_e_flagged_msb,      is_a_eqz_msb           );
     708           0 :   const uint32_t is_c_nan_min_msb                   = _uint32_or(   is_c_nan_min_via_a_msb,  is_c_nan_min_via_b_msb );
     709           0 :   const uint32_t is_c_inf_msb                       = _uint32_or(   is_a_e_flagged_msb,      is_b_e_flagged_msb     );
     710           0 :   const uint32_t is_overflow_msb                    = _uint32_or(   is_round_overflow_msb,   is_mul_overflow_msb    );
     711           0 :   const uint32_t c_em_overflow_result               = _uint32_sels( is_overflow_msb, h_e_mask, c_em_norm );
     712           0 :   const uint32_t c_common_result                    = _uint32_or(   c_s, c_em_overflow_result );
     713           0 :   const uint32_t c_zero_result                      = _uint32_sels( is_b_eqz_msb,     c_s,       c_common_result  );
     714           0 :   const uint32_t c_nan_result                       = _uint32_sels( is_c_nan_msb,     c_nan,     c_zero_result );
     715           0 :   const uint32_t c_nan_min_result                   = _uint32_sels( is_c_nan_min_msb, h_nan_min, c_nan_result     );
     716           0 :   const uint32_t c_inf_result                       = _uint32_sels( is_c_inf_msb,     c_inf,     c_nan_min_result   );
     717           0 :   const uint32_t c_denorm_result                    = _uint32_sels( is_c_denorm_msb,  c_denorm,  c_inf_result);
     718           0 :   const uint32_t c_result                           = _uint32_sels( is_c_snan_msb,    h_snan,    c_denorm_result );
     719             : 
     720           0 :   return (uint16_t)(c_result);
     721             : }

Generated by: LCOV version 1.10