将两个无符号整数相乘作为无符号int

问题描述

我有以下C函数,该函数对GPU上的32位无符号整数执行一些乘法和移位。假设我从值X = 0和C = 2开始。

void MWC64X_Step(global mwc64x_state_t *s)
{
    uint X=s->x,C=s->c;
    printf("X = %u,C = %u,",X,C);
    uint Xn=MWC64X_A*X+C;
    uint carry=(uint)(Xn<C); //The (Xn<C) will be zero or one for scalar
    uint Cn=mad_hi(MWC64X_A,carry);
    printf("Xn = %u,Cn = %u,Xn,Cn);
    s->x=Xn;
    s->c=Cn;
}

使用

typedef struct{ uint x; uint c; } mwc64x_state_t;

enum{ MWC64X_A = 4294883355U };
enum{ MWC64X_M = 18446383549859758079UL };

功能是我在网上找到的软件包的一部分。我很好奇,如果X变得非常大,约为2^32,因为Xn被声明为无符号整数(在我的平台上为32位),那么它是如何计算的? Xn只是保留模MAX_INT_32的值,还是执行其他一些运算?

我从X = 0和C = 2的几次连续运行中得到的结果:

Xn = 2,Cn = 0,Xn = 4294799414,Cn = 1,Xn = 1207281075,Cn = 4294715476. <--- 3rd iteration

谢谢

解决方法

常量MWC64X_A = 4294883355U与-83941 mod 2 ^ 32是一致的。

2 *(-83941)+ 0 = -167882,与4294799414 mod 2 ^ 32是一致的。

(-167882)*(-83941)= 14092182962,这与1207281074 mod 2 ^ 32(根据Excel)一致,并且1207281074 + 1 =1207281075。因此,您得到的结果与采用乘法结果一致每次取模2 ^ 32。