17 uint64_t
Math::MulDiv64(uint64_t operant, uint64_t multiplier, uint64_t divider)
19 #if defined(__GNUC__) && defined(__SIZEOF_INT128__)
20 __uint128_t a = operant;
21 __uint128_t b = multiplier;
22 __uint128_t c = divider;
24 return (uint64_t)(a * b / c);
25 #elif defined(_MSC_VER)
34 #define REMAINDER quotient
40 mov eax, dword ptr[operant+4]
41 xor eax, dword ptr[multiplier+4]
42 xor eax, dword ptr[divider+4]
49 mov eax, dword ptr[divider+4]
50 or eax, dword ptr[divider]
57 cmp eax, dword ptr[multiplier+4]
59 cmp eax, dword ptr[multiplier]
67 mov dword ptr[edi+12], eax
68 mov dword ptr[edi+8], eax
70 cmp eax, dword ptr[multiplier]
73 mov eax, dword ptr[operant+4]
74 mov dword ptr[edi+4], eax
75 mov eax, dword ptr[operant]
76 mov dword ptr[edi], eax
81 mov ecx, dword ptr[operant+4]
82 or ecx, eax ;test
for both hiwords zero.
85 mov ecx, dword ptr[multiplier]
86 mov eax, dword ptr[operant]
88 mov dword ptr[edi+4], edx
89 mov dword ptr[edi], eax
94 mov eax, dword ptr[multiplier]
95 mul dword ptr[operant]
96 mov dword ptr[edi], eax
99 mov eax, dword ptr[multiplier]
100 mul dword ptr[operant+4]
106 mov eax, dword ptr[multiplier+4]
107 mul dword ptr[operant]
109 mov dword ptr[edi+4], eax
113 mov eax, dword ptr[multiplier+4]
114 mul dword ptr[operant+4]
118 mov dword ptr[edi+8], eax
119 mov dword ptr[edi+12], edx
124 mov eax, dword ptr[divider+4]
127 mov ecx, dword ptr[divider]
132 mov eax, dword ptr[edi+12]
135 mov dword ptr[quotient+12], eax
137 mov eax, dword ptr[edi+8]
139 mov dword ptr[quotient+8], eax
141 mov eax, dword ptr[edi+4]
143 mov dword ptr[quotient+4], eax
145 mov eax, dword ptr[edi]
147 mov dword ptr[quotient], eax
150 mov eax, dword ptr[quotient+12]
151 mov dword ptr[edi+12], eax
152 mov eax, dword ptr[quotient+8]
153 mov dword ptr[edi+8], eax
154 mov eax, dword ptr[quotient+4]
155 mov dword ptr[edi+4], eax
156 mov eax, dword ptr[quotient]
157 mov dword ptr[edi], eax
164 mov dword ptr[REMAINDER+12], eax
165 mov dword ptr[REMAINDER+8], eax
166 mov dword ptr[REMAINDER+4], eax
167 mov dword ptr[REMAINDER], eax
172 shl dword ptr[QUOTIENT], 1
173 rcl dword ptr[QUOTIENT+4], 1
174 rcl dword ptr[QUOTIENT+8], 1
175 rcl dword ptr[QUOTIENT+12], 1
176 rcl dword ptr[REMAINDER], 1
177 rcl dword ptr[REMAINDER+4], 1
178 rcl dword ptr[REMAINDER+8], 1
179 rcl dword ptr[REMAINDER+12], 1
183 cmp dword ptr[REMAINDER+12], eax
187 cmp dword ptr[REMAINDER+8], eax
191 mov eax, dword ptr[REMAINDER+4]
192 cmp eax, dword ptr[divider+4]
196 mov eax, dword ptr[REMAINDER]
197 cmp eax, dword ptr[divider]
201 mov eax, dword ptr[divider]
202 sub dword ptr[REMAINDER], eax
203 mov eax, dword ptr[divider+4]
204 sbb dword ptr[REMAINDER+4], eax
206 sbb dword ptr[REMAINDER+8], eax
207 sbb dword ptr[REMAINDER+12], eax
209 add dword ptr[QUOTIENT], 1
210 adc dword ptr[QUOTIENT+4], 0
211 adc dword ptr[QUOTIENT+8], 0
212 adc dword ptr[QUOTIENT+12], 0
221 not dword ptr[edi+12]
222 not dword ptr[edi+ 8]
223 not dword ptr[edi+ 4]
225 add dword ptr[edi], 1
226 adc dword ptr[edi+ 4], 0
227 adc dword ptr[edi+ 8], 0
228 adc dword ptr[edi+12], 0
232 mov edx, dword ptr[edi+4]
233 mov eax, dword ptr[edi]
237 #elif defined (_M_X64 )
238 #pragma warning(push)
239 #pragma warning(disable: 4244)
240 uint64_t a = operant;
241 uint64_t b = multiplier;
242 uint64_t c = divider;
246 _BitScanReverse64(&shift, c);
252 a = _umul128(a, b, &b);
253 if (((b << shift) >> shift) != b)
256 return 0xFFFFFFFFFFFFFFFF;
258 b = __shiftleft128(a, b, shift);
266 div = (uint32_t)(c >> 32);
273 t0 = _umul128(c, (uint64_t)q1 << 32, &t1);
274 if (t1 < b || (t1 == b && t0 <= a))
286 return 0xFFFFFFFFFFFFFFFF;
290 t0 = ((b << 32) | (a >> 32)) / div;
297 t0 = _umul128(c, q0, &t1);
298 if (t1 < b || (t1 == b && t0 <= a))
303 return ((uint64_t)q1 << 32) | q0;
307 #error MulDiv64 is no supported!
static uint64_t MulDiv64(uint64_t operant, uint64_t multiplier, uint64_t divider)
Calculate (operant * multiplier / divider) with 64-bit unsigned integer values.
C++ Common project definitions.