Search code examples
cinteger-overflowunsigned-integer

Multiplication of two unsigned integers as an unsigned int


I have the following C function which performs some multiplications and bit-shifting on 32-bit unsigned integers on GPU. Let's say I start with values X = 0 and 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,X,carry);
    printf("Xn = %u, Cn = %u, ", Xn, Cn);
    s->x=Xn;
    s->c=Cn;
}

with

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

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

The function is part of a package I found online. I am curious to understand if X becomes very very large, of the order of 2^32, since Xn is declared as an unsigned int (32 bits on my platform), then how is it calculated? Does Xn just keep the value of modulo MAX_INT_32, or does it perform some other operation(s)?

Results I get from a few consecutive runs with X=0 and C=2:

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

Thanks,


Solution

  • The constant MWC64X_A = 4294883355U is congruent to -83941 mod 2^32.

    2 * (-83941) + 0 = -167882, which is congruent to 4294799414 mod 2^32.

    (-167882) * (-83941) = 14092182962, which is congruent to 1207281074 mod 2^32 (according to Excel), and 1207281074 + 1 = 1207281075. So the results you get are consistent with taking the results of multiplication modulo 2^32 every time.