#pragma once #include #include #include #include #include #if !defined(ARCADIA_BUILD) # include "config_core.h" #endif namespace DB { namespace ErrorCodes { extern const int DECIMAL_OVERFLOW; } template struct GCDLCMImpl { using ResultType = typename NumberTraits::ResultOfAdditionMultiplication::Type; static const constexpr bool allow_fixed_string = false; template static inline Result apply(A a, B b) { throwIfDivisionLeadsToFPE(typename NumberTraits::ToInteger::Type(a), typename NumberTraits::ToInteger::Type(b)); throwIfDivisionLeadsToFPE(typename NumberTraits::ToInteger::Type(b), typename NumberTraits::ToInteger::Type(a)); using Int = typename NumberTraits::ToInteger::Type; if constexpr (is_signed_v) { /// gcd() internally uses std::abs() Int a_s = static_cast(a); Int b_s = static_cast(b); Int min = std::numeric_limits::lowest(); Int max = std::numeric_limits::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); } return Impl::applyImpl(a, b); } #if USE_EMBEDDED_COMPILER static constexpr bool compilable = false; /// exceptions (and a non-trivial algorithm) #endif }; }