xref: /netbsd-src/external/gpl3/gcc.old/dist/libstdc++-v3/include/experimental/numeric (revision 23f5f46327e37e7811da3520f4bb933f9489322f)
11debfc3dSmrg// <experimental/numeric> -*- C++ -*-
21debfc3dSmrg
38feb0f0bSmrg// Copyright (C) 2015-2020 Free Software Foundation, Inc.
41debfc3dSmrg//
51debfc3dSmrg// This file is part of the GNU ISO C++ Library.  This library is free
61debfc3dSmrg// software; you can redistribute it and/or modify it under the
71debfc3dSmrg// terms of the GNU General Public License as published by the
81debfc3dSmrg// Free Software Foundation; either version 3, or (at your option)
91debfc3dSmrg// any later version.
101debfc3dSmrg
111debfc3dSmrg// This library is distributed in the hope that it will be useful,
121debfc3dSmrg// but WITHOUT ANY WARRANTY; without even the implied warranty of
131debfc3dSmrg// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
141debfc3dSmrg// GNU General Public License for more details.
151debfc3dSmrg
161debfc3dSmrg// Under Section 7 of GPL version 3, you are granted additional
171debfc3dSmrg// permissions described in the GCC Runtime Library Exception, version
181debfc3dSmrg// 3.1, as published by the Free Software Foundation.
191debfc3dSmrg
201debfc3dSmrg// You should have received a copy of the GNU General Public License and
211debfc3dSmrg// a copy of the GCC Runtime Library Exception along with this program;
221debfc3dSmrg// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
231debfc3dSmrg// <http://www.gnu.org/licenses/>.
241debfc3dSmrg
251debfc3dSmrg/** @file experimental/numeric
261debfc3dSmrg *  This is a TS C++ Library header.
278feb0f0bSmrg *  @ingroup libfund-ts
281debfc3dSmrg */
291debfc3dSmrg
301debfc3dSmrg//
311debfc3dSmrg// N4336 Working Draft, C++ Extensions for Library Fundamentals, Version 2
321debfc3dSmrg//
331debfc3dSmrg
341debfc3dSmrg#ifndef _GLIBCXX_EXPERIMENTAL_NUMERIC
351debfc3dSmrg#define _GLIBCXX_EXPERIMENTAL_NUMERIC 1
361debfc3dSmrg
371debfc3dSmrg#pragma GCC system_header
381debfc3dSmrg
391debfc3dSmrg#if __cplusplus >= 201402L
401debfc3dSmrg
411debfc3dSmrg#include <numeric>
421debfc3dSmrg#include <experimental/type_traits>
431debfc3dSmrg
441debfc3dSmrgnamespace std _GLIBCXX_VISIBILITY(default)
451debfc3dSmrg{
46a2dc1f3fSmrg_GLIBCXX_BEGIN_NAMESPACE_VERSION
47a2dc1f3fSmrg
481debfc3dSmrgnamespace experimental
491debfc3dSmrg{
501debfc3dSmrginline namespace fundamentals_v2
511debfc3dSmrg{
521debfc3dSmrg#define __cpp_lib_experimental_gcd_lcm 201411
531debfc3dSmrg
541debfc3dSmrg  /// Greatest common divisor
551debfc3dSmrg  template<typename _Mn, typename _Nn>
561debfc3dSmrg    constexpr common_type_t<_Mn, _Nn>
578feb0f0bSmrg    gcd(_Mn __m, _Nn __n) noexcept
581debfc3dSmrg    {
59*23f5f463Smrg      static_assert(is_integral_v<_Mn> && is_integral_v<_Nn>,
608feb0f0bSmrg		    "std::experimental::gcd arguments must be integers");
61*23f5f463Smrg      static_assert(_Mn(2) == 2 && _Nn(2) == 2,
628feb0f0bSmrg		    "std::experimental::gcd arguments must not be bool");
63*23f5f463Smrg      namespace __detail = std::__detail;
64*23f5f463Smrg      using _Ct = common_type_t<_Mn, _Nn>;
65*23f5f463Smrg      const _Ct __m2 = __detail::__abs_r<_Ct>(__m);
66*23f5f463Smrg      const _Ct __n2 = __detail::__abs_r<_Ct>(__n);
67*23f5f463Smrg      return __detail::__gcd<make_unsigned_t<_Ct>>(__m2, __n2);
681debfc3dSmrg    }
691debfc3dSmrg
701debfc3dSmrg  /// Least common multiple
711debfc3dSmrg  template<typename _Mn, typename _Nn>
721debfc3dSmrg    constexpr common_type_t<_Mn, _Nn>
731debfc3dSmrg    lcm(_Mn __m, _Nn __n)
741debfc3dSmrg    {
75*23f5f463Smrg      static_assert(is_integral_v<_Mn> && is_integral_v<_Nn>,
768feb0f0bSmrg	  "std::experimental::lcm arguments must be integers");
77*23f5f463Smrg      static_assert(_Mn(2) == 2 && _Nn(2) == 2,
788feb0f0bSmrg	  "std::experimental::lcm arguments must not be bool");
79*23f5f463Smrg      namespace __detail = std::__detail;
80*23f5f463Smrg      using _Ct = common_type_t<_Mn, _Nn>;
81*23f5f463Smrg      const _Ct __m2 = __detail::__abs_r<_Ct>(__m);
82*23f5f463Smrg      const _Ct __n2 = __detail::__abs_r<_Ct>(__n);
83*23f5f463Smrg      if (__m2 == 0 || __n2 == 0)
84*23f5f463Smrg	return 0;
85*23f5f463Smrg      _Ct __r = __m2 / __detail::__gcd<make_unsigned_t<_Ct>>(__m2, __n2);
86*23f5f463Smrg
87*23f5f463Smrg#if defined _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED
88*23f5f463Smrg      if _GLIBCXX17_CONSTEXPR (is_signed_v<_Ct>)
89*23f5f463Smrg	if (__builtin_is_constant_evaluated())
90*23f5f463Smrg	  return __r * __n2; // constant evaluation can detect overflow here.
91*23f5f463Smrg#endif
92*23f5f463Smrg
93*23f5f463Smrg      bool __overflow = __builtin_mul_overflow(__r, __n2, &__r);
94*23f5f463Smrg      __glibcxx_assert(!__overflow);
95*23f5f463Smrg      return __r;
961debfc3dSmrg    }
971debfc3dSmrg} // namespace fundamentals_v2
981debfc3dSmrg} // namespace experimental
99a2dc1f3fSmrg
100a2dc1f3fSmrg_GLIBCXX_END_NAMESPACE_VERSION
1011debfc3dSmrg} // namespace std
1021debfc3dSmrg
1031debfc3dSmrg#endif // __cplusplus <= 201103L
1041debfc3dSmrg
1051debfc3dSmrg#endif // _GLIBCXX_EXPERIMENTAL_NUMERIC
106