Coverage for /opt/cloud/slavespace/usr1/096471637100f3de0fcfc01072822a80/dttest/api/python/ge/ge/graph/_numeric.py: 98%

41 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-07-27 10:03 +0800

1#!/usr/bin/env python3 

2# -*- coding: utf-8 -*- 

3# ------------------------------------------------------------------- 

4# ----------------------------------------------------------------------------------------------------------- 

5# Copyright (c) 2025 Huawei Technologies Co., Ltd. 

6# This program is free software, you can redistribute it and/or modify it under the terms and conditions of 

7# CANN Open Software License Agreement Version 2.0 (the "License"). 

8# Please refer to the License for details. You may not use this file except in compliance with the License. 

9# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, 

10# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. 

11# See LICENSE in the root of the software repository for the full text of the License. 

12# ----------------------------------------------------------------------------------------------------------- 

13 

14"""Numeric module for numeric operations in GraphEngine.""" 

15 

16import struct 

17from typing import List 

18 

19__all__ = ["float_to_fp16_bits", "float_list_to_fp16_bits"] 

20 

21 

22def float_to_fp16_bits(value: float) -> int: 

23 """Convert float to fp16 bits.""" 

24 f32 = struct.unpack("<I", struct.pack("<f", float(value)))[0] 

25 sign = (f32 >> 31) & 0x1 

26 exponent = (f32 >> 23) & 0xFF 

27 mantissa = f32 & 0x7FFFFF 

28 

29 if exponent == 255: 

30 half_exp = 0x1F 

31 half_mant = 0x200 if mantissa != 0 else 0 

32 else: 

33 exponent -= 127 

34 if exponent > 15: 

35 half_exp = 0x1F 

36 half_mant = 0 

37 elif exponent < -14: 

38 if exponent < -24: 

39 half_exp = 0 

40 half_mant = 0 

41 else: 

42 mantissa |= 0x800000 

43 shift = -exponent - 14 

44 shifted = mantissa >> (shift + 13) 

45 round_bit = (mantissa >> (shift + 12)) & 0x1 

46 remainder = mantissa & ((1 << (shift + 12)) - 1) 

47 if round_bit and ((shifted & 0x1) or remainder): 

48 shifted += 1 

49 half_exp = 0 

50 half_mant = shifted 

51 else: 

52 half_exp = exponent + 15 

53 half_mant = mantissa >> 13 

54 round_bits = mantissa & 0x1FFF 

55 if round_bits > 0x1000 or (round_bits == 0x1000 and (half_mant & 0x1)): 

56 half_mant += 1 

57 if half_mant == 0x400: 

58 half_mant = 0 

59 half_exp += 1 

60 if half_exp == 0x1F: 

61 half_mant = 0 

62 return (sign << 15) | ((half_exp & 0x1F) << 10) | (half_mant & 0x3FF) 

63 

64 

65def float_list_to_fp16_bits(values: List[float]) -> List[int]: 

66 """Convert float list to fp16 bits list.""" 

67 return [float_to_fp16_bits(v) for v in values]