// -*- C++ -*- //===--------------------------- numeric ----------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef _LIBCPP_EXPERIMENTAL_NUMERIC #define _LIBCPP_EXPERIMENTAL_NUMERIC /* experimental/numeric synopsis // C++1z namespace std { namespace experimental { inline namespace fundamentals_v2 { // 13.1.2, Greatest common divisor template constexpr common_type_t gcd(M m, N n); // 13.1.3, Least common multiple template constexpr common_type_t lcm(M m, N n); } // namespace fundamentals_v2 } // namespace experimental } // namespace std */ #include #include #include // is_integral #include // numeric_limits #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) #pragma GCC system_header #endif _LIBCPP_PUSH_MACROS #include <__undef_macros> #if _LIBCPP_STD_VER > 11 _LIBCPP_BEGIN_NAMESPACE_LFTS_V2 template ::value> struct __abs; template struct __abs<_Result, _Source, true> { _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY _Result operator()(_Source __t) const noexcept { if (__t >= 0) return __t; if (__t == numeric_limits<_Source>::min()) return -static_cast<_Result>(__t); return -__t; } }; template struct __abs<_Result, _Source, false> { _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY _Result operator()(_Source __t) const noexcept { return __t; } }; template _LIBCPP_CONSTEXPR _LIBCPP_HIDDEN inline _Tp __gcd(_Tp __m, _Tp __n) { static_assert((!is_signed<_Tp>::value), "" ); return __n == 0 ? __m : _VSTD_LFTS_V2::__gcd<_Tp>(__n, __m % __n); } template _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY common_type_t<_Tp,_Up> gcd(_Tp __m, _Up __n) { static_assert((is_integral<_Tp>::value && is_integral<_Up>::value), "Arguments to gcd must be integer types"); static_assert((!is_same::type, bool>::value), "First argument to gcd cannot be bool" ); static_assert((!is_same::type, bool>::value), "Second argument to gcd cannot be bool" ); using _Rp = common_type_t<_Tp,_Up>; using _Wp = make_unsigned_t<_Rp>; return static_cast<_Rp>(_VSTD_LFTS_V2::__gcd( static_cast<_Wp>(__abs<_Rp, _Tp>()(__m)), static_cast<_Wp>(__abs<_Rp, _Up>()(__n)))); } template _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY common_type_t<_Tp,_Up> lcm(_Tp __m, _Up __n) { static_assert((is_integral<_Tp>::value && is_integral<_Up>::value), "Arguments to lcm must be integer types"); static_assert((!is_same::type, bool>::value), "First argument to lcm cannot be bool" ); static_assert((!is_same::type, bool>::value), "Second argument to lcm cannot be bool" ); if (__m == 0 || __n == 0) return 0; using _Rp = common_type_t<_Tp,_Up>; _Rp __val1 = __abs<_Rp, _Tp>()(__m) / _VSTD_LFTS_V2::gcd(__m, __n); _Rp __val2 = __abs<_Rp, _Up>()(__n); _LIBCPP_ASSERT((numeric_limits<_Rp>::max() / __val1 > __val2), "Overflow in lcm"); return __val1 * __val2; } _LIBCPP_END_NAMESPACE_LFTS_V2 #endif /* _LIBCPP_STD_VER > 11 */ _LIBCPP_POP_MACROS #endif /* _LIBCPP_EXPERIMENTAL_NUMERIC */