Geant4-11
Functions
helpers.h File Reference
#include <cstdint>

Go to the source code of this file.

Functions

static uint64_t add_carry (uint64_t a, uint64_t b, unsigned &carry)
 Compute a + b and increment carry if there was an overflow. More...
 
static uint64_t add_overflow (uint64_t a, uint64_t b, unsigned &overflow)
 Compute a + b and set overflow accordingly. More...
 
static int64_t compute_r (const uint64_t *upper, uint64_t *r)
 
static uint64_t sub_carry (uint64_t a, uint64_t b, unsigned &carry)
 Compute a - b and increment carry if there was an overflow. More...
 
static uint64_t sub_overflow (uint64_t a, uint64_t b, unsigned &overflow)
 Compute a - b and set overflow accordingly. More...
 

Function Documentation

◆ add_carry()

static uint64_t add_carry ( uint64_t  a,
uint64_t  b,
unsigned &  carry 
)
inlinestatic

Compute a + b and increment carry if there was an overflow.

Definition at line 24 of file helpers.h.

24 {
25 unsigned overflow;
26 uint64_t add = add_overflow(a, b, overflow);
27 // Do NOT branch on overflow to avoid jumping code, just add 0 if there was
28 // no overflow.
29 carry += overflow;
30 return add;
31}
static uint64_t add_overflow(uint64_t a, uint64_t b, unsigned &overflow)
Compute a + b and set overflow accordingly.
Definition: helpers.h:16

References add_overflow().

Referenced by compute_r(), multiply9x9(), and to_ranlux().

◆ add_overflow()

static uint64_t add_overflow ( uint64_t  a,
uint64_t  b,
unsigned &  overflow 
)
inlinestatic

Compute a + b and set overflow accordingly.

Definition at line 16 of file helpers.h.

17 {
18 uint64_t add = a + b;
19 overflow = (add < a);
20 return add;
21}

Referenced by add_carry(), compute_r(), multiply9x9(), to_lcg(), and to_ranlux().

◆ compute_r()

static int64_t compute_r ( const uint64_t *  upper,
uint64_t *  r 
)
inlinestatic

Update r = r - (t1 + t2) + (t3 + t2) * b ** 10

This function also yields cbar = floor(r / m) as its return value (int64_t because the value can be -1). With an initial value of r = t0, this can be used for computing the remainder after division by m (see the function mod_m in mulmod.h). The function to_ranlux passes r = 0 and uses only the return value to obtain the decimal expansion after divison by m.

Definition at line 58 of file helpers.h.

58 {
59 // Subtract t1 (24 * 24 = 576 bits)
60 unsigned carry = 0;
61 for (int i = 0; i < 9; i++) {
62 uint64_t r_i = r[i];
63 r_i = sub_overflow(r_i, carry, carry);
64
65 uint64_t t1_i = upper[i];
66 r_i = sub_carry(r_i, t1_i, carry);
67 r[i] = r_i;
68 }
69 int64_t c = -((int64_t)carry);
70
71 // Subtract t2 (only 240 bits, so need to extend)
72 carry = 0;
73 for (int i = 0; i < 9; i++) {
74 uint64_t r_i = r[i];
75 r_i = sub_overflow(r_i, carry, carry);
76
77 uint64_t t2_bits = 0;
78 if (i < 4) {
79 t2_bits += upper[i + 5] >> 16;
80 if (i < 3) {
81 t2_bits += upper[i + 6] << 48;
82 }
83 }
84 r_i = sub_carry(r_i, t2_bits, carry);
85 r[i] = r_i;
86 }
87 c -= carry;
88
89 // r += (t3 + t2) * 2 ** 240
90 carry = 0;
91 {
92 uint64_t r_3 = r[3];
93 // 16 upper bits
94 uint64_t t2_bits = (upper[5] >> 16) << 48;
95 uint64_t t3_bits = (upper[0] << 48);
96
97 r_3 = add_carry(r_3, t2_bits, carry);
98 r_3 = add_carry(r_3, t3_bits, carry);
99
100 r[3] = r_3;
101 }
102 for (int i = 0; i < 3; i++) {
103 uint64_t r_i = r[i + 4];
104 r_i = add_overflow(r_i, carry, carry);
105
106 uint64_t t2_bits = (upper[5 + i] >> 32) + (upper[6 + i] << 32);
107 uint64_t t3_bits = (upper[i] >> 16) + (upper[1 + i] << 48);
108
109 r_i = add_carry(r_i, t2_bits, carry);
110 r_i = add_carry(r_i, t3_bits, carry);
111
112 r[i + 4] = r_i;
113 }
114 {
115 uint64_t r_7 = r[7];
116 r_7 = add_overflow(r_7, carry, carry);
117
118 uint64_t t2_bits = (upper[8] >> 32);
119 uint64_t t3_bits = (upper[3] >> 16) + (upper[4] << 48);
120
121 r_7 = add_carry(r_7, t2_bits, carry);
122 r_7 = add_carry(r_7, t3_bits, carry);
123
124 r[7] = r_7;
125 }
126 {
127 uint64_t r_8 = r[8];
128 r_8 = add_overflow(r_8, carry, carry);
129
130 uint64_t t3_bits = (upper[4] >> 16) + (upper[5] << 48);
131
132 r_8 = add_carry(r_8, t3_bits, carry);
133
134 r[8] = r_8;
135 }
136 c += carry;
137
138 // c = floor(r / 2 ** 576) has been computed along the way via the carry
139 // flags. Now if c = 0 and the value currently stored in r is greater or
140 // equal to m, we need cbar = 1 and subtract m, otherwise cbar = c. The
141 // value currently in r is greater or equal to m, if and only if one of
142 // the last 240 bits is set and the upper bits are all set.
143 bool greater_m = r[0] | r[1] | r[2] | (r[3] & 0x0000ffffffffffff);
144 greater_m &= (r[3] >> 48) == 0xffff;
145 for (int i = 4; i < 9; i++) {
146 greater_m &= (r[i] == UINT64_MAX);
147 }
148 return c + (c == 0 && greater_m);
149}
static uint64_t sub_overflow(uint64_t a, uint64_t b, unsigned &overflow)
Compute a - b and set overflow accordingly.
Definition: helpers.h:34
static uint64_t sub_carry(uint64_t a, uint64_t b, unsigned &carry)
Compute a - b and increment carry if there was an overflow.
Definition: helpers.h:42
static uint64_t add_carry(uint64_t a, uint64_t b, unsigned &carry)
Compute a + b and increment carry if there was an overflow.
Definition: helpers.h:24

References add_carry(), add_overflow(), sub_carry(), and sub_overflow().

Referenced by mod_m(), and to_ranlux().

◆ sub_carry()

static uint64_t sub_carry ( uint64_t  a,
uint64_t  b,
unsigned &  carry 
)
inlinestatic

Compute a - b and increment carry if there was an overflow.

Definition at line 42 of file helpers.h.

42 {
43 unsigned overflow;
44 uint64_t sub = sub_overflow(a, b, overflow);
45 // Do NOT branch on overflow to avoid jumping code, just add 0 if there was
46 // no overflow.
47 carry += overflow;
48 return sub;
49}

References sub_overflow().

Referenced by compute_r(), mod_m(), and to_lcg().

◆ sub_overflow()

static uint64_t sub_overflow ( uint64_t  a,
uint64_t  b,
unsigned &  overflow 
)
inlinestatic

Compute a - b and set overflow accordingly.

Definition at line 34 of file helpers.h.

35 {
36 uint64_t sub = a - b;
37 overflow = (sub > a);
38 return sub;
39}

Referenced by compute_r(), mod_m(), sub_carry(), and to_lcg().