问题描述
我有以下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。