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

Generated by: LCOV version 2.0-1