LCOV - code coverage report
Current view: top level - adump/printf - hifloat.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 97.6 % 84 82
Test Date: 2026-08-31 10:09:28 Functions: 100.0 % 8 8

            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              : #include "hifloat.h"
      11              : 
      12              : #include <bitset>
      13              : #include <limits>
      14              : #include <unordered_map>
      15              : #include "log/hdc_log.h"
      16              : 
      17              : namespace Adx {
      18              : constexpr int32_t FP8E8M0_EXPONENT_BIAS = 127U;
      19              : constexpr size_t ONE_BYTE_BIT_NUM = 8U;
      20              : constexpr uint32_t FP8E5M2_EXPONENT_BIT_NUM = 5U;
      21              : constexpr uint32_t FP8E4M3_EXPONENT_BIT_NUM = 4U;
      22              : constexpr int32_t HIFLOAT8_SUBNORMAL_NUM = 23;
      23              : 
      24              : static std::unordered_map<std::string, float> g_adxMantissaMapB2f = {
      25              :     {"000", 0},     {"001", 0.125}, {"010", 0.25}, {"011", 0.375}, {"100", 0.5}, {"101", 0.625}, {"110", 0.75},
      26              :     {"111", 0.875}, {"00", 0},      {"01", 0.25},  {"10", 0.5},    {"11", 0.75}, {"0", 0},       {"1", 0.5}};
      27              : 
      28              : static std::unordered_map<std::string, float> g_adxPresetEncoedsMap = {
      29              :     {"00000000", 0},
      30              :     {"10000000", std::numeric_limits<float>::quiet_NaN()},
      31              :     {"01101111", std::numeric_limits<float>::infinity()},
      32              :     {"11101111", -std::numeric_limits<float>::infinity()}};
      33              : 
      34              : static std::unordered_map<std::string, uint32_t> g_adxConventionalMap = {{"11", 4},  {"10", 3},   {"01", 2},
      35              :                                                                          {"001", 1}, {"0001", 0}, {"0000", 0}};
      36              : 
      37           45 : static inline std::string ByteToBinary(const uint8_t byte) { return std::bitset<ONE_BYTE_BIT_NUM>(byte).to_string(); }
      38              : 
      39            7 : int32_t HiFloat8::GetExponent(const std::string& binary) const
      40              : {
      41            7 :     if (binary.length() == 0) {
      42            1 :         return 0;
      43              :     }
      44            6 :     int32_t symbol = binary.substr(0, 1) == "0" ? 1 : -1;
      45            6 :     std::string revisedBinary = "1" + binary.substr(1);
      46            6 :     return symbol * std::stoi(revisedBinary, nullptr, BASE_NUM);
      47            6 : }
      48              : 
      49            7 : float HiFloat8::GetMantissaField(const std::string& binary) const
      50              : {
      51            7 :     return std::stoi(binary, nullptr, BASE_NUM) / static_cast<float>(pow(BASE_NUM, binary.length()));
      52              : }
      53              : 
      54           12 : float HiFloat8::GetValue() const
      55              : {
      56           12 :     std::string bitString = ByteToBinary(val);
      57           12 :     float value = 0.0;
      58           12 :     if (g_adxPresetEncoedsMap.find(bitString) != g_adxPresetEncoedsMap.end()) {
      59            4 :         value = g_adxPresetEncoedsMap[bitString];
      60            4 :         return value;
      61              :     }
      62            8 :     if (bitString.length() == ONE_BYTE_BIT_NUM) {
      63            8 :         std::string symbolBit = bitString.substr(0, 1);
      64            8 :         int32_t signVal = symbolBit == "0" ? 1 : -1;
      65            8 :         std::string dotField;
      66            8 :         uint32_t dotVal = 0;
      67           29 :         for (const auto& pair : g_adxConventionalMap) {
      68           29 :             const std::string& dot = pair.first;
      69           29 :             if (bitString.substr(1).find(dot) == 0) {
      70            8 :                 dotField = dot;
      71            8 :                 dotVal = pair.second;
      72            8 :                 break;
      73              :             }
      74              :         }
      75            8 :         if (dotField.empty()) {
      76            0 :             IDE_LOGE("No dot field was found.");
      77            0 :             return std::numeric_limits<float>::max();
      78              :         }
      79            8 :         if (dotField == "0000") {
      80            1 :             std::string mantissaBit = bitString.substr(1 + dotField.length());
      81            1 :             int32_t mantissaVal = std::stoi(mantissaBit, nullptr, BASE_NUM);
      82            1 :             value = signVal * static_cast<float>(pow(BASE_NUM, mantissaVal - HIFLOAT8_SUBNORMAL_NUM));
      83            1 :             return value;
      84            1 :         }
      85            7 :         int32_t exponentField = GetExponent(bitString.substr(1 + dotField.length(), dotVal));
      86            7 :         float mantissaField = GetMantissaField(bitString.substr(1 + dotField.length() + dotVal));
      87            7 :         value = signVal * static_cast<float>(pow(BASE_NUM, exponentField) * (1 + mantissaField));
      88            9 :     }
      89            7 :     return value;
      90           12 : }
      91              : 
      92           20 : float FpaEbMc::Decode(
      93              :     const std::string& bitString, const std::string& exponentBit, const std::string& mantissaBit,
      94              :     const uint32_t exponentBitNum) const
      95              : {
      96           20 :     int32_t exponentBias = (1 << (exponentBitNum - 1)) - 1;
      97           20 :     int32_t signVal = std::stoi(bitString.substr(0, 1), nullptr, BASE_NUM);
      98           20 :     int32_t exponentVal = std::stoi(exponentBit, nullptr, BASE_NUM);
      99           20 :     bool isNormal = exponentVal == 0U ? false : true;
     100           20 :     float value = 0.0;
     101           20 :     if (isNormal) {
     102           14 :         value = static_cast<float>(
     103           14 :             pow(-1, signVal) * pow(BASE_NUM, exponentVal - exponentBias) * (1 + g_adxMantissaMapB2f[mantissaBit]));
     104              :     } else {
     105            6 :         value = static_cast<float>(
     106            6 :             pow(-1, signVal) * pow(BASE_NUM, exponentVal - exponentBias + 1) * g_adxMantissaMapB2f[mantissaBit]);
     107              :     }
     108           20 :     return value;
     109              : }
     110              : 
     111           12 : float Fp8E5M2::GetValue() const
     112              : {
     113           12 :     std::string bitString = ByteToBinary(val);
     114           12 :     std::string exponentBit = bitString.substr(1, FP8E5M2_EXPONENT_BIT_NUM);
     115           12 :     std::string mantissaBit = bitString.substr(1 + FP8E5M2_EXPONENT_BIT_NUM);
     116           12 :     if (exponentBit == "11111" && mantissaBit == "00") {
     117            2 :         return static_cast<float>(pow(-1, std::stoi(bitString.substr(0, 1), nullptr, BASE_NUM))) *
     118            1 :                std::numeric_limits<float>::infinity();
     119           11 :     } else if (exponentBit == "11111") {
     120            1 :         return std::numeric_limits<float>::quiet_NaN();
     121              :     }
     122           10 :     return Decode(bitString, exponentBit, mantissaBit, FP8E5M2_EXPONENT_BIT_NUM);
     123           12 : }
     124              : 
     125           11 : float Fp8E4M3::GetValue() const
     126              : {
     127           11 :     std::string bitString = ByteToBinary(val);
     128           11 :     std::string exponentBit = bitString.substr(1, FP8E4M3_EXPONENT_BIT_NUM);
     129           11 :     std::string mantissaBit = bitString.substr(1 + FP8E4M3_EXPONENT_BIT_NUM);
     130           11 :     if (exponentBit == "1111" && mantissaBit == "111") {
     131            1 :         return std::numeric_limits<float>::quiet_NaN();
     132              :     }
     133           10 :     return Decode(bitString, exponentBit, mantissaBit, FP8E4M3_EXPONENT_BIT_NUM);
     134           11 : }
     135              : 
     136           10 : float Fp8E8M0::GetValue() const
     137              : {
     138           10 :     std::string bitString = ByteToBinary(val);
     139           10 :     float value = 0.0;
     140           10 :     std::string exponentBit = bitString.substr(0, ONE_BYTE_BIT_NUM);
     141           10 :     if (exponentBit == "11111111") {
     142            1 :         value = std::numeric_limits<float>::quiet_NaN();
     143            1 :         return value;
     144              :     }
     145              :     // exponentBit为空时stoi会抛异常,可以保证exponentBit不会为空
     146            9 :     int32_t exponentVal = std::stoi(exponentBit, nullptr, BASE_NUM);
     147            9 :     value = static_cast<float>(pow(BASE_NUM, exponentVal - FP8E8M0_EXPONENT_BIAS));
     148            9 :     return value;
     149           10 : }
     150              : }; // namespace Adx
        

Generated by: LCOV version 2.0-1