微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 IEEE-754 格式寻址 LUT

如何解决使用 IEEE-754 格式寻址 LUT

当使用 LUT 时,通常会通过对一个 LUT 的位进行按位运算来获取它的地址 定点数。一个例子:

// The LUT has 8 addres: from 0 to 7 with a step of 1.
// The input number,x,is in u4.8 format

// Input number is 1.748 --> Fixed representation is 447: 0001.10111111
address = bits[1:4] + bits[4] // := 2; Returned value: 2

// Input number is 4.69 --> Fixed representation is 1201: 0100.10110001
address = bits[1:4] + bits[4] // := 5; Returned value: 5

// Input number is 7.22 --> Fixed representation is 1848: 0111.00111000
address = bits[1:4] + bits[4] // := 7; Returned value: 7

好的,我们现在假设 LUT 有 16 个存储值:从 0 到 7.5,步长为 0.5。一个例子:

// The LUT has 16 addres: from 0 to 7.5 with a step of 0.5.
// The input number,is in u4.8 format

// Input number is 1.748 --> Fixed representation is 447: 0001.10111111
address = bits[1:5] + bits[5] // := 3; Returned value: 1.5

// Input number is 4.69 --> Fixed representation is 1201: 0100.10110001
address = bits[1:5] + bits[5] // := 9; Returned value: 4.5

// Input number is 7.22 --> Fixed representation is 1848: 0111.00111000
address = bits[1:5] + bits[5] // := 14; Returned value: 7

该示例仅说明目标是根据步骤获取与输入值最接近的值对应的地址。我在所有测试中以大于 99% 的概率匹配在固定点上实现了这一点。

但是,问题是:如何在 fp32 (IEEE-754) 中实现它?因为 fp32 中的表示没有整数和小数部分,我不知道如何实现它...

编辑:第一种方法

正如评论中的@njuffa 所说,使用 IEEE-754 标准处理 LUT 的方法是使用尾数中的 MSB。该位包含地址,并且必须获得始终小于或等于地址长度的特定范围的位。我已经计算了必要的位数,将指数的位数考虑在内。例如,如果 LUT 的步骤为 1/256,那么我解析地址的方式是:

// To normalize the exponent
exponent = exponent - 127;

// msb indicates the number of bits to get from
// from the mantissa. This bits are the MSB. I have
// checked for large LUTS: 2¹⁸ stored values and always
// works well :)
// The step is 1/256: np.log2(step) = 8 --> The number of
// bits in the step!
msb = int(np.log2(step) - exp) 

// And finally,get the bits from the mantissa
address = mantissa[31:msb]

最后,如果需要四舍五入到最接近,则需要添加,但如果使用表插值四舍五入到最接近,则不需要。

当输入值接近于零时,我已经感知到,有时地址不正确。始终与参考测试相差一个

这种解析地址的方法只有在 lut 中的 step 是 2 的幂时才是正确的。例如:如果 LUT 的 step 是 pi/(4*512),范围从 0 到 { {1}},存储在 LUT 中的总值将是 512,但步长为 pi/4,因此据我所知,有必要执行除法。

这是我为验证地址正确而执行的测试。

pi

以及一个测试的样本(当一个或多个地址不正确时显示 False):

import numpy as np
import struct

# if mode == 0: No nearest rounding for address
# if mode == 1: Nearest rounding for address
MODE = 0
step = 256 # Step size in the LUT 
max_value = 4 # Only for test purposes
LUT = np.arange(0,max_value,1/step)

# Reference test
def ref_addressing(x):
    if MODE == 0:
        ref_address = (np.floor(x * step)).astype(np.int32)
    elif MODE == 1:
        ref_address = (np.round(x * step)).astype(np.int32)
    return ref_address

# Test
def test_addressing(x):
    j = 0
    test_address = np.zeros(len(x),dtype=np.int32)
    for x_ in x:
        test_address[j] = ieee754_address(x_)
        j = j + 1
    return test_address



# Convert value to IEEE-754 Standard
def float_to_bin(num):
    bits,= struct.unpack('!I',struct.pack('!f',num))
    return "{:032b}".format(bits)

# Resolves the address with the MSB's bits of the mantissa
def ieee754_address(x):
    ieee754 = float_to_bin(x) # Get the number in IEEE754 Standard
    exp = 127 - int(ieee754[1:9],2) # Calculte the exponent
    mnt = ieee754[9::] # Get the mantissa
    
    # How many bits are needed for succesfull addresing?
    # np.log2(step): Maximun number of bits in the step size
    # ObvIoUsly,these values are fixed in the hardware 
    # implementation. Only for testing.
    msb = int(np.log2(step) - exp)
    
    # Get the address. Don't forget the hidden bit!
    address = int('1'+mnt[0:msb],2)
    
    # If rounding to the nearest,MODE == 1
    if MODE == 1:
        # int(mnt[msb],2) --> Rounding bit
        address = address + int(mnt[msb],2)
    
    # Negatives address if exp > int(np.log2(step)
    if exp > int(np.log2(step):
        address = 0
    return address

# Uniform random values to check all the range
r = np.random.uniform(0.0,65536)

# Perform the tests
ref_address = ref_addressing(r)
test_address = test_addressing(r)

# Statistics and report
diffs = ref_address - test_address
errors = len(np.where(diffs != 0)[0])
p = (1 - (errors / len(r))) * 100

print("-----------------------------------")
print("Total test's samples : %i " % (len(r)))
print("-----------------------------------")
print("Equal addrressing    : %r " % (np.array_equal(ref_address,test_address)))
print("Errors               : %i " % errors)
print("Probability matching : %0.3f %% " % p)
print("-----------------------------------")

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。