Skip to content

Commit

Permalink
Move std::gcm and std::lcm into their own file
Browse files Browse the repository at this point in the history
  • Loading branch information
miscco committed Apr 30, 2024
1 parent 697f955 commit f4b1fcd
Show file tree
Hide file tree
Showing 16 changed files with 655 additions and 69 deletions.
112 changes: 112 additions & 0 deletions libcudacxx/include/cuda/std/__numeric/gcd_lcm.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// Part of libcu++, the C++ Standard Library for your entire system,
// under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES.
//
//===----------------------------------------------------------------------===//

#ifndef _LIBCUDACXX___NUMERIC_GCD_LCM_H
#define _LIBCUDACXX___NUMERIC_GCD_LCM_H

#include <cuda/std/detail/__config>

#if defined(_CCCL_IMPLICIT_SYSTEM_HEADER_GCC)
# pragma GCC system_header
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_CLANG)
# pragma clang system_header
#elif defined(_CCCL_IMPLICIT_SYSTEM_HEADER_MSVC)
# pragma system_header
#endif // no system header

#include <cuda/std/__type_traits/common_type.h>
#include <cuda/std/__type_traits/is_integral.h>
#include <cuda/std/__type_traits/is_same.h>
#include <cuda/std/__type_traits/is_signed.h>
#include <cuda/std/__type_traits/make_unsigned.h>
#include <cuda/std/limits>

// comes last
#include <cuda/std/detail/__pragma_push>

_LIBCUDACXX_BEGIN_NAMESPACE_STD

template <typename _Result, typename _Source, bool _IsSigned = _LIBCUDACXX_TRAIT(is_signed, _Source)>
struct __ct_abs;

template <typename _Result, typename _Source>
struct __ct_abs<_Result, _Source, true>
{
_CCCL_CONSTEXPR_CXX14 _LIBCUDACXX_INLINE_VISIBILITY _Result operator()(_Source __t) const noexcept
{
if (__t >= 0)
{
return __t;
}
_CCCL_DIAG_PUSH
_CCCL_DIAG_SUPPRESS_MSVC(4146) // unary minus operator applied to unsigned type, result still unsigned
if (__t == (numeric_limits<_Source>::min)())
{
return -static_cast<_Result>(__t);
}
_CCCL_DIAG_POP
return -__t;
}
};

template <typename _Result, typename _Source>
struct __ct_abs<_Result, _Source, false>
{
_CCCL_CONSTEXPR_CXX14 _LIBCUDACXX_INLINE_VISIBILITY _Result operator()(_Source __t) const noexcept
{
return __t;
}
};

template <class _Tp>
_CCCL_CONSTEXPR_CXX14 _LIBCUDACXX_INLINE_VISIBILITY _Tp __gcd(_Tp __m, _Tp __n)
{
static_assert((!_LIBCUDACXX_TRAIT(is_signed, _Tp)), "");
return __n == 0 ? __m : _CUDA_VSTD::__gcd<_Tp>(__n, __m % __n);
}

template <class _Tp, class _Up>
_CCCL_CONSTEXPR_CXX14 _LIBCUDACXX_INLINE_VISIBILITY __common_type_t<_Tp, _Up> gcd(_Tp __m, _Up __n)
{
static_assert((_LIBCUDACXX_TRAIT(is_integral, _Tp) && _LIBCUDACXX_TRAIT(is_integral, _Up)),
"Arguments to gcd must be integer types");
static_assert((!_LIBCUDACXX_TRAIT(is_same, __remove_cv_t<_Tp>, bool)), "First argument to gcd cannot be bool");
static_assert((!_LIBCUDACXX_TRAIT(is_same, __remove_cv_t<_Up>, bool)), "Second argument to gcd cannot be bool");
using _Rp = __common_type_t<_Tp, _Up>;
using _Wp = __make_unsigned_t<_Rp>;
return static_cast<_Rp>(
_CUDA_VSTD::__gcd(static_cast<_Wp>(__ct_abs<_Rp, _Tp>()(__m)), static_cast<_Wp>(__ct_abs<_Rp, _Up>()(__n))));
}

template <class _Tp, class _Up>
_CCCL_CONSTEXPR_CXX14 _LIBCUDACXX_INLINE_VISIBILITY __common_type_t<_Tp, _Up> lcm(_Tp __m, _Up __n)
{
static_assert((_LIBCUDACXX_TRAIT(is_integral, _Tp) && _LIBCUDACXX_TRAIT(is_integral, _Up)),
"Arguments to lcm must be integer types");
static_assert((!_LIBCUDACXX_TRAIT(is_same, __remove_cv_t<_Tp>, bool)), "First argument to lcm cannot be bool");
static_assert((!_LIBCUDACXX_TRAIT(is_same, __remove_cv_t<_Up>, bool)), "Second argument to lcm cannot be bool");
if (__m == 0 || __n == 0)
{
return 0;
}

using _Rp = __common_type_t<_Tp, _Up>;
_Rp __val1 = __ct_abs<_Rp, _Tp>()(__m) / _CUDA_VSTD::gcd(__m, __n);
_Rp __val2 = __ct_abs<_Rp, _Up>()(__n);
_LIBCUDACXX_ASSERT((numeric_limits<_Rp>::max() / __val1 > __val2), "Overflow in lcm");
return __val1 * __val2;
}

_LIBCUDACXX_END_NAMESPACE_STD

#include <cuda/std/detail/__pragma_pop>

#endif // _LIBCUDACXX___NUMERIC_GCD_LCM_H
70 changes: 1 addition & 69 deletions libcudacxx/include/cuda/std/detail/libcxx/include/numeric
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ floating_point midpoint(floating_point a, floating_point b); // C++20
#include <cuda/std/__numeric/accumulate.h>
#include <cuda/std/__numeric/adjacent_difference.h>
#include <cuda/std/__numeric/exclusive_scan.h>
#include <cuda/std/__numeric/gcd_lcm.h>
#include <cuda/std/__numeric/inclusive_scan.h>
#include <cuda/std/__numeric/inner_product.h>
#include <cuda/std/__numeric/iota.h>
Expand All @@ -178,75 +179,6 @@ floating_point midpoint(floating_point a, floating_point b); // C++20
_LIBCUDACXX_BEGIN_NAMESPACE_STD

#ifndef __cuda_std__
# if _CCCL_STD_VER > 2014
template <typename _Result, typename _Source, bool _IsSigned = is_signed<_Source>::value>
struct __ct_abs;

template <typename _Result, typename _Source>
struct __ct_abs<_Result, _Source, true>
{
constexpr _LIBCUDACXX_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 <typename _Result, typename _Source>
struct __ct_abs<_Result, _Source, false>
{
constexpr _LIBCUDACXX_INLINE_VISIBILITY _Result operator()(_Source __t) const noexcept
{
return __t;
}
};

template <class _Tp>
constexpr _LIBCUDACXX_HIDDEN _Tp __gcd(_Tp __m, _Tp __n)
{
static_assert((!is_signed<_Tp>::value), "");
return __n == 0 ? __m : _CUDA_VSTD::__gcd<_Tp>(__n, __m % __n);
}

template <class _Tp, class _Up>
constexpr _LIBCUDACXX_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<__remove_cv_t<_Tp>, bool>::value), "First argument to gcd cannot be bool");
static_assert((!is_same<__remove_cv_t<_Up>, 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>(
_CUDA_VSTD::__gcd(static_cast<_Wp>(__ct_abs<_Rp, _Tp>()(__m)), static_cast<_Wp>(__ct_abs<_Rp, _Up>()(__n))));
}

template <class _Tp, class _Up>
constexpr _LIBCUDACXX_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<__remove_cv_t<_Tp>, bool>::value), "First argument to lcm cannot be bool");
static_assert((!is_same<__remove_cv_t<_Up>, 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 = __ct_abs<_Rp, _Tp>()(__m) / _CUDA_VSTD::gcd(__m, __n);
_Rp __val2 = __ct_abs<_Rp, _Up>()(__n);
_LIBCUDACXX_ASSERT((numeric_limits<_Rp>::max() / __val1 > __val2), "Overflow in lcm");
return __val1 * __val2;
}

# endif /* _CCCL_STD_VER > 2014 */

# if _CCCL_STD_VER > 2017
template <class _Tp>
_LIBCUDACXX_INLINE_VISIBILITY constexpr enable_if_t<
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// <numeric>

// template<class _M, class _N>
// constexpr common_type_t<_M,_N> gcd(_M __m, _N __n)

// Remarks: If either M or N is not an integer type,
// or if either is (a possibly cv-qualified) bool, the program is ill-formed.

#include <cuda/std/__numeric_>

int main(int, char**)
{
cuda::std::gcd(false, 4);

return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// <numeric>

// template<class _M, class _N>
// constexpr common_type_t<_M,_N> gcd(_M __m, _N __n)

// Remarks: If either M or N is not an integer type,
// or if either is (a possibly cv-qualified) bool, the program is ill-formed.

#include <cuda/std/__numeric_>

int main(int, char**)
{
cuda::std::gcd(2, true);

return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// <numeric>

// template<class _M, class _N>
// constexpr common_type_t<_M,_N> gcd(_M __m, _N __n)

// Remarks: If either M or N is not an integer type,
// or if either is (a possibly cv-qualified) bool, the program is ill-formed.

#include <cuda/std/__numeric_>

int main(int, char**)
{
cuda::std::gcd<volatile bool, int>(false, 4);

return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// <numeric>

// template<class _M, class _N>
// constexpr common_type_t<_M,_N> gcd(_M __m, _N __n)

// Remarks: If either M or N is not an integer type,
// or if either is (a possibly cv-qualified) bool, the program is ill-formed.

#include <cuda/std/__numeric_>

int main(int, char**)
{
cuda::std::gcd<int, const bool>(2, true);

return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// <numeric>

// template<class _M, class _N>
// constexpr common_type_t<_M,_N> gcd(_M __m, _N __n)

// Remarks: If either M or N is not an integer type,
// or if either is (a possibly cv-qualified) bool, the program is ill-formed.

#include <cuda/std/__numeric_>

int main(int, char**)
{
cuda::std::gcd(2.0, 4);

return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// <numeric>

// template<class _M, class _N>
// constexpr common_type_t<_M,_N> gcd(_M __m, _N __n)

// Remarks: If either M or N is not an integer type,
// or if either is (a possibly cv-qualified) bool, the program is ill-formed.

#include <cuda/std/__numeric_>

int main(int, char**)
{
cuda::std::gcd(4, 6.0);

return 0;
}
Loading

0 comments on commit f4b1fcd

Please sign in to comment.