// -*- 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 #if _LIBCPP_STD_VER > 11 _LIBCPP_BEGIN_NAMESPACE_LFTS_V2 template ::value> struct __abs; template struct __abs<_Tp, true> { _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY _Tp operator()(_Tp __t) const noexcept { return __t >= 0 ? __t : -__t; } }; template struct __abs<_Tp, false> { _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY _Tp operator()(_Tp __t) const noexcept { return __t; } }; template _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY _Tp __gcd(_Tp __m, _Tp __n) { static_assert((!is_signed<_Tp>::value), "" ); return __n == 0 ? __m : __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"); using _Rp = common_type_t<_Tp,_Up>; using _Wp = make_unsigned_t<_Rp>; return static_cast<_Rp>(__gcd(static_cast<_Wp>(__abs<_Tp>()(__m)), static_cast<_Wp>(__abs<_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"); if (__m == 0 || __n == 0) return 0; using _Rp = common_type_t<_Tp,_Up>; _Rp __val1 = __abs<_Tp>()(__m) / gcd(__m,__n); _Up __val2 = __abs<_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 */ #endif /* _LIBCPP_EXPERIMENTAL_NUMERIC */