File tree Expand file tree Collapse file tree 1 file changed +42
-0
lines changed
Expand file tree Collapse file tree 1 file changed +42
-0
lines changed Original file line number Diff line number Diff line change 1212
1313#include < limits>
1414#include < iostream>
15+ #include < limits>
1516
1617#endif
1718
@@ -288,6 +289,11 @@ constexpr int128_t gcd(const int128_t a, const int128_t b) noexcept
288289 return static_cast <int128_t >(gcd (static_cast <uint128_t >(abs (a)), static_cast <uint128_t >(abs (b))));
289290}
290291
292+ // For unknown reasons this implementation fails for MSVC x86 only in release mode
293+ // Directly calculating leads to the same failures, so unfortunately we have a viable,
294+ // but very slow impl that we know works.
295+ #if !(defined(_M_IX86) && !defined(_NDEBUG))
296+
291297constexpr uint128_t lcm (const uint128_t a, const uint128_t b) noexcept
292298{
293299 if (a == 0U || b == 0U )
@@ -302,6 +308,42 @@ constexpr uint128_t lcm(const uint128_t a, const uint128_t b) noexcept
302308 return (a / g) * b;
303309}
304310
311+ #else
312+
313+ constexpr uint128_t lcm (uint128_t a, uint128_t b) noexcept
314+ {
315+ if (a == 0U || b == 0U )
316+ {
317+ return 0 ;
318+ }
319+
320+
321+ unsigned shift{};
322+ while ((a & 1U ) == 0U && (b & 1U ) == 0U )
323+ {
324+ a >>= 1U ;
325+ b >>= 1U ;
326+ shift++;
327+ }
328+
329+ // Ensure a >= b
330+ if (a < b)
331+ {
332+ std::swap (a, b);
333+ }
334+
335+ uint128_t lcm{a};
336+
337+ while (lcm % b != 0U )
338+ {
339+ lcm += a;
340+ }
341+
342+ return lcm << shift;
343+ }
344+
345+ #endif
346+
305347constexpr int128_t lcm (const int128_t a, const int128_t b) noexcept
306348{
307349 return static_cast <int128_t >(lcm (static_cast <uint128_t >(abs (a)), static_cast <uint128_t >(abs (b))));
You can’t perform that action at this time.
0 commit comments