LCOV - code coverage report
Current view: top level - src/acl_stub - kernel_fp16.cpp (source / functions) Coverage Total Hit
Test: coverage.info_filtered Lines: 43.8 % 793 347
Test Date: 2026-07-27 14:41:20 Functions: 45.6 % 79 36

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 2025 Huawei Technologies Co., Ltd.
       3              :  * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
       4              :  * CANN Open Software License Agreement Version 2.0 (the "License").
       5              :  * Please refer to the License for details. You may not use this file except in compliance with the License.
       6              :  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
       7              :  * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
       8              :  * See LICENSE in the root of the software repository for the full text of the License.
       9              :  */
      10              : 
      11              : /*!
      12              :  * \file kernel_fp16.cpp
      13              :  * \brief
      14              :  */
      15              : #include "kernel_fp16.h"
      16              : 
      17              : namespace {
      18              : constexpr uint16_t K_MAN_BIT_LENGTH = 11;
      19              : constexpr int16_t HFEXP_NUM = 31;
      20              : constexpr uint32_t ERET_NUM = 255;
      21              : } // namespace
      22              : 
      23              : // namespace float16 {
      24              : /**
      25              :  * @ingroup half global filed
      26              :  * @brief   round mode of last valid digital
      27              :  */
      28              : const enum TagFp16RoundMode ROUND_MODE = TagFp16RoundMode::K_ROUND_TO_NEAREST;
      29              : 
      30           36 : void ExtractFp16(const uint16_t& val, uint16_t& s, int16_t& e, uint16_t& m)
      31              : {
      32              :     // 1.Extract
      33           36 :     s = FP16_EXTRAC_SIGN(val);
      34           36 :     e = FP16_EXTRAC_EXP(val);
      35           36 :     m = FP16_EXTRAC_MAN(val);
      36              :     // Denormal
      37           36 :     if (e == 0) {
      38            4 :         e = 1;
      39              :     }
      40           36 : }
      41              : 
      42              : /**
      43              :  * @ingroup half static method
      44              :  * @param [in] man       truncated mantissa
      45              :  * @param [in] shiftOut left shift bits based on ten bits
      46              :  * @brief   judge whether to add one to the result while converting half to
      47              :  * other datatype
      48              :  * @return  Return true if add one, otherwise false
      49              :  */
      50           38 : static bool IsRoundOne(uint64_t man, uint16_t truncLen)
      51              : {
      52           38 :     uint64_t mask0 = 0x4;
      53           38 :     uint64_t mask1 = 0x2;
      54              :     uint64_t mask2;
      55           38 :     uint16_t shiftOut = static_cast<uint16_t>(truncLen - static_cast<uint16_t>(DimIndex::K_DIM2));
      56           38 :     mask0 = mask0 << shiftOut;
      57           38 :     mask1 = mask1 << shiftOut;
      58           38 :     mask2 = mask1 - 1;
      59              : 
      60           38 :     bool lastBit = ((man & mask0) > 0);
      61           38 :     bool truncHigh = false;
      62           38 :     bool truncLeft = false;
      63              :     if (ROUND_MODE == TagFp16RoundMode::K_ROUND_TO_NEAREST) {
      64           38 :         truncHigh = ((man & mask1) > 0);
      65           38 :         truncLeft = ((man & mask2) > 0);
      66              :     }
      67           38 :     return (truncHigh && (truncLeft || lastBit));
      68              : }
      69              : 
      70              : /**
      71              :  * @ingroup half public method
      72              :  * @param [in] exp       exponent of half value
      73              :  * @param [in] man       exponent of half value
      74              :  * @brief   normalize half value
      75              :  * @return
      76              :  */
      77           24 : static void Fp16Normalize(int16_t& exp, uint16_t& man)
      78              : {
      79              :     // set to invalid data
      80           24 :     if (exp >= static_cast<int16_t>(Fp16BasicParam::K_FP16_MAX_EXP)) {
      81            2 :         exp = static_cast<int16_t>(Fp16BasicParam::K_FP16_MAX_EXP);
      82            2 :         man = static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAX_MAN);
      83           22 :     } else if ((exp == 0) && (man == static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_HIDE_BIT))) {
      84            0 :         exp++;
      85            0 :         man = 0;
      86              :     }
      87           24 : }
      88              : 
      89              : /**
      90              :  * @ingroup half math conversion static method
      91              :  * @param [in] fpVal uint16_t value of half object
      92              :  * @brief   Convert half to float/fp32
      93              :  * @return  Return float/fp32 value of fpVal which is the value of half object
      94              :  */
      95           18 : static float Fp16ToFloat(const uint16_t& fpVal)
      96              : {
      97              :     uint16_t hfSign;
      98              :     uint16_t hfMan;
      99              :     int16_t hfExp;
     100           18 :     ExtractFp16(fpVal, hfSign, hfExp, hfMan);
     101              : 
     102           18 :     while ((hfMan != 0) && ((hfMan & static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_HIDE_BIT)) == 0)) {
     103            0 :         hfMan <<= 1;
     104            0 :         hfExp--;
     105              :     }
     106              : 
     107              :     uint32_t eRet;
     108              :     uint32_t mRet;
     109           18 :     uint32_t sRet = hfSign;
     110              : 
     111           18 :     if (hfExp == HFEXP_NUM) {
     112            2 :         eRet = ERET_NUM;
     113            2 :         mRet = hfMan
     114            2 :                << (static_cast<uint32_t>(Fp32BasicParam::K_FP32_MAN_LEN) -
     115              :                    static_cast<uint32_t>(Fp16BasicParam::K_FP16_MAN_LEN));
     116            2 :         uint32_t fVal = FP32_CONSTRUCTOR(sRet, eRet, mRet);
     117            2 :         auto pRetV = reinterpret_cast<float*>(&fVal);
     118              : 
     119            2 :         return *pRetV;
     120              :     }
     121              : 
     122           16 :     if (hfMan == 0) {
     123            4 :         eRet = 0;
     124            4 :         mRet = 0;
     125              :     } else {
     126           12 :         eRet = (static_cast<uint32_t>(hfExp) - static_cast<uint32_t>(Fp16BasicParam::K_FP16_EXP_BIAS)) +
     127              :                static_cast<uint32_t>(Fp32BasicParam::K_FP32_EXP_BIAS);
     128           12 :         mRet = static_cast<uint32_t>(hfMan & static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_MASK));
     129           12 :         mRet = mRet
     130              :                << (static_cast<uint32_t>(Fp32BasicParam::K_FP32_MAN_LEN) -
     131              :                    static_cast<uint32_t>(Fp16BasicParam::K_FP16_MAN_LEN));
     132              :     }
     133           16 :     uint32_t fVal = FP32_CONSTRUCTOR(sRet, eRet, mRet);
     134           16 :     auto pRetV = reinterpret_cast<float*>(&fVal);
     135              : 
     136           16 :     return *pRetV;
     137              : }
     138              : 
     139              : /**
     140              :  * @ingroup half math conversion static method
     141              :  * @param [in] fpVal uint16_t value of half object
     142              :  * @brief   Convert half to double/fp64
     143              :  * @return  Return double/fp64 value of fpVal which is the value of half object
     144              :  */
     145            2 : static double Fp16ToDouble(const uint16_t& fpVal)
     146              : {
     147              :     uint16_t hfSign;
     148              :     uint16_t hfMan;
     149              :     int16_t hfExp;
     150            2 :     ExtractFp16(fpVal, hfSign, hfExp, hfMan);
     151              : 
     152            2 :     while ((hfMan != 0) && ((hfMan & static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_HIDE_BIT)) == 0)) {
     153            0 :         hfMan <<= 1;
     154            0 :         hfExp--;
     155              :     }
     156              : 
     157              :     uint64_t eRet;
     158              :     uint64_t mRet;
     159            2 :     if (hfMan == 0) {
     160            0 :         eRet = 0;
     161            0 :         mRet = 0;
     162              :     } else {
     163            2 :         eRet = (static_cast<uint64_t>(hfExp) - static_cast<uint64_t>(Fp16BasicParam::K_FP16_EXP_BIAS)) +
     164              :                static_cast<uint64_t>(Fp64BasicParam::K_FP64_EXP_BIAS);
     165            2 :         mRet = hfMan & static_cast<uint64_t>(Fp16BasicParam::K_FP16_MAN_MASK);
     166            2 :         mRet = mRet
     167              :                << (static_cast<uint64_t>(Fp64BasicParam::K_FP64_MAN_LEN) -
     168              :                    static_cast<uint64_t>(Fp16BasicParam::K_FP16_MAN_LEN));
     169              :     }
     170            2 :     uint64_t fVal = (static_cast<uint64_t>(hfSign) << static_cast<uint64_t>(Fp64BasicParam::K_FP64_SIGN_INDEX)) |
     171            2 :                     (eRet << static_cast<uint64_t>(Fp64BasicParam::K_FP64_MAN_LEN)) | (mRet);
     172            2 :     auto pRetV = reinterpret_cast<double*>(&fVal);
     173              : 
     174            2 :     return *pRetV;
     175              : }
     176              : 
     177              : // / @ingroup half static method
     178              : // / @param [in] sRet       sign of half value
     179              : // / @param [in] longIntM   man uint64_t value of half object
     180              : // / @param [in] shiftOut   shift offset
     181              : // / @brief   calculate uint8 value by sign,man and shift offset
     182              : // / @return Return uint8 value of half object
     183            0 : static uint8_t GetUint8ValByMan(uint8_t sRet, const uint64_t& longIntM, const uint16_t& shiftOut)
     184              : {
     185            0 :     bool needRound = IsRoundOne(longIntM, shiftOut + static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_LEN));
     186            0 :     auto mRet = static_cast<uint8_t>(
     187            0 :         (longIntM >> (static_cast<uint32_t>(Fp16BasicParam::K_FP16_MAN_LEN) + static_cast<uint32_t>(shiftOut))) &
     188              :         static_cast<uint8_t>(NumBitMax::K_BIT_LEN8_MAX));
     189            0 :     needRound = needRound && (((sRet == 0) && (mRet < static_cast<uint8_t>(NumBitMax::K_INT8_MAX))) ||
     190            0 :                               ((sRet == 1) && (mRet <= static_cast<uint8_t>(NumBitMax::K_INT8_MAX))));
     191            0 :     if (needRound) {
     192            0 :         mRet++;
     193              :     }
     194            0 :     if (sRet != 0) {
     195            0 :         mRet = (~mRet) + 1;
     196              :     }
     197            0 :     if (mRet == 0) {
     198            0 :         sRet = 0;
     199              :     }
     200            0 :     return static_cast<uint8_t>((sRet << static_cast<uint16_t>(BitShift::K_BIT_SHIFT7)) | (mRet));
     201              : }
     202              : 
     203            2 : static void CalcOverflowFlagInt8(
     204              :     const uint8_t& sRet, uint16_t& hfE, uint64_t& longIntM, uint8_t& overflowFlag, uint16_t& shiftOut)
     205              : {
     206           14 :     while (hfE != static_cast<uint16_t>(Fp16BasicParam::K_FP16_EXP_BIAS)) {
     207           14 :         if (hfE > static_cast<uint16_t>(Fp16BasicParam::K_FP16_EXP_BIAS)) {
     208           14 :             hfE--;
     209           14 :             longIntM = longIntM << 1;
     210           14 :             if ((sRet == 1) && (longIntM >= 0x20000u)) { // sign=1,negative number(<0)
     211            0 :                 longIntM = 0x20000u;                     // 10 0000 0000 0000 0000  10(half-man)+7(int8)=17bit
     212            0 :                 overflowFlag = 1;
     213            0 :                 break;
     214           14 :             } else if ((sRet != 1) && (longIntM >= 0x1FFFFu)) { // sign=0,positive number(>0)
     215            2 :                 longIntM = 0x1FFFFu;                            // 01 1111 1111 1111 1111  10(half-man)+7(int8)
     216            2 :                 overflowFlag = 1;
     217            2 :                 break;
     218              :             }
     219              :         } else {
     220            0 :             hfE++;
     221            0 :             shiftOut++;
     222              :         }
     223              :     }
     224            2 : }
     225              : 
     226              : /**
     227              :  * @ingroup half math conversion static method
     228              :  * @param [in] fpVal uint16_t value of half object
     229              :  * @brief   Convert half to int8_t
     230              :  * @return  Return int8_t value of fpVal which is the value of half object
     231              :  */
     232            2 : static int8_t Fp16ToInt8(const uint16_t& fpVal)
     233              : {
     234              :     uint8_t ret;
     235              :     // 1.get sRet and shift it to bit0.
     236            2 :     uint8_t sRet = static_cast<uint8_t>(FP16_EXTRAC_SIGN(fpVal));
     237              :     // 2.get hfE and hfM
     238            2 :     uint16_t hfE = static_cast<uint16_t>(FP16_EXTRAC_EXP(fpVal));
     239            2 :     uint16_t hfM = FP16_EXTRAC_MAN(fpVal);
     240              : 
     241            2 :     if (FP16_IS_DENORM(fpVal)) { // Denormalized number
     242            0 :         return 0;
     243              :     }
     244              : 
     245            2 :     uint64_t longIntM = hfM;
     246            2 :     uint8_t overflowFlag = 0;
     247            2 :     uint16_t shiftOut = 0;
     248            2 :     if (FP16_IS_INVALID(fpVal)) { // Inf or NaN
     249            0 :         overflowFlag = 1;
     250              :     } else {
     251            2 :         CalcOverflowFlagInt8(sRet, hfE, longIntM, overflowFlag, shiftOut);
     252              :     }
     253            2 :     if (overflowFlag != 0) {
     254            2 :         ret = static_cast<uint8_t>(NumBitMax::K_INT8_MAX) + sRet;
     255              :     } else {
     256              :         // Generate final result
     257            0 :         ret = GetUint8ValByMan(sRet, longIntM, shiftOut);
     258              :     }
     259              : 
     260            2 :     return static_cast<int8_t>(ret);
     261              : }
     262              : 
     263            2 : static void CalcOverflowFlagUInt8(
     264              :     uint16_t& hfE, uint64_t& longIntM, uint8_t& overflowFlag, uint8_t& mRet, uint16_t& shiftOut)
     265              : {
     266           16 :     while (hfE != static_cast<uint16_t>(Fp16BasicParam::K_FP16_EXP_BIAS)) {
     267           16 :         if (hfE > static_cast<uint16_t>(Fp16BasicParam::K_FP16_EXP_BIAS)) {
     268           16 :             hfE--;
     269           16 :             longIntM = longIntM << 1;
     270           16 :             if (longIntM >= 0x40000Lu) { // overflow 0100 0000 0000 0000 0000
     271            2 :                 longIntM = 0x3FFFFLu;    // 11 1111 1111 1111 1111   10(half-man)+8(uint8)=18bit
     272            2 :                 overflowFlag = 1;
     273            2 :                 mRet = ~0;
     274            2 :                 break;
     275              :             }
     276              :         } else {
     277            0 :             hfE++;
     278            0 :             shiftOut++;
     279              :         }
     280              :     }
     281            2 : }
     282              : 
     283              : /**
     284              :  * @ingroup half math conversion static method
     285              :  * @param [in] fpVal uint16_t value of half object
     286              :  * @brief   Convert half to uint8_t
     287              :  * @return  Return uint8_t value of fpVal which is the value of half object
     288              :  */
     289            2 : static uint8_t Fp16ToUInt8(const uint16_t& fpVal)
     290              : {
     291            2 :     uint8_t mRet = 0;
     292              :     // 1.get sRet and shift it to bit0.
     293            2 :     uint16_t sRet = FP16_EXTRAC_SIGN(fpVal);
     294              :     // 2.get hfE and hfM
     295            2 :     uint16_t hfE = static_cast<uint16_t>(FP16_EXTRAC_EXP(fpVal));
     296            2 :     uint16_t hfM = FP16_EXTRAC_MAN(fpVal);
     297              : 
     298            2 :     if (FP16_IS_DENORM(fpVal)) { // Denormalized number
     299            0 :         return 0;
     300              :     }
     301              : 
     302            2 :     if (FP16_IS_INVALID(fpVal)) { // Inf or NaN
     303            0 :         mRet = ~0;
     304              :     } else {
     305            2 :         uint64_t longIntM = hfM;
     306            2 :         uint8_t overflowFlag = 0;
     307            2 :         uint16_t shiftOut = 0;
     308            2 :         CalcOverflowFlagUInt8(hfE, longIntM, overflowFlag, mRet, shiftOut);
     309            2 :         if (overflowFlag == 0) {
     310            0 :             bool needRound = IsRoundOne(longIntM, shiftOut + static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_LEN));
     311            0 :             mRet = static_cast<uint8_t>(
     312            0 :                 (longIntM >>
     313            0 :                  (static_cast<uint32_t>(Fp16BasicParam::K_FP16_MAN_LEN) + static_cast<uint32_t>(shiftOut))) &
     314              :                 static_cast<uint8_t>(NumBitMax::K_BIT_LEN8_MAX));
     315            0 :             if (needRound && (mRet != static_cast<uint8_t>(NumBitMax::K_BIT_LEN8_MAX))) {
     316            0 :                 mRet++;
     317              :             }
     318              :         }
     319              :     }
     320              : 
     321            2 :     if (sRet == 1) { // Negative number
     322            0 :         mRet = 0;
     323              :     }
     324              :     // mRet equal to final result
     325            2 :     return mRet;
     326              : }
     327              : // / @ingroup half static method
     328              : // / @param [in] sRet       sign of half value
     329              : // / @param [in] longIntM   man uint64_t value of half object
     330              : // / @param [in] shiftOut   shift offset
     331              : // / @brief   calculate uint16 value by sign,man and shift offset
     332              : // / @return Return uint16 value of half object
     333            2 : static uint16_t GetUint16ValByMan(uint16_t sRet, const uint64_t& longIntM, const uint16_t& shiftOut)
     334              : {
     335            2 :     bool needRound = IsRoundOne(longIntM, shiftOut + static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_LEN));
     336            2 :     auto mRet = static_cast<uint16_t>(
     337            2 :         (longIntM >> (static_cast<uint32_t>(Fp16BasicParam::K_FP16_MAN_LEN) + static_cast<uint32_t>(shiftOut))) &
     338              :         static_cast<uint16_t>(NumBitMax::K_BIT_LEN16_MAX));
     339            2 :     if (needRound && (mRet < static_cast<int16_t>(NumBitMax::K_INT16_MAX))) {
     340            0 :         mRet++;
     341              :     }
     342            2 :     if (sRet != 0) {
     343            0 :         mRet = (~mRet) + 1;
     344              :     }
     345            2 :     if (mRet == 0) {
     346            0 :         sRet = 0;
     347              :     }
     348            2 :     return static_cast<uint16_t>((sRet << static_cast<uint16_t>(BitShift::K_BIT_SHIFT15)) | (mRet));
     349              : }
     350              : 
     351            2 : static void CalcOverflowFlagInt16(
     352              :     uint16_t& hfE, uint64_t& longIntM, const uint16_t& sRet, uint8_t& overflowFlag, uint16_t& shiftOut)
     353              : {
     354           30 :     while (hfE != static_cast<uint16_t>(Fp16BasicParam::K_FP16_EXP_BIAS)) {
     355           28 :         if (hfE > static_cast<uint16_t>(Fp16BasicParam::K_FP16_EXP_BIAS)) {
     356           28 :             longIntM = longIntM << 1;
     357           28 :             hfE--;
     358           28 :             if ((sRet == 1) && (longIntM > 0x2000000Lu)) { // sign=1,negative number(<0)
     359            0 :                 longIntM = 0x2000000Lu;                    // 10(half-man)+15(int16)=25bit
     360            0 :                 overflowFlag = 1;
     361            0 :                 break;
     362           28 :             } else if ((sRet != 1) && (longIntM >= 0x1FFFFFFLu)) { // sign=0,positive number(>0) Overflow
     363            0 :                 longIntM = 0x1FFFFFFLu;                            // 10(half-man)+15(int16)=25bit
     364            0 :                 overflowFlag = 1;
     365            0 :                 break;
     366              :             }
     367              :         } else {
     368            0 :             shiftOut++;
     369            0 :             hfE++;
     370              :         }
     371              :     }
     372            2 : }
     373              : /**
     374              :  * @ingroup half math conversion static method
     375              :  * @param [in] fpVal uint16_t value of half object
     376              :  * @brief   Convert half to int16_t
     377              :  * @return  Return int16_t value of fpVal which is the value of half object
     378              :  */
     379            2 : static int16_t Fp16ToInt16(const uint16_t& fpVal)
     380              : {
     381              :     int16_t ret;
     382              :     uint16_t retV;
     383              :     // 1.get sRet and shift it to bit0.
     384            2 :     uint16_t sRet = FP16_EXTRAC_SIGN(fpVal);
     385              :     // 2.get hfE and hfM
     386            2 :     uint16_t hfM = FP16_EXTRAC_MAN(fpVal);
     387            2 :     uint16_t hfE = static_cast<uint16_t>(FP16_EXTRAC_EXP(fpVal));
     388              : 
     389            2 :     if (FP16_IS_DENORM(fpVal)) { // Denormalized number
     390            0 :         retV = 0;
     391            0 :         ret = *(reinterpret_cast<uint8_t*>(&retV));
     392            0 :         return ret;
     393              :     }
     394              : 
     395            2 :     uint8_t overflowFlag = 0;
     396            2 :     uint16_t shiftOut = 0;
     397            2 :     uint64_t longIntM = hfM;
     398            2 :     if (FP16_IS_INVALID(fpVal)) { // Inf or NaN
     399            0 :         overflowFlag = 1;
     400              :     } else {
     401            2 :         CalcOverflowFlagInt16(hfE, longIntM, sRet, overflowFlag, shiftOut);
     402              :     }
     403            2 :     if (overflowFlag != 0) {
     404            0 :         retV = static_cast<int16_t>(NumBitMax::K_INT16_MAX) + sRet;
     405              :     } else {
     406              :         // Generate final result
     407            2 :         retV = GetUint16ValByMan(sRet, longIntM, shiftOut);
     408              :     }
     409            2 :     ret = *(reinterpret_cast<int16_t*>(&retV));
     410            2 :     return ret;
     411              : }
     412              : 
     413              : /**
     414              :  * @ingroup half math conversion static method
     415              :  * @param [in] fpVal uint16_t value of half object
     416              :  * @brief   Convert half to uint16_t
     417              :  * @return  Return uint16_t value of fpVal which is the value of half object
     418              :  */
     419           14 : static uint16_t Fp16ToUInt16(const uint16_t& fpVal)
     420              : {
     421              :     uint16_t mRet;
     422              :     // 1.get sRet and shift it to bit0.
     423           14 :     uint16_t sRet = FP16_EXTRAC_SIGN(fpVal);
     424              :     // 2.get hfE and hfM
     425           14 :     int16_t hfE = FP16_EXTRAC_EXP(fpVal);
     426           14 :     uint16_t hfM = FP16_EXTRAC_MAN(fpVal);
     427              : 
     428           14 :     if (FP16_IS_DENORM(fpVal)) { // Denormalized number
     429            4 :         return 0;
     430              :     }
     431              : 
     432           10 :     if (FP16_IS_INVALID(fpVal)) { // Inf or NaN
     433            0 :         mRet = ~0;
     434              :     } else {
     435           10 :         uint16_t shiftOut = 0;
     436           10 :         uint64_t longIntM = hfM;
     437           86 :         while (hfE != static_cast<int16_t>(Fp16BasicParam::K_FP16_EXP_BIAS)) {
     438           76 :             if (hfE > static_cast<int16_t>(Fp16BasicParam::K_FP16_EXP_BIAS)) {
     439           76 :                 hfE--;
     440           76 :                 longIntM = longIntM << 1;
     441              :             } else {
     442            0 :                 shiftOut++;
     443            0 :                 hfE++;
     444              :             }
     445              :         }
     446           10 :         bool needRound = IsRoundOne(longIntM, shiftOut + static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_LEN));
     447           10 :         mRet = static_cast<uint16_t>(
     448           10 :             (longIntM >> (static_cast<uint32_t>(Fp16BasicParam::K_FP16_MAN_LEN) + static_cast<uint32_t>(shiftOut))) &
     449              :             static_cast<uint16_t>(NumBitMax::K_BIT_LEN16_MAX));
     450           10 :         if (needRound && (mRet != static_cast<uint16_t>(NumBitMax::K_BIT_LEN16_MAX))) {
     451            0 :             mRet++;
     452              :         }
     453              :     }
     454              : 
     455           10 :     if (sRet == 1) { // Negative number
     456            0 :         mRet = 0;
     457              :     }
     458              :     // mRet equal to final result
     459           10 :     return mRet;
     460              : }
     461              : 
     462              : /**
     463              :  * @ingroup half math convertion static method
     464              :  * @param [in] fpVal uint16_t value of half object
     465              :  * @brief   Convert half to int32_t
     466              :  * @return  Return int32_t value of fpVal which is the value of half object
     467              :  */
     468           12 : static int32_t Fp16ToInt32(const uint16_t& fpVal)
     469              : {
     470              :     uint32_t retV;
     471              :     // 1.get sRet and shift it to bit0.
     472           12 :     uint32_t sRet = FP16_EXTRAC_SIGN(fpVal);
     473              :     // 2.get hfE and hfM
     474           12 :     int16_t hfE = FP16_EXTRAC_EXP(fpVal);
     475           12 :     uint16_t hfM = FP16_EXTRAC_MAN(fpVal);
     476              : 
     477           12 :     if (FP16_IS_INVALID(fpVal)) { // Inf or NaN
     478            2 :         retV = static_cast<int32_t>(NumBitMax::K_INT32_MAX) + sRet;
     479              :     } else {
     480           10 :         uint64_t longIntM = hfM;
     481           10 :         uint16_t shiftOut = 0;
     482              : 
     483          102 :         while (hfE != static_cast<int16_t>(Fp16BasicParam::K_FP16_EXP_BIAS)) {
     484           92 :             if (hfE > static_cast<int16_t>(Fp16BasicParam::K_FP16_EXP_BIAS)) {
     485           92 :                 longIntM = longIntM << 1;
     486           92 :                 hfE--;
     487              :             } else {
     488            0 :                 hfE++;
     489            0 :                 shiftOut++;
     490              :             }
     491              :         }
     492           10 :         bool needRound = IsRoundOne(longIntM, shiftOut + static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_LEN));
     493           10 :         auto mRet = static_cast<uint32_t>(
     494           10 :             (longIntM >> (static_cast<uint32_t>(Fp16BasicParam::K_FP16_MAN_LEN) + static_cast<uint32_t>(shiftOut))) &
     495              :             static_cast<uint32_t>(NumBitMax::K_BIT_LEN32_MAX));
     496           10 :         if (needRound && (mRet < static_cast<uint32_t>(NumBitMax::K_INT32_MAX))) {
     497            2 :             mRet++;
     498              :         }
     499              : 
     500           10 :         if (sRet == 1) {
     501            0 :             mRet = (~mRet) + 1;
     502              :         }
     503           10 :         if (mRet == 0) {
     504            0 :             sRet = 0;
     505              :         }
     506              :         // Generate final result
     507           10 :         retV = (sRet << static_cast<uint16_t>(BitShift::K_BIT_SHIFT31)) | (mRet);
     508              :     }
     509              : 
     510           12 :     return *(reinterpret_cast<int32_t*>(&retV));
     511              : }
     512              : 
     513              : /**
     514              :  * @ingroup half math conversion static method
     515              :  * @param [in] fpVal uint16_t value of half object
     516              :  * @brief   Convert half to uint32_t
     517              :  * @return  Return uint32_t value of fpVal which is the value of half object
     518              :  */
     519            2 : static uint32_t Fp16ToUInt32(const uint16_t& fpVal)
     520              : {
     521              :     uint32_t mRet;
     522              :     // 1.get sRet and shift it to bit0.
     523            2 :     uint32_t sRet = FP16_EXTRAC_SIGN(fpVal);
     524              :     // 2.get hfE and hfM
     525            2 :     int16_t hfE = FP16_EXTRAC_EXP(fpVal);
     526            2 :     uint16_t hfM = FP16_EXTRAC_MAN(fpVal);
     527              : 
     528            2 :     if (FP16_IS_DENORM(fpVal)) { // Denormalized number
     529            0 :         return 0u;
     530              :     }
     531              : 
     532            2 :     if (FP16_IS_INVALID(fpVal)) { // Inf or NaN
     533            0 :         mRet = ~0u;
     534              :     } else {
     535            2 :         uint64_t longIntM = hfM;
     536            2 :         uint16_t shiftOut = 0;
     537           30 :         while (hfE != static_cast<int16_t>(Fp16BasicParam::K_FP16_EXP_BIAS)) {
     538           28 :             if (hfE > static_cast<int16_t>(Fp16BasicParam::K_FP16_EXP_BIAS)) {
     539           28 :                 hfE--;
     540           28 :                 longIntM = longIntM << 1;
     541              :             } else {
     542            0 :                 hfE++;
     543            0 :                 shiftOut++;
     544              :             }
     545              :         }
     546            2 :         bool needRound = IsRoundOne(longIntM, shiftOut + static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_LEN));
     547            2 :         mRet =
     548              :             static_cast<uint32_t>(
     549            2 :                 longIntM >> (static_cast<uint32_t>(Fp16BasicParam::K_FP16_MAN_LEN) + static_cast<uint32_t>(shiftOut))) &
     550              :             static_cast<uint32_t>(NumBitMax::K_BIT_LEN32_MAX);
     551            2 :         if (needRound && (mRet != static_cast<uint32_t>(NumBitMax::K_BIT_LEN32_MAX))) {
     552            0 :             mRet++;
     553              :         }
     554              :     }
     555              : 
     556            2 :     if (sRet == 1) { // Negative number
     557            0 :         mRet = 0;
     558              :     }
     559              :     // mRet equal to final result
     560            2 :     return mRet;
     561              : }
     562            0 : static uint16_t Fp16AddCalVal(const uint16_t& sRet, int16_t eRet, uint16_t mRet, uint32_t mTrunc, uint16_t shiftOut)
     563              : {
     564            0 :     uint16_t mMin = static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_HIDE_BIT) << shiftOut;
     565            0 :     uint16_t mMax = mMin << 1;
     566              :     // Denormal
     567            0 :     while ((mRet < mMin) && (eRet > 0)) { // the value of mRet should not be smaller than 2^23
     568            0 :         mRet = mRet << 1;
     569            0 :         mRet += (static_cast<uint32_t>(Fp32BasicParam::K_FP32_SIGN_MASK) & mTrunc) >>
     570              :                 static_cast<uint16_t>(Fp32BasicParam::K_FP32_SIGN_INDEX);
     571            0 :         mTrunc = mTrunc << 1;
     572            0 :         eRet = eRet - 1;
     573              :     }
     574            0 :     while (mRet >= mMax) { // the value of mRet should be smaller than 2^24
     575            0 :         mTrunc = mTrunc >> 1;
     576            0 :         mTrunc = mTrunc | (static_cast<uint32_t>(Fp32BasicParam::K_FP32_SIGN_MASK) * (mRet & 1));
     577            0 :         mRet = mRet >> 1;
     578            0 :         eRet = eRet + 1;
     579              :     }
     580              : 
     581            0 :     bool bLastBit = ((mRet & 1) > 0);
     582            0 :     bool bTruncHigh = (ROUND_MODE == TagFp16RoundMode::K_ROUND_TO_NEAREST) &&
     583            0 :                       ((mTrunc & static_cast<uint32_t>(Fp32BasicParam::K_FP32_SIGN_MASK)) > 0);
     584            0 :     bool bTruncLeft = (ROUND_MODE == TagFp16RoundMode::K_ROUND_TO_NEAREST) &&
     585            0 :                       ((mTrunc & static_cast<uint32_t>(Fp32BasicParam::K_FP32_ABS_MAX)) > 0);
     586            0 :     mRet = ManRoundToNearest(bLastBit, bTruncHigh, bTruncLeft, mRet, shiftOut);
     587            0 :     while (mRet >= mMax) {
     588            0 :         mRet = mRet >> 1;
     589            0 :         eRet = eRet + 1;
     590              :     }
     591              : 
     592            0 :     if ((eRet == 0) && (mRet <= mMax)) {
     593            0 :         mRet = mRet >> 1;
     594              :     }
     595            0 :     Fp16Normalize(eRet, mRet);
     596            0 :     uint16_t ret = FP16_CONSTRUCTOR(sRet, static_cast<uint16_t>(eRet), mRet);
     597            0 :     return ret;
     598              : }
     599              : 
     600              : /**
     601              :  * @ingroup half math operator
     602              :  * @param [in] v1 left operator value of half object
     603              :  * @param [in] v2 right operator value of half object
     604              :  * @brief   Performing half addition
     605              :  * @return  Return half result of adding this and fp
     606              :  */
     607            0 : static uint16_t Fp16Add(uint16_t v1, uint16_t v2)
     608              : {
     609              :     uint16_t sa;
     610              :     uint16_t sb;
     611              :     int16_t ea;
     612              :     int16_t eb;
     613              :     uint32_t ma;
     614              :     uint32_t mb;
     615              :     uint16_t maTmp;
     616              :     uint16_t mbTmp;
     617            0 :     uint16_t shiftOut = 0;
     618              :     // 1.Extract
     619            0 :     ExtractFp16(v1, sa, ea, maTmp);
     620            0 :     ExtractFp16(v2, sb, eb, mbTmp);
     621            0 :     ma = maTmp;
     622            0 :     mb = mbTmp;
     623              : 
     624              :     uint16_t sum;
     625              :     uint16_t sRet;
     626            0 :     if (sa != sb) {
     627            0 :         ReverseMan(sa > 0, ma);
     628            0 :         ReverseMan(sb > 0, mb);
     629            0 :         sum = static_cast<uint16_t>(GetManSum(ea, ma, eb, mb));
     630            0 :         sRet = (sum & static_cast<uint16_t>(Fp16BasicParam::K_FP16_SIGN_MASK)) >>
     631              :                static_cast<uint16_t>(Fp16BasicParam::K_FP16_SIGN_INDEX);
     632            0 :         ReverseMan(sRet > 0, ma);
     633            0 :         ReverseMan(sRet > 0, mb);
     634              :     } else {
     635            0 :         sum = static_cast<uint16_t>(GetManSum(ea, ma, eb, mb));
     636            0 :         sRet = sa;
     637              :     }
     638              : 
     639            0 :     if (sum == 0) {
     640            0 :         shiftOut = 3; // shift to left 3 bits
     641            0 :         ma = ma << shiftOut;
     642            0 :         mb = mb << shiftOut;
     643              :     }
     644              : 
     645            0 :     uint32_t mTrunc = 0;
     646            0 :     int16_t eRet = std::max(ea, eb);
     647            0 :     uint32_t eTmp = static_cast<uint32_t>(std::abs(ea - eb));
     648            0 :     if (ea > eb) {
     649            0 :         mTrunc = (mb << (static_cast<uint32_t>(BitShift::K_BIT_SHIFT32) - eTmp));
     650            0 :         mb = RightShift(mb, eTmp);
     651            0 :     } else if (ea < eb) {
     652            0 :         mTrunc = (ma << (static_cast<uint32_t>(BitShift::K_BIT_SHIFT32) - eTmp));
     653            0 :         ma = RightShift(ma, eTmp);
     654              :     }
     655              :     // calculate mantissav
     656            0 :     auto mRet = static_cast<uint16_t>(ma + mb);
     657            0 :     return Fp16AddCalVal(sRet, eRet, mRet, mTrunc, shiftOut);
     658              : }
     659              : 
     660              : /**
     661              :  * @ingroup half math operator
     662              :  * @param [in] v1 left operator value of half object
     663              :  * @param [in] v2 right operator value of half object
     664              :  * @brief   Performing half subtraction
     665              :  * @return  Return half result of subtraction fp from this
     666              :  */
     667            0 : static uint16_t Fp16Sub(uint16_t v1, uint16_t v2)
     668              : {
     669              :     // Reverse
     670            0 :     uint16_t tmp = ((~(v2)) & static_cast<uint16_t>(Fp16BasicParam::K_FP16_SIGN_MASK)) |
     671              :                    (v2 & static_cast<uint16_t>(Fp16BasicParam::K_FP16_ABS_MAX));
     672            0 :     return Fp16Add(v1, tmp);
     673              : }
     674              : /**
     675              :  * @ingroup half math operator
     676              :  * @param [in] v1 left operator value of half object
     677              :  * @param [in] v2 right operator value of half object
     678              :  * @brief   Performing half multiplication
     679              :  * @return  Return half result of multiplying this and fp
     680              :  */
     681            4 : static uint16_t Fp16Mul(uint16_t v1, uint16_t v2)
     682              : {
     683              :     uint16_t sa;
     684              :     uint16_t sb;
     685              :     int16_t ea;
     686              :     int16_t eb;
     687              :     uint16_t mRet;
     688              :     uint16_t maTmp;
     689              :     uint16_t mbTmp;
     690              :     // 1.Extract
     691            4 :     ExtractFp16(v1, sa, ea, maTmp);
     692            4 :     ExtractFp16(v2, sb, eb, mbTmp);
     693            4 :     uint32_t ma = maTmp;
     694            4 :     uint32_t mb = mbTmp;
     695              : 
     696            4 :     int16_t eRet =
     697            4 :         (ea + eb - static_cast<uint16_t>(Fp16BasicParam::K_FP16_EXP_BIAS)) - static_cast<uint16_t>(DimIndex::K_DIM10);
     698            4 :     uint32_t mulM = ma * mb;
     699            4 :     uint16_t sRet = sa ^ sb;
     700              : 
     701            4 :     uint32_t mMin = static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_HIDE_BIT);
     702            4 :     uint32_t mMax = mMin << 1;
     703            4 :     uint32_t mTrunc = 0;
     704              :     // the value of mRet should not be smaller than 2^23
     705            4 :     while ((mulM < mMin) && (eRet > 1)) {
     706            0 :         mulM = mulM << 1;
     707            0 :         eRet = eRet - 1;
     708              :     }
     709           44 :     while ((mulM >= mMax) || (eRet < 1)) {
     710           40 :         mTrunc = mTrunc >> 1;
     711           40 :         mTrunc = mTrunc | (static_cast<uint32_t>(Fp32BasicParam::K_FP32_SIGN_MASK) * (mulM & 1));
     712           40 :         mulM = mulM >> 1;
     713           40 :         eRet = eRet + 1;
     714              :     }
     715            4 :     bool bLastBit = ((mulM & 1) > 0);
     716            4 :     bool bTruncHigh = (ROUND_MODE == TagFp16RoundMode::K_ROUND_TO_NEAREST) &&
     717            4 :                       ((mTrunc & static_cast<uint32_t>(Fp32BasicParam::K_FP32_SIGN_MASK)) > 0);
     718            4 :     bool bTruncLeft = (ROUND_MODE == TagFp16RoundMode::K_ROUND_TO_NEAREST) &&
     719            4 :                       ((mTrunc & static_cast<uint32_t>(Fp32BasicParam::K_FP32_ABS_MAX)) > 0);
     720            4 :     mulM = ManRoundToNearest(bLastBit, bTruncHigh, bTruncLeft, mulM);
     721              : 
     722            4 :     while ((mulM >= mMax) || (eRet < 0)) {
     723            0 :         mulM = mulM >> 1;
     724            0 :         eRet = eRet + 1;
     725              :     }
     726              : 
     727            4 :     if ((eRet == 1) && (mulM < static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_HIDE_BIT))) {
     728            0 :         eRet = 0;
     729              :     }
     730            4 :     mRet = static_cast<uint16_t>(mulM);
     731              : 
     732            4 :     Fp16Normalize(eRet, mRet);
     733              : 
     734            4 :     uint16_t ret = FP16_CONSTRUCTOR(sRet, static_cast<uint16_t>(eRet), mRet);
     735            4 :     return ret;
     736              : }
     737              : 
     738              : /**
     739              :  * @ingroup half math operator divided
     740              :  * @param [in] v1 left operator value of half object
     741              :  * @param [in] v2 right operator value of half object
     742              :  * @brief   Performing half division
     743              :  * @return  Return half result of division this by fp
     744              :  */
     745            4 : static uint16_t Fp16Div(uint16_t v1, uint16_t v2)
     746              : {
     747              :     uint16_t ret;
     748            4 :     if (FP16_IS_ZERO(v2)) { // result is inf
     749              :         // throw "half division by zero.";
     750              :         uint16_t sa;
     751              :         uint16_t sb;
     752              :         uint16_t sRet;
     753            0 :         sa = FP16_EXTRAC_SIGN(v1);
     754            0 :         sb = FP16_EXTRAC_SIGN(v2);
     755            0 :         sRet = sa ^ sb;
     756            0 :         ret = FP16_CONSTRUCTOR(sRet, static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAX_EXP), 0u);
     757            4 :     } else if (FP16_IS_ZERO(v1)) {
     758            0 :         ret = 0u;
     759              :     } else {
     760              :         uint16_t sa;
     761              :         uint16_t sb;
     762              :         int16_t ea;
     763              :         int16_t eb;
     764              :         uint16_t maTmp;
     765              :         uint16_t mbTmp;
     766              :         // 1.Extract
     767            4 :         ExtractFp16(v1, sa, ea, maTmp);
     768            4 :         ExtractFp16(v2, sb, eb, mbTmp);
     769            4 :         uint64_t ma = maTmp;
     770            4 :         uint64_t mb = mbTmp;
     771              :         uint64_t mTmp;
     772            4 :         if (ea > eb) {
     773            4 :             mTmp = ma;
     774            4 :             int16_t tmp = ea - eb;
     775           22 :             for (int16_t i = 0; i < tmp; i++) {
     776           18 :                 mTmp = mTmp << 1;
     777              :             }
     778            4 :             ma = mTmp;
     779            0 :         } else if (ea < eb) {
     780            0 :             mTmp = mb;
     781            0 :             int16_t tmp = eb - ea;
     782            0 :             for (int16_t i = 0; i < tmp; i++) {
     783            0 :                 mTmp = mTmp << 1;
     784              :             }
     785            0 :             mb = mTmp;
     786              :         }
     787            4 :         float mDiv = static_cast<float>(ma * 1.0f / mb);
     788            4 :         half fpDiv(mDiv);
     789            4 :         ret = fpDiv.val;
     790            4 :         if (sa != sb) {
     791            0 :             ret |= static_cast<uint16_t>(Fp16BasicParam::K_FP16_SIGN_MASK);
     792              :         }
     793              :     }
     794            4 :     return ret;
     795              : }
     796              : 
     797              : // operate
     798            0 : half half::operator+(const half fp) const
     799              : {
     800            0 :     uint16_t retVal = Fp16Add(val, fp.val);
     801              :     half ret;
     802            0 :     ret.val = retVal;
     803            0 :     return ret;
     804              : }
     805            0 : half half::operator-(const half fp) const
     806              : {
     807            0 :     uint16_t retVal = Fp16Sub(val, fp.val);
     808              :     half ret;
     809            0 :     ret.val = retVal;
     810            0 :     return ret;
     811              : }
     812            2 : half half::operator*(const half fp) const
     813              : {
     814            2 :     uint16_t retVal = Fp16Mul(val, fp.val);
     815              :     half ret;
     816            2 :     ret.val = retVal;
     817            2 :     return ret;
     818              : }
     819            2 : half half::operator/(const half fp) const
     820              : {
     821            2 :     uint16_t retVal = Fp16Div(val, fp.val);
     822              :     half ret;
     823            2 :     ret.val = retVal;
     824            2 :     return ret;
     825              : }
     826              : 
     827            0 : half half::operator+=(const half fp)
     828              : {
     829            0 :     val = Fp16Add(val, fp.val);
     830            0 :     return *this;
     831              : }
     832            0 : half half::operator-=(const half fp)
     833              : {
     834            0 :     val = Fp16Sub(val, fp.val);
     835            0 :     return *this;
     836              : }
     837            2 : half half::operator*=(const half fp)
     838              : {
     839            2 :     val = Fp16Mul(val, fp.val);
     840            2 :     return *this;
     841              : }
     842            2 : half half::operator/=(const half fp)
     843              : {
     844            2 :     val = Fp16Div(val, fp.val);
     845            2 :     return *this;
     846              : }
     847              : 
     848              : // compare
     849            0 : bool half::operator==(const half& fp) const
     850              : {
     851            0 :     bool result = true;
     852            0 :     if (FP16_IS_ZERO(val) && FP16_IS_ZERO(fp.val)) {
     853            0 :         result = true;
     854              :     } else {
     855            0 :         result =
     856            0 :             ((val & static_cast<uint16_t>(NumBitMax::K_BIT_LEN16_MAX)) ==
     857            0 :              (fp.val & static_cast<uint16_t>(NumBitMax::K_BIT_LEN16_MAX))); // bit compare
     858              :     }
     859            0 :     return result;
     860              : }
     861            0 : bool half::operator!=(const half& fp) const
     862              : {
     863            0 :     bool result = true;
     864            0 :     if (FP16_IS_ZERO(val) && FP16_IS_ZERO(fp.val)) {
     865            0 :         result = false;
     866              :     } else {
     867            0 :         result =
     868            0 :             ((val & static_cast<uint16_t>(NumBitMax::K_BIT_LEN16_MAX)) !=
     869            0 :              (fp.val & static_cast<uint16_t>(NumBitMax::K_BIT_LEN16_MAX))); // bit compare
     870              :     }
     871            0 :     return result;
     872              : }
     873            0 : static bool CmpPosNums(const uint16_t& ea, const uint16_t& eb, const uint16_t& ma, const uint16_t& mb)
     874              : {
     875            0 :     bool result = true;
     876            0 :     if (ea > eb) { // ea - eb >= 1; Va always larger than Vb
     877            0 :         result = true;
     878            0 :     } else if (ea == eb) {
     879            0 :         result = ma > mb;
     880              :     } else {
     881            0 :         result = false;
     882              :     }
     883            0 :     return result;
     884              : }
     885            0 : static bool CmpNegNums(const uint16_t& ea, const uint16_t& eb, const uint16_t& ma, const uint16_t& mb)
     886              : {
     887            0 :     bool result = true;
     888            0 :     if (ea < eb) {
     889            0 :         result = true;
     890            0 :     } else if (ea == eb) {
     891            0 :         result = ma < mb;
     892              :     } else {
     893            0 :         result = false;
     894              :     }
     895            0 :     return result;
     896              : }
     897            0 : bool half::operator>(const half& fp) const
     898              : {
     899              :     uint16_t sa;
     900              :     uint16_t sb;
     901              :     uint16_t ea;
     902              :     uint16_t eb;
     903              :     uint16_t ma;
     904              :     uint16_t mb;
     905            0 :     bool result = true;
     906              : 
     907              :     // 1.Extract
     908            0 :     sa = FP16_EXTRAC_SIGN(val);
     909            0 :     sb = FP16_EXTRAC_SIGN(fp.val);
     910            0 :     ea = static_cast<uint16_t>(FP16_EXTRAC_EXP(val));
     911            0 :     eb = static_cast<uint16_t>(FP16_EXTRAC_EXP(fp.val));
     912            0 :     ma = FP16_EXTRAC_MAN(val);
     913            0 :     mb = FP16_EXTRAC_MAN(fp.val);
     914              : 
     915              :     // Compare
     916            0 :     if ((sa == 0) && (sb > 0)) { // +  -
     917              :         // -0=0
     918            0 :         result = !(FP16_IS_ZERO(val) && FP16_IS_ZERO(fp.val));
     919            0 :     } else if ((sa == 0) && (sb == 0)) { // + +
     920            0 :         result = CmpPosNums(ea, eb, ma, mb);
     921            0 :     } else if ((sa > 0) && (sb > 0)) { // - -    opposite to  + +
     922            0 :         result = CmpNegNums(ea, eb, ma, mb);
     923              :     } else {
     924              :         // -  +
     925            0 :         result = false;
     926              :     }
     927              : 
     928            0 :     return result;
     929              : }
     930              : 
     931            0 : bool half::operator>=(const half& fp) const
     932              : {
     933            0 :     bool result = true;
     934            0 :     if (((*this) > fp) || ((*this) == fp)) {
     935            0 :         result = true;
     936              :     } else {
     937            0 :         result = false;
     938              :     }
     939              : 
     940            0 :     return result;
     941              : }
     942              : 
     943            0 : bool half::operator<=(const half& fp) const
     944              : {
     945            0 :     bool result = true;
     946            0 :     if ((*this) > fp) {
     947            0 :         result = false;
     948              :     }
     949            0 :     return result;
     950              : }
     951              : 
     952            0 : bool half::operator<(const half& fp) const
     953              : {
     954            0 :     bool result = true;
     955            0 :     if ((*this) >= fp) {
     956            0 :         result = false;
     957              :     }
     958            0 :     return result;
     959              : }
     960              : 
     961            0 : half half::operator++()
     962              : {
     963            0 :     half one = 1.0;
     964            0 :     val = Fp16Add(val, one.val);
     965            0 :     return *this;
     966              : }
     967              : 
     968            0 : half half::operator++(int)
     969              : {
     970            0 :     half oldBf = *this;
     971            0 :     operator++();
     972            0 :     return oldBf;
     973              : }
     974              : 
     975            0 : half half::operator--()
     976              : {
     977            0 :     half one = 1.0;
     978            0 :     val = Fp16Sub(val, one.val);
     979            0 :     return *this;
     980              : }
     981              : 
     982            0 : half half::operator--(int)
     983              : {
     984            0 :     half oldBf = *this;
     985            0 :     operator--();
     986            0 :     return oldBf;
     987              : }
     988              : 
     989            0 : bool half::operator&&(const half fp) const { return (val != 0) && (fp.val != 0); }
     990              : 
     991            0 : bool half::operator||(const half fp) const { return (val != 0) || (fp.val != 0); }
     992              : 
     993           16 : uint16_t half::FloatToFp16(const float& fVal) const
     994              : {
     995              :     uint16_t sRet;
     996              :     uint16_t mRet;
     997              :     int16_t eRet;
     998              :     uint32_t ef;
     999              :     uint32_t mf;
    1000           16 :     const uint32_t ui32V = *(reinterpret_cast<const uint32_t*>(&fVal)); // 1:8:23bit sign:exp:man
    1001              :     uint32_t mLenDelta;
    1002              : 
    1003           16 :     sRet = static_cast<uint16_t>(
    1004           16 :         (ui32V & static_cast<uint32_t>(Fp32BasicParam::K_FP32_SIGN_MASK)) >>
    1005              :         static_cast<uint16_t>(Fp32BasicParam::K_FP32_SIGN_INDEX)); // 4Byte->2Byte
    1006           16 :     ef = (ui32V & static_cast<uint32_t>(Fp32BasicParam::K_FP32_EXP_MASK)) >>
    1007              :          static_cast<uint16_t>(Fp32BasicParam::K_FP32_MAN_LEN); // 8 bit exponent
    1008           16 :     mf =
    1009              :         (ui32V &
    1010              :          static_cast<uint32_t>(Fp32BasicParam::K_FP32_MAN_MASK)); // 23 bit mantissa dont't need to care about denormal
    1011           16 :     mLenDelta =
    1012              :         static_cast<uint16_t>(Fp32BasicParam::K_FP32_MAN_LEN) - static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_LEN);
    1013              : 
    1014           16 :     bool needRound = false;
    1015              :     // Exponent overflow/NaN converts to signed inf/NaN
    1016           16 :     if (ef > 0x8Fu) { // 0x8Fu:142=127+15
    1017            0 :         eRet = static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAX_EXP) - 1;
    1018            0 :         mRet = static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAX_MAN);
    1019           16 :     } else if (ef <= 0x70u) { // 0x70u:112=127-15 Exponent underflow converts to denormalized half or signed zero
    1020            4 :         eRet = 0;
    1021            4 :         if (ef >= 0x67) { // 0x67:103=127-24 Denormal
    1022            0 :             mf = (mf | static_cast<uint32_t>(Fp32BasicParam::K_FP32_MAN_HIDE_BIT));
    1023            0 :             uint16_t shiftOut = static_cast<uint16_t>(Fp32BasicParam::K_FP32_MAN_LEN);
    1024            0 :             uint64_t mTmp = (static_cast<uint64_t>(mf)) << (ef - 0x67);
    1025              : 
    1026            0 :             needRound = IsRoundOne(mTmp, shiftOut);
    1027            0 :             mRet = static_cast<uint16_t>(mTmp >> shiftOut);
    1028            0 :             if (needRound) {
    1029            0 :                 mRet++;
    1030              :             }
    1031            4 :         } else if ((ef == 0x66) && (mf > 0)) { // 0x66:102 Denormal 0<f_v<min(Denormal)
    1032            0 :             mRet = 1;
    1033              :         } else {
    1034            4 :             mRet = 0;
    1035              :         }
    1036              :     } else { // Regular case with no overflow or underflow
    1037           12 :         eRet = static_cast<int16_t>(ef - 0x70u);
    1038              : 
    1039           12 :         needRound = IsRoundOne(mf, static_cast<uint16_t>(mLenDelta));
    1040           12 :         mRet = static_cast<uint16_t>(mf >> mLenDelta);
    1041           12 :         if (needRound) {
    1042            2 :             mRet++;
    1043              :         }
    1044           12 :         if ((mRet & static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_HIDE_BIT)) != 0) {
    1045            0 :             eRet++;
    1046              :         }
    1047              :     }
    1048              : 
    1049           16 :     Fp16Normalize(eRet, mRet);
    1050           16 :     return FP16_CONSTRUCTOR(sRet, static_cast<uint16_t>(eRet), mRet);
    1051              : }
    1052              : 
    1053            4 : uint16_t half::DoubleToFp16(const double& dVal)
    1054              : {
    1055              :     uint16_t sRet;
    1056              :     uint16_t mRet;
    1057              :     int16_t eRet;
    1058              :     uint64_t ed;
    1059              :     uint64_t md;
    1060            4 :     uint64_t ui64V = *(reinterpret_cast<const uint64_t*>(&dVal)); // 1:11:52bit sign:exp:man
    1061              :     uint16_t mLenDelta;
    1062              : 
    1063            4 :     sRet = static_cast<uint16_t>(
    1064            4 :         (ui64V & static_cast<uint64_t>(Fp64BasicParam::K_FP64_SIGN_MASK)) >>
    1065              :         static_cast<uint16_t>(Fp64BasicParam::K_FP64_SIGN_INDEX)); // 4Byte
    1066            4 :     ed = (ui64V & static_cast<uint64_t>(Fp64BasicParam::K_FP64_EXP_MASK)) >>
    1067              :          static_cast<uint16_t>(Fp64BasicParam::K_FP64_MAN_LEN);            // 10 bit exponent
    1068            4 :     md = (ui64V & static_cast<uint64_t>(Fp64BasicParam::K_FP64_MAN_MASK)); // 52 bit mantissa
    1069            4 :     mLenDelta =
    1070              :         static_cast<uint16_t>(Fp64BasicParam::K_FP64_MAN_LEN) - static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_LEN);
    1071              : 
    1072            4 :     bool needRound = false;
    1073              :     // Exponent overflow/NaN converts to signed inf/NaN
    1074            4 :     if (ed >= 0x410u) { // 0x410:1040=1023+16
    1075            2 :         eRet = static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAX_EXP) - 1;
    1076            2 :         mRet = static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAX_MAN);
    1077            2 :         val = FP16_CONSTRUCTOR(sRet, static_cast<uint16_t>(eRet), mRet);
    1078            2 :     } else if (ed <= 0x3F0u) { // Exponent underflow converts to denormalized half or signed zero
    1079              :         // 0x3F0:1008=1023-15
    1080              :         // Signed zeros, denormalized floats, and floats with small
    1081              :         // exponents all convert to signed zero half precision.
    1082            0 :         eRet = 0;
    1083            0 :         if (ed >= 0x3E7u) { // 0x3E7u:999=1023-24 Denormal
    1084              :             // Underflows to a denormalized value
    1085            0 :             md = (static_cast<uint64_t>(Fp64BasicParam::K_FP64_MAN_HIDE_BIT) | md);
    1086            0 :             uint16_t shiftOut = static_cast<uint16_t>(Fp64BasicParam::K_FP64_MAN_LEN);
    1087            0 :             uint64_t mTmp = (static_cast<uint64_t>(md)) << (ed - 0x3E7u);
    1088              : 
    1089            0 :             needRound = IsRoundOne(mTmp, shiftOut);
    1090            0 :             mRet = static_cast<uint16_t>(mTmp >> shiftOut);
    1091            0 :             if (needRound) {
    1092            0 :                 mRet++;
    1093              :             }
    1094            0 :         } else if ((ed == 0x3E6u) && (md > 0)) {
    1095            0 :             mRet = 1;
    1096              :         } else {
    1097            0 :             mRet = 0;
    1098              :         }
    1099              :     } else { // Regular case with no overflow or underflow
    1100            2 :         eRet = static_cast<int16_t>(ed - 0x3F0u);
    1101              : 
    1102            2 :         needRound = IsRoundOne(md, mLenDelta);
    1103            2 :         mRet = static_cast<uint16_t>(md >> mLenDelta);
    1104            2 :         if (needRound) {
    1105            2 :             mRet++;
    1106              :         }
    1107            2 :         if ((static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_HIDE_BIT) & mRet) != 0) {
    1108            0 :             eRet++;
    1109              :         }
    1110              :     }
    1111              : 
    1112            4 :     Fp16Normalize(eRet, mRet);
    1113            4 :     return FP16_CONSTRUCTOR(sRet, static_cast<uint16_t>(eRet), mRet);
    1114              : }
    1115              : 
    1116            0 : uint16_t half::Int8ToFp16(const int8_t& iVal) const
    1117              : {
    1118              :     uint16_t sRet;
    1119              :     uint16_t eRet;
    1120              :     uint16_t mRet;
    1121              : 
    1122            0 :     sRet = ((static_cast<uint8_t>(iVal)) & 0x80) == 0 ? 0 : 1;
    1123            0 :     mRet = static_cast<uint16_t>(((static_cast<uint8_t>(iVal)) & static_cast<int8_t>(NumBitMax::K_INT8_MAX)));
    1124              : 
    1125            0 :     if (mRet == 0) {
    1126            0 :         eRet = 0;
    1127              :     } else {
    1128            0 :         if (sRet != 0) {                                  // negative number(<0)
    1129            0 :             mRet = static_cast<uint16_t>(std::abs(iVal)); // complement
    1130              :         }
    1131              : 
    1132            0 :         eRet = static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_LEN);
    1133            0 :         while ((mRet & static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_HIDE_BIT)) == 0) {
    1134            0 :             eRet = eRet - 1;
    1135            0 :             mRet = mRet << 1;
    1136              :         }
    1137            0 :         eRet = eRet + static_cast<uint16_t>(Fp16BasicParam::K_FP16_EXP_BIAS);
    1138              :     }
    1139            0 :     return FP16_CONSTRUCTOR(sRet, eRet, mRet);
    1140              : }
    1141              : 
    1142            0 : uint16_t half::UInt8ToFp16(const uint8_t& uiVal) const
    1143              : {
    1144              :     uint16_t sRet;
    1145              :     uint16_t eRet;
    1146              :     uint16_t mRet;
    1147            0 :     sRet = 0;
    1148            0 :     eRet = 0;
    1149            0 :     mRet = uiVal;
    1150            0 :     if (mRet != 0) {
    1151            0 :         eRet = static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_LEN);
    1152            0 :         while ((mRet & static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_HIDE_BIT)) == 0) {
    1153            0 :             mRet = mRet << 1;
    1154            0 :             eRet = eRet - 1;
    1155              :         }
    1156            0 :         eRet = eRet + static_cast<uint16_t>(Fp16BasicParam::K_FP16_EXP_BIAS);
    1157              :     }
    1158            0 :     return FP16_CONSTRUCTOR(sRet, eRet, mRet);
    1159              : }
    1160              : 
    1161            0 : static void SetValByUint16Val(const uint16_t& inputVal, const uint16_t& sign, uint16_t& retVal)
    1162              : {
    1163            0 :     uint32_t mTmp = (inputVal & static_cast<uint32_t>(Fp32BasicParam::K_FP32_ABS_MAX));
    1164            0 :     uint16_t mMin = static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_HIDE_BIT);
    1165            0 :     uint16_t mMax = mMin << 1;
    1166            0 :     uint16_t len = static_cast<uint16_t>(GetManBitLength(mTmp));
    1167            0 :     if (mTmp != 0) {
    1168              :         uint16_t eRet;
    1169            0 :         if (len > static_cast<uint16_t>(DimIndex::K_DIM11)) {
    1170            0 :             eRet = static_cast<uint16_t>(Fp16BasicParam::K_FP16_EXP_BIAS) +
    1171              :                    static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_LEN);
    1172            0 :             uint32_t eTmp = static_cast<uint32_t>(len) - static_cast<uint32_t>(DimIndex::K_DIM11);
    1173            0 :             uint32_t truncMask = 1;
    1174            0 :             for (uint32_t i = 1; i < eTmp; i++) {
    1175            0 :                 truncMask = (truncMask << 1) + 1;
    1176              :             }
    1177            0 :             uint32_t mTrunc = (mTmp & truncMask) << (static_cast<uint32_t>(BitShift::K_BIT_SHIFT32) - eTmp);
    1178            0 :             for (uint32_t i = 0; i < eTmp; i++) {
    1179            0 :                 eRet = eRet + 1;
    1180            0 :                 mTmp = (mTmp >> 1);
    1181              :             }
    1182            0 :             bool bLastBit = ((mTmp & 1) > 0);
    1183            0 :             bool bTruncHigh = static_cast<bool>(0);
    1184            0 :             bool bTruncLeft = static_cast<bool>(0);
    1185              :             if (ROUND_MODE == TagFp16RoundMode::K_ROUND_TO_NEAREST) { // trunc
    1186            0 :                 bTruncHigh = ((mTrunc & static_cast<uint32_t>(Fp32BasicParam::K_FP32_SIGN_MASK)) > 0);
    1187            0 :                 bTruncLeft = ((mTrunc & static_cast<uint32_t>(Fp32BasicParam::K_FP32_ABS_MAX)) > 0);
    1188              :             }
    1189            0 :             mTmp = ManRoundToNearest(bLastBit, bTruncHigh, bTruncLeft, mTmp);
    1190            0 :             while (mTmp >= mMax) {
    1191            0 :                 mTmp = mTmp >> 1;
    1192            0 :                 eRet = eRet + 1;
    1193              :             }
    1194              :         } else {
    1195            0 :             eRet = static_cast<uint16_t>(Fp16BasicParam::K_FP16_EXP_BIAS);
    1196            0 :             mTmp = mTmp << static_cast<uint32_t>(K_MAN_BIT_LENGTH - len);
    1197            0 :             eRet = eRet + (len - static_cast<uint16_t>(1));
    1198              :         }
    1199            0 :         auto mRet = static_cast<uint16_t>(mTmp);
    1200            0 :         retVal = FP16_CONSTRUCTOR(sign, eRet, mRet);
    1201              :     }
    1202            0 : }
    1203              : 
    1204            0 : uint16_t half::Int16ToFp16(const int16_t& iVal) const
    1205              : {
    1206            0 :     uint16_t retVal = 0;
    1207            0 :     if (iVal != 0) {
    1208            0 :         uint16_t uiVal = *(reinterpret_cast<const uint16_t*>(&iVal));
    1209            0 :         auto sRet = static_cast<uint16_t>(uiVal >> static_cast<uint16_t>(BitShift::K_BIT_SHIFT15));
    1210            0 :         if (sRet != 0) {
    1211            0 :             int16_t iValM = -iVal;
    1212            0 :             uiVal = *(reinterpret_cast<uint16_t*>(&iValM));
    1213              :         }
    1214            0 :         SetValByUint16Val(uiVal, sRet, retVal);
    1215              :     }
    1216            0 :     return retVal;
    1217              : }
    1218              : 
    1219           40 : uint16_t half::UInt16ToFp16(const uint16_t& uiVal)
    1220              : {
    1221           40 :     if (uiVal == 0) {
    1222            4 :         return 0;
    1223              :     } else {
    1224              :         uint16_t eRet;
    1225           36 :         uint16_t mRet = uiVal;
    1226           36 :         uint16_t mMin = static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_HIDE_BIT);
    1227           36 :         uint16_t mMax = mMin << 1;
    1228           36 :         uint16_t len = static_cast<uint16_t>(GetManBitLength(mRet));
    1229           36 :         if (len > K_MAN_BIT_LENGTH) {
    1230           22 :             eRet = static_cast<uint16_t>(Fp16BasicParam::K_FP16_EXP_BIAS) +
    1231              :                    static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_LEN);
    1232              :             uint32_t mTrunc;
    1233           22 :             uint32_t truncMask = 1;
    1234           22 :             uint32_t eTmp = static_cast<uint32_t>(len - K_MAN_BIT_LENGTH);
    1235           74 :             for (uint32_t i = 1; i < eTmp; i++) {
    1236           52 :                 truncMask = (truncMask << 1) + 1;
    1237              :             }
    1238           22 :             mTrunc = (mRet & truncMask) << (static_cast<uint32_t>(BitShift::K_BIT_SHIFT32) - eTmp);
    1239           96 :             for (uint32_t i = 0; i < eTmp; i++) {
    1240           74 :                 mRet = (mRet >> 1);
    1241           74 :                 eRet = eRet + 1;
    1242              :             }
    1243           22 :             bool bLastBit = ((mRet & 1) > 0);
    1244           22 :             bool bTruncHigh = static_cast<bool>(0);
    1245           22 :             bool bTruncLeft = static_cast<bool>(0);
    1246              :             if (ROUND_MODE == TagFp16RoundMode::K_ROUND_TO_NEAREST) { // trunc
    1247           22 :                 bTruncHigh = ((mTrunc & static_cast<uint32_t>(Fp32BasicParam::K_FP32_SIGN_MASK)) > 0);
    1248           22 :                 bTruncLeft = ((mTrunc & static_cast<uint32_t>(Fp32BasicParam::K_FP32_ABS_MAX)) > 0);
    1249              :             }
    1250           22 :             mRet = ManRoundToNearest(bLastBit, bTruncHigh, bTruncLeft, mRet);
    1251           28 :             while (mRet >= mMax) {
    1252            6 :                 mRet = mRet >> 1;
    1253            6 :                 eRet = eRet + 1;
    1254              :             }
    1255           22 :             if (FP16_IS_INVALID(val)) {
    1256            0 :                 val = static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAX);
    1257              :             }
    1258              :         } else {
    1259           14 :             eRet = static_cast<uint16_t>(Fp16BasicParam::K_FP16_EXP_BIAS);
    1260           14 :             mRet = mRet << (static_cast<uint32_t>(DimIndex::K_DIM11) - static_cast<uint32_t>(len));
    1261           14 :             eRet = eRet + (len - static_cast<uint16_t>(1));
    1262              :         }
    1263           36 :         return FP16_CONSTRUCTOR(0u, eRet, mRet);
    1264              :     }
    1265              : }
    1266              : 
    1267            0 : static void SetValByUint32Val(const uint32_t& inputVal, const uint16_t& sign, uint16_t& retVal)
    1268              : {
    1269              :     uint16_t eRet;
    1270            0 :     uint32_t mMin = static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_HIDE_BIT);
    1271            0 :     uint32_t mMax = mMin << 1;
    1272            0 :     uint32_t mTmp = (inputVal & static_cast<uint32_t>(Fp32BasicParam::K_FP32_ABS_MAX));
    1273            0 :     uint16_t len = static_cast<uint16_t>(GetManBitLength(mTmp));
    1274            0 :     if (len > static_cast<uint16_t>(DimIndex::K_DIM11)) {
    1275            0 :         eRet = static_cast<uint16_t>(Fp16BasicParam::K_FP16_EXP_BIAS) +
    1276              :                static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_LEN);
    1277            0 :         uint32_t truncMask = 1;
    1278            0 :         uint32_t eTmp = len - static_cast<uint32_t>(DimIndex::K_DIM11);
    1279            0 :         for (uint32_t i = 1; i < eTmp; i++) {
    1280            0 :             truncMask = (truncMask << 1) + 1;
    1281              :         }
    1282            0 :         uint32_t mTrunc = (mTmp & truncMask) << (static_cast<uint32_t>(BitShift::K_BIT_SHIFT32) - eTmp);
    1283            0 :         for (uint32_t i = 0; i < eTmp; i++) {
    1284            0 :             mTmp = (mTmp >> 1);
    1285            0 :             eRet = eRet + 1;
    1286              :         }
    1287            0 :         bool bLastBit = ((mTmp & 1) > 0);
    1288            0 :         bool bTruncHigh = static_cast<bool>(0);
    1289            0 :         bool bTruncLeft = static_cast<bool>(0);
    1290              :         if (ROUND_MODE == TagFp16RoundMode::K_ROUND_TO_NEAREST) { // trunc
    1291            0 :             bTruncLeft = ((mTrunc & static_cast<uint32_t>(Fp32BasicParam::K_FP32_ABS_MAX)) > 0);
    1292            0 :             bTruncHigh = ((mTrunc & static_cast<uint32_t>(Fp32BasicParam::K_FP32_SIGN_MASK)) > 0);
    1293              :         }
    1294            0 :         mTmp = ManRoundToNearest(bLastBit, bTruncHigh, bTruncLeft, mTmp);
    1295            0 :         while (mTmp >= mMax) {
    1296            0 :             eRet = eRet + 1;
    1297            0 :             mTmp = mTmp >> 1;
    1298              :         }
    1299            0 :         if (eRet >= static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAX_EXP)) {
    1300            0 :             mTmp = static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAX_MAN);
    1301            0 :             eRet = static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAX_EXP) - 1;
    1302              :         }
    1303              :     } else {
    1304            0 :         eRet = static_cast<uint16_t>(Fp16BasicParam::K_FP16_EXP_BIAS);
    1305            0 :         eRet = eRet + (len - 1);
    1306            0 :         mTmp = mTmp << (static_cast<uint32_t>(DimIndex::K_DIM11) - static_cast<uint32_t>(len));
    1307              :     }
    1308            0 :     auto mRet = static_cast<uint16_t>(mTmp);
    1309            0 :     retVal = FP16_CONSTRUCTOR(sign, eRet, mRet);
    1310            0 : }
    1311              : 
    1312            0 : uint16_t half::Int32ToFp16(const int32_t& iVal) const
    1313              : {
    1314            0 :     uint16_t retVal = 0;
    1315            0 :     if (iVal != 0) {
    1316            0 :         uint32_t uiVal = *(reinterpret_cast<const uint32_t*>(&iVal));
    1317            0 :         auto sRet = static_cast<uint16_t>(uiVal >> static_cast<uint16_t>(BitShift::K_BIT_SHIFT31));
    1318            0 :         if (sRet != 0) {
    1319            0 :             int32_t iValM = -iVal;
    1320            0 :             uiVal = *(reinterpret_cast<uint32_t*>(&iValM));
    1321              :         }
    1322            0 :         SetValByUint32Val(uiVal, sRet, retVal);
    1323              :     }
    1324            0 :     return retVal;
    1325              : }
    1326              : 
    1327            0 : uint16_t half::UInt32ToFp16(const uint32_t& uiVal) const
    1328              : {
    1329            0 :     if (uiVal == 0) {
    1330            0 :         return 0;
    1331              :     } else {
    1332              :         uint16_t eRet;
    1333            0 :         uint32_t mTmp = uiVal;
    1334            0 :         uint32_t mMin = static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_HIDE_BIT);
    1335            0 :         uint32_t mMax = mMin << 1;
    1336            0 :         uint16_t len = static_cast<uint16_t>(GetManBitLength(mTmp));
    1337            0 :         if (len > static_cast<uint16_t>(DimIndex::K_DIM11)) {
    1338            0 :             eRet = static_cast<uint16_t>(Fp16BasicParam::K_FP16_EXP_BIAS) +
    1339              :                    static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_LEN);
    1340            0 :             uint32_t truncMask = 1;
    1341            0 :             uint16_t eTmp = len - static_cast<uint16_t>(DimIndex::K_DIM11);
    1342            0 :             for (uint16_t i = 1; i < eTmp; i++) {
    1343            0 :                 truncMask = (truncMask << 1) + 1;
    1344              :             }
    1345            0 :             uint32_t mTrunc = (mTmp & truncMask)
    1346            0 :                               << static_cast<uint32_t>(static_cast<uint16_t>(BitShift::K_BIT_SHIFT32) - eTmp);
    1347            0 :             for (uint16_t i = 0; i < eTmp; i++) {
    1348            0 :                 mTmp = (mTmp >> 1);
    1349            0 :                 eRet = eRet + 1;
    1350              :             }
    1351            0 :             bool bLastBit = ((mTmp & 1) > 0);
    1352            0 :             bool bTruncHigh = false;
    1353            0 :             bool bTruncLeft = false;
    1354              :             if (ROUND_MODE == TagFp16RoundMode::K_ROUND_TO_NEAREST) { // trunc
    1355            0 :                 bTruncHigh = ((mTrunc & static_cast<uint32_t>(Fp32BasicParam::K_FP32_SIGN_MASK)) > 0);
    1356            0 :                 bTruncLeft = ((mTrunc & static_cast<uint32_t>(Fp32BasicParam::K_FP32_ABS_MAX)) > 0);
    1357              :             }
    1358            0 :             mTmp = ManRoundToNearest(bLastBit, bTruncHigh, bTruncLeft, mTmp);
    1359            0 :             while (mTmp >= mMax) {
    1360            0 :                 mTmp = mTmp >> 1;
    1361            0 :                 eRet = eRet + 1;
    1362              :             }
    1363            0 :             if (eRet >= static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAX_EXP)) {
    1364            0 :                 eRet = static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAX_EXP) - 1;
    1365            0 :                 mTmp = static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAX_MAN);
    1366              :             }
    1367              :         } else {
    1368            0 :             eRet = static_cast<uint16_t>(Fp16BasicParam::K_FP16_EXP_BIAS);
    1369            0 :             mTmp = mTmp << (static_cast<uint32_t>(DimIndex::K_DIM11) - static_cast<uint32_t>(len));
    1370            0 :             eRet = eRet + (len - static_cast<uint16_t>(1));
    1371              :         }
    1372            0 :         auto mRet = static_cast<uint16_t>(mTmp);
    1373            0 :         return FP16_CONSTRUCTOR(0u, eRet, mRet);
    1374              :     }
    1375              : }
    1376              : 
    1377              : // evaluation
    1378            4 : half& half::operator=(const half& fp)
    1379              : {
    1380            4 :     if (&fp == this) {
    1381            0 :         return *this;
    1382              :     }
    1383            4 :     val = fp.val;
    1384            4 :     return *this;
    1385              : }
    1386            0 : half& half::operator=(const float& fVal)
    1387              : {
    1388            0 :     val = FloatToFp16(fVal);
    1389            0 :     return *this;
    1390              : }
    1391            2 : half& half::operator=(const double& dVal)
    1392              : {
    1393            2 :     val = DoubleToFp16(dVal);
    1394            2 :     return *this;
    1395              : }
    1396            0 : half& half::operator=(const int8_t& iVal)
    1397              : {
    1398            0 :     val = Int8ToFp16(iVal);
    1399            0 :     return *this;
    1400              : }
    1401            0 : half& half::operator=(const uint8_t& uiVal)
    1402              : {
    1403            0 :     val = UInt8ToFp16(uiVal);
    1404            0 :     return *this;
    1405              : }
    1406            0 : half& half::operator=(const int16_t& iVal)
    1407              : {
    1408            0 :     val = Int16ToFp16(iVal);
    1409            0 :     return *this;
    1410              : }
    1411            0 : half& half::operator=(const uint16_t& uiVal)
    1412              : {
    1413            0 :     val = UInt16ToFp16(uiVal);
    1414            0 :     return *this;
    1415              : }
    1416            0 : half& half::operator=(const int32_t& iVal)
    1417              : {
    1418            0 :     val = Int32ToFp16(iVal);
    1419            0 :     return *this;
    1420              : }
    1421            0 : half& half::operator=(const uint32_t& uiVal)
    1422              : {
    1423            0 :     val = UInt32ToFp16(uiVal);
    1424            0 :     return *this;
    1425              : }
    1426              : 
    1427              : // convert
    1428           12 : half::operator float() const { return Fp16ToFloat(val); }
    1429            0 : half::operator double() const { return Fp16ToDouble(val); }
    1430            0 : half::operator int8_t() const { return Fp16ToInt8(val); }
    1431            0 : half::operator uint8_t() const { return Fp16ToUInt8(val); }
    1432            0 : half::operator int16_t() const { return Fp16ToInt16(val); }
    1433           12 : half::operator uint16_t() const { return Fp16ToUInt16(val); }
    1434            0 : half::operator int32_t() const { return Fp16ToInt32(val); }
    1435            0 : half::operator uint32_t() const { return Fp16ToUInt32(val); }
    1436              : 
    1437            0 : int32_t half::IsInf() const
    1438              : {
    1439            0 :     if (((val) & (static_cast<uint16_t>(Fp16BasicParam::K_FP16_ABS_MAX))) ==
    1440              :         static_cast<uint16_t>(Fp16BasicParam::K_FP16_EXP_MASK)) {
    1441            0 :         if (((static_cast<uint16_t>(Fp16BasicParam::K_FP16_SIGN_MASK)) & (val)) != 0) {
    1442            0 :             return -1;
    1443              :         } else {
    1444            0 :             return 1;
    1445              :         }
    1446              :     } else {
    1447            0 :         return 0;
    1448              :     }
    1449              : }
    1450              : 
    1451            6 : float half::ToFloat() const { return Fp16ToFloat(val); }
    1452            2 : double half::ToDouble() const { return Fp16ToDouble(val); }
    1453            2 : int8_t half::ToInt8() const { return Fp16ToInt8(val); }
    1454            2 : uint8_t half::ToUInt8() const { return Fp16ToUInt8(val); }
    1455            2 : int16_t half::ToInt16() const { return Fp16ToInt16(val); }
    1456            2 : uint16_t half::ToUInt16() const { return Fp16ToUInt16(val); }
    1457           12 : int32_t half::ToInt32() const { return Fp16ToInt32(val); }
    1458            2 : uint32_t half::ToUInt32() const { return Fp16ToUInt32(val); }
    1459              : // } // namespace float16
        

Generated by: LCOV version 2.0-1