mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 15:12:02 +00:00
Fix assert in "lcm"
This commit is contained in:
parent
8f16c542b6
commit
ec281cd703
@ -1,6 +1,28 @@
|
||||
#include <Functions/FunctionFactory.h>
|
||||
#include <Functions/FunctionBinaryArithmetic.h>
|
||||
|
||||
#include <numeric>
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
constexpr T abs(T value) noexcept
|
||||
{
|
||||
if constexpr (std::is_signed_v<T>)
|
||||
{
|
||||
if (value >= 0 || value == std::numeric_limits<T>::min())
|
||||
return value;
|
||||
return -value;
|
||||
}
|
||||
else
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
namespace DB
|
||||
@ -18,9 +40,21 @@ struct LCMImpl
|
||||
{
|
||||
throwIfDivisionLeadsToFPE(typename NumberTraits::ToInteger<A>::Type(a), typename NumberTraits::ToInteger<B>::Type(b));
|
||||
throwIfDivisionLeadsToFPE(typename NumberTraits::ToInteger<B>::Type(b), typename NumberTraits::ToInteger<A>::Type(a));
|
||||
return std::lcm(
|
||||
typename NumberTraits::ToInteger<Result>::Type(a),
|
||||
typename NumberTraits::ToInteger<Result>::Type(b));
|
||||
|
||||
/** It's tempting to use std::lcm function.
|
||||
* But it has undefined behaviour on overflow.
|
||||
* And assert in debug build.
|
||||
* We need some well defined behaviour instead
|
||||
* (example: throw an exception or overflow in implementation specific way).
|
||||
*/
|
||||
|
||||
using Int = typename NumberTraits::ToInteger<Result>::Type;
|
||||
|
||||
Int val1 = abs<Int>(a) / std::gcd(Int(a), Int(b));
|
||||
Int val2 = abs<Int>(b);
|
||||
|
||||
/// Overflow in implementation specific way.
|
||||
return Result(val1 * val2);
|
||||
}
|
||||
|
||||
#if USE_EMBEDDED_COMPILER
|
||||
|
8
tests/queries/0_stateless/01435_lcm_overflow.reference
Normal file
8
tests/queries/0_stateless/01435_lcm_overflow.reference
Normal file
@ -0,0 +1,8 @@
|
||||
30
|
||||
30
|
||||
30
|
||||
30
|
||||
18446744073709551360
|
||||
-256
|
||||
-256
|
||||
-256
|
10
tests/queries/0_stateless/01435_lcm_overflow.sql
Normal file
10
tests/queries/0_stateless/01435_lcm_overflow.sql
Normal file
@ -0,0 +1,10 @@
|
||||
SELECT lcm(15, 10);
|
||||
SELECT lcm(-15, 10);
|
||||
SELECT lcm(15, -10);
|
||||
SELECT lcm(-15, -10);
|
||||
|
||||
-- Implementation specific result on overflow:
|
||||
SELECT lcm(256, 9223372036854775807);
|
||||
SELECT lcm(256, -9223372036854775807);
|
||||
SELECT lcm(-256, 9223372036854775807);
|
||||
SELECT lcm(-256, -9223372036854775807);
|
Loading…
Reference in New Issue
Block a user