mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-10 09:32:06 +00:00
gcd and lcm for big integers
This commit is contained in:
parent
fee0314057
commit
7d93734f54
@ -1,9 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <ostream>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "wide_integer.h"
|
||||
|
||||
|
||||
namespace wide
|
||||
{
|
||||
|
||||
@ -33,3 +36,34 @@ inline std::string to_string(const integer<Bits, Signed> & n)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
template <size_t Bits, typename Signed>
|
||||
std::ostream & operator<<(std::ostream & out, const wide::integer<Bits, Signed> & value)
|
||||
{
|
||||
return out << to_string(value);
|
||||
}
|
||||
|
||||
|
||||
/// See https://fmt.dev/latest/api.html#formatting-user-defined-types
|
||||
template <size_t Bits, typename Signed>
|
||||
struct fmt::formatter<wide::integer<Bits, Signed>>
|
||||
{
|
||||
constexpr auto parse(format_parse_context & ctx)
|
||||
{
|
||||
auto it = ctx.begin();
|
||||
auto end = ctx.end();
|
||||
|
||||
/// Only support {}.
|
||||
if (it != end && *it != '}')
|
||||
throw format_error("invalid format");
|
||||
|
||||
return it;
|
||||
}
|
||||
|
||||
template <typename FormatContext>
|
||||
auto format(const wide::integer<Bits, Signed> & value, FormatContext & ctx)
|
||||
{
|
||||
return format_to(ctx.out(), "{}", to_string(value));
|
||||
}
|
||||
};
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
#include <DataTypes/NumberTraits.h>
|
||||
#include <Common/Exception.h>
|
||||
#include <numeric>
|
||||
#include <common/extended_types.h>
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
|
||||
@ -20,8 +20,6 @@ namespace ErrorCodes
|
||||
extern const int DECIMAL_OVERFLOW;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline constexpr bool is_gcd_lcm_implemeted = !is_big_int_v<T>;
|
||||
|
||||
template <typename A, typename B, typename Impl, typename Name>
|
||||
struct GCDLCMImpl
|
||||
@ -30,15 +28,7 @@ struct GCDLCMImpl
|
||||
static const constexpr bool allow_fixed_string = false;
|
||||
|
||||
template <typename Result = ResultType>
|
||||
static inline std::enable_if_t<!is_gcd_lcm_implemeted<Result>, Result>
|
||||
apply(A, B)
|
||||
{
|
||||
throw Exception(ErrorCodes::NOT_IMPLEMENTED, "{} is not implemented for big integers", Name::name);
|
||||
}
|
||||
|
||||
template <typename Result = ResultType>
|
||||
static inline std::enable_if_t<is_gcd_lcm_implemeted<Result>, Result>
|
||||
apply(A a, B b)
|
||||
static inline Result apply(A a, B b)
|
||||
{
|
||||
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));
|
||||
@ -50,7 +40,7 @@ struct GCDLCMImpl
|
||||
/// gcd() internally uses std::abs()
|
||||
Int a_s = static_cast<Int>(a);
|
||||
Int b_s = static_cast<Int>(b);
|
||||
Int min = std::numeric_limits<Int>::min();
|
||||
Int min = std::numeric_limits<Int>::lowest();
|
||||
Int max = std::numeric_limits<Int>::max();
|
||||
if (unlikely((a_s == min || a_s == max) || (b_s == min || b_s == max)))
|
||||
throw Exception(ErrorCodes::DECIMAL_OVERFLOW, "Intermediate result overflow (signed a = {}, signed b = {}, min = {}, max = {})", a_s, b_s, min, max);
|
||||
|
@ -2,6 +2,8 @@
|
||||
#include <Functions/FunctionBinaryArithmetic.h>
|
||||
#include <Functions/GCDLCMImpl.h>
|
||||
|
||||
#include <boost/math/common_factor.hpp>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
@ -19,7 +21,7 @@ struct GCDImpl : public GCDLCMImpl<A, B, GCDImpl<A, B>, NameGCD>
|
||||
static ResultType applyImpl(A a, B b)
|
||||
{
|
||||
using Int = typename NumberTraits::ToInteger<ResultType>::Type;
|
||||
return std::gcd(Int(a), Int(b));
|
||||
return boost::math::gcd(Int(a), Int(b));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -2,6 +2,9 @@
|
||||
#include <Functions/FunctionBinaryArithmetic.h>
|
||||
#include <Functions/GCDLCMImpl.h>
|
||||
|
||||
#include <boost/math/common_factor.hpp>
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
@ -46,7 +49,7 @@ struct LCMImpl : public GCDLCMImpl<A, B, LCMImpl<A, B>, NameLCM>
|
||||
* (example: throw an exception or overflow in implementation specific way).
|
||||
*/
|
||||
|
||||
Unsigned val1 = abs<Int>(a) / std::gcd(Int(a), Int(b));
|
||||
Unsigned val1 = abs<Int>(a) / boost::math::gcd(Int(a), Int(b));
|
||||
Unsigned val2 = abs<Int>(b);
|
||||
|
||||
/// Overflow in implementation specific way.
|
||||
|
Loading…
Reference in New Issue
Block a user