我想在不使用64位数据类型的情况下进行32位有符号整数乘法。我的输入是Q1.31(两种)格式。
input1 = A32 (Ah Al) - higher, lower half's of A32
input2 = B32 (Bh Bl) - higher, lower half's of B32
结果应该是Q1.31格式,保留溢出情况。
我需要C代码。请提供格式说明。
答案 0 :(得分:8)
签名的Q1.31格式是一种完全分数格式,能够表示-1和几乎+1之间的操作数。比例因子是2 31 。这意味着当每个Q1.31操作数存储在32位有符号整数中时,我们可以通过计算有符号整数的完整双宽乘积来生成Q1.31乘积,然后将结果右移31位。右移是必要的,因为产品包括比例因子两次,并且移位充当除去比例因子的一个实例的除法。
我们可以通过分别计算完整产品的上下32位来计算两个32位整数的双宽度乘积。低32位是作为两个输入的普通乘积而平凡计算的。要计算高32位,我们需要编写函数mul32hi()
。为了避免在中间计算中使用更宽的类型(即一个使用超过32位的类型),我们需要将原始操作数分成两半,计算它们的部分乘积,然后适当地对这些部分乘积求和。
请注意,各种处理器提供实现mul32hi()
功能的硬件指令。在这种情况下,如果不存在内在的,则可能需要使用适当的内部或一些内联汇编代码,而不是使用此处提供的仿真代码。
有助于首先将问题减少到相应的无符号乘法umul32hi()
,然后通过2的补码表示(在以下C代码中假设)的定义从中导出签名结果:
#include <stdint.h>
/* compute the upper 32 bits of the product of two unsigned 32-bit integers */
uint32_t umul32hi (uint32_t a, uint32_t b)
{
/* split operands into halves */
uint32_t al = (uint16_t)a;
uint32_t ah = a >> 16;
uint32_t bl = (uint16_t)b;
uint32_t bh = b >> 16;
/* compute partial products */
uint32_t p0 = al * bl;
uint32_t p1 = al * bh;
uint32_t p2 = ah * bl;
uint32_t p3 = ah * bh;
/* sum partial products */
uint32_t cy = ((p0 >> 16) + (uint16_t)p1 + (uint16_t)p2) >> 16;
return p3 + (p2 >> 16) + (p1 >> 16) + cy;
}
/* compute the upper 32 bits of the product of two signed 32-bit integers */
int32_t mul32hi (int32_t a, int32_t b)
{
return umul32hi (a, b) - ((a < 0) ? b : 0) - ((b < 0) ? a : 0);
}
/* compute the full 64-bit product of two signed 32-bit integers */
void mul32wide (int32_t a, int32_t b, int32_t *rhi, int32_t *rlo)
{
*rlo = a * b; /* bits <31:0> of the product a * b */
*rhi = mul32hi (a, b); /* bits <63:32> of the product a * b */
}
/* compute the product of two signed Q1.31 fixed-point numbers */
int32_t mul_q_1_31 (int32_t a, int32_t b)
{
int32_t hi, lo;
mul32wide (a, b, &hi, &lo);
/* Q1.31 is scaled by 2**31, trim out scale factor */
return (int32_t)(((uint32_t)hi << 1) | ((uint32_t)lo >> 31));
}
我将请求解释为&#34;离开溢出案例&#34;意味着忽略溢出。因此,将-1(0x80000000)乘以-1(0x80000000)与mul_q_1_31()
将返回-1(0x80000000)。
答案 1 :(得分:0)
以下网站旨在提供一个ANSI-C库的32位实现,以便通常使用Q值进行操作:http://www.ti.com/tool/sprc542
我没有尝试过这个,也无法保证它会为您做什么或不做什么,但在该网站上有一个链接可以请求源代码。