问题描述
当使用 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 (将#修改为@)