mclow.lists updated this revision to Diff 60856.
mclow.lists added a comment.
Updated based on comments here and elsewhere.
- Do the abs once, rather than at every level of recursion
- Add tests for `bool`.
- Constexpr
Also, add an assertion to detect overflow in `lcm`.
I have not yet incorporated Eric's constexpr tests.
http://reviews.llvm.org/D21343
Files:
include/experimental/numeric
test/std/experimental/numeric/numeric.ops.overview/nothing_to_do.pass.cpp
test/std/experimental/numeric/numeric.ops/nothing_to_do.pass.cpp
test/std/experimental/numeric/numeric.ops/numeric.ops.gcd/gcd.not_integral1.fail.cpp
test/std/experimental/numeric/numeric.ops/numeric.ops.gcd/gcd.not_integral2.fail.cpp
test/std/experimental/numeric/numeric.ops/numeric.ops.gcd/gcd.pass.cpp
test/std/experimental/numeric/numeric.ops/numeric.ops.lcm/lcm.not_integral1.fail.cpp
test/std/experimental/numeric/numeric.ops/numeric.ops.lcm/lcm.not_integral2.fail.cpp
test/std/experimental/numeric/numeric.ops/numeric.ops.lcm/lcm.pass.cpp
Index: test/std/experimental/numeric/numeric.ops.overview/nothing_to_do.pass.cpp
===================================================================
--- test/std/experimental/numeric/numeric.ops.overview/nothing_to_do.pass.cpp
+++ test/std/experimental/numeric/numeric.ops.overview/nothing_to_do.pass.cpp
@@ -0,0 +1,15 @@
+//===----------------------------------------------------------------------===//
+//
+// 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.
+//
+//===----------------------------------------------------------------------===//
+//
+// UNSUPPORTED: c++98, c++03, c++11
+// <numeric>
+
+#include <experimental/numeric>
+
+int main () {}
Index: test/std/experimental/numeric/numeric.ops/numeric.ops.lcm/lcm.pass.cpp
===================================================================
--- test/std/experimental/numeric/numeric.ops/numeric.ops.lcm/lcm.pass.cpp
+++ test/std/experimental/numeric/numeric.ops/numeric.ops.lcm/lcm.pass.cpp
@@ -0,0 +1,260 @@
+//===----------------------------------------------------------------------===//
+//
+// 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.
+//
+//===----------------------------------------------------------------------===//
+//
+// UNSUPPORTED: c++98, c++03, c++11
+// <numeric>
+
+// template<class _M, class _N>
+// constexpr common_type_t<_M,_N> gcd(_M __m, _N __n)
+
+#include <experimental/numeric>
+#include <cassert>
+#include <iostream>
+
+template <typename Input1, typename Input2, typename Output>
+void test0(Input1 in1, Input2 in2, Output out)
+{
+ static_assert((std::is_same<Output, decltype(std::experimental::lcm(Input1(0), Input2(0)))>::value), "" );
+ static_assert((std::is_same<Output, decltype(std::experimental::lcm(Input2(0), Input1(0)))>::value), "" );
+ assert(out == std::experimental::lcm(in1, in2));
+ assert(out == std::experimental::lcm(in2, in1));
+}
+
+
+template <typename Input>
+void test_same_signed()
+{
+ static_assert(( std::is_signed<Input>::value), "" );
+
+// Returns: zero when either m or n is zero.
+ test0<Input, Input, Input>( 0, 0, 0);
+ test0<Input, Input, Input>( 1, 0, 0);
+ test0<Input, Input, Input>( 0, 1, 0);
+ test0<Input, Input, Input>(-1, 0, 0);
+ test0<Input, Input, Input>( 0, -1, 0);
+
+// Otherwise, returns the least common multiple of |m| and |n|.
+ test0<Input, Input, Input>( 1, 1, 1);
+ test0<Input, Input, Input>( 2, 3, 6);
+ test0<Input, Input, Input>( 2, 4, 4);
+ test0<Input, Input, Input>( 3, 17, 51);
+ test0<Input, Input, Input>( 36, 18, 36);
+
+ test0<Input, Input, Input>( -1, 1, 1);
+ test0<Input, Input, Input>( -2, 3, 6);
+ test0<Input, Input, Input>( -2, 4, 4);
+ test0<Input, Input, Input>( -3, 17, 51);
+ test0<Input, Input, Input>(-36, 18, 36);
+
+ test0<Input, Input, Input>( 1, -1, 1);
+ test0<Input, Input, Input>( 2, -3, 6);
+ test0<Input, Input, Input>( 2, -4, 4);
+ test0<Input, Input, Input>( 3, -17, 51);
+ test0<Input, Input, Input>( 36, -18, 36);
+
+ test0<Input, Input, Input>( -1, -1, 1);
+ test0<Input, Input, Input>( -2, -3, 6);
+ test0<Input, Input, Input>( -2, -4, 4);
+ test0<Input, Input, Input>( -3, -17, 51);
+ test0<Input, Input, Input>(-36, -18, 36);
+}
+
+template <typename Input>
+void test_same_unsigned()
+{
+ static_assert((!std::is_signed<Input>::value), "" );
+
+// Returns: zero when either m or n is zero.
+ test0<Input, Input, Input>( 0, 0, 0);
+ test0<Input, Input, Input>( 1, 0, 0);
+ test0<Input, Input, Input>( 0, 1, 0);
+
+// Otherwise, returns the least common multiple of |m| and |n|.
+ test0<Input, Input, Input>( 1, 1, 1);
+ test0<Input, Input, Input>( 2, 3, 6);
+ test0<Input, Input, Input>( 2, 4, 4);
+ test0<Input, Input, Input>( 3, 17, 51);
+ test0<Input, Input, Input>( 36, 18, 36);
+}
+
+
+template <typename Input1, typename Input2, typename Output>
+void test_different_signed()
+{
+ static_assert(( std::is_signed<Input1>::value), "" );
+ static_assert(( std::is_signed<Input2>::value), "" );
+
+// Returns: zero when either m or n is zero.
+ test0<Input1, Input2, Output>( 0, 0, 0);
+ test0<Input1, Input2, Output>( 1, 0, 0);
+ test0<Input1, Input2, Output>( 0, 1, 0);
+ test0<Input1, Input2, Output>(-1, 0, 0);
+ test0<Input1, Input2, Output>( 0, -1, 0);
+
+// Otherwise, returns the least common multiple of |m| and |n|.
+ test0<Input1, Input2, Output>( 1, 1, 1);
+ test0<Input1, Input2, Output>( 2, 3, 6);
+ test0<Input1, Input2, Output>( 2, 4, 4);
+ test0<Input1, Input2, Output>( 3, 17, 51);
+ test0<Input1, Input2, Output>( 36, 18, 36);
+
+ test0<Input1, Input2, Output>( -1, 1, 1);
+ test0<Input1, Input2, Output>( -2, 3, 6);
+ test0<Input1, Input2, Output>( -2, 4, 4);
+ test0<Input1, Input2, Output>( -3, 17, 51);
+ test0<Input1, Input2, Output>(-36, 18, 36);
+
+ test0<Input1, Input2, Output>( 1, -1, 1);
+ test0<Input1, Input2, Output>( 2, -3, 6);
+ test0<Input1, Input2, Output>( 2, -4, 4);
+ test0<Input1, Input2, Output>( 3, -17, 51);
+ test0<Input1, Input2, Output>( 36, -18, 36);
+
+ test0<Input1, Input2, Output>( -1, -1, 1);
+ test0<Input1, Input2, Output>( -2, -3, 6);
+ test0<Input1, Input2, Output>( -2, -4, 4);
+ test0<Input1, Input2, Output>( -3, -17, 51);
+ test0<Input1, Input2, Output>(-36, -18, 36);
+}
+
+template <typename Input1, typename Input2, typename Output>
+void test_different_unsigned()
+{
+ static_assert((!std::is_signed<Input1>::value), "" );
+ static_assert((!std::is_signed<Input2>::value), "" );
+
+// Returns: zero when either m or n is zero.
+ test0<Input1, Input2, Output>( 0, 0, 0);
+ test0<Input1, Input2, Output>( 1, 0, 0);
+ test0<Input1, Input2, Output>( 0, 1, 0);
+
+// Otherwise, returns the least common multiple of |m| and |n|.
+ test0<Input1, Input2, Output>( 1, 1, 1);
+ test0<Input1, Input2, Output>( 2, 3, 6);
+ test0<Input1, Input2, Output>( 2, 4, 4);
+ test0<Input1, Input2, Output>( 3, 17, 51);
+ test0<Input1, Input2, Output>( 36, 18, 36);
+}
+
+template <typename Input1, typename Input2, typename Output>
+void test_mixed_first_signed()
+{
+ static_assert(( std::is_signed<Input1>::value), "" );
+ static_assert((!std::is_signed<Input2>::value), "" );
+
+// Returns: zero when either m or n is zero.
+ test0<Input1, Input2, Output>( 0, 0, 0);
+ test0<Input1, Input2, Output>( 1, 0, 0);
+ test0<Input1, Input2, Output>(-1, 0, 0);
+ test0<Input1, Input2, Output>( 0, 1, 0);
+
+// Otherwise, returns the least common multiple of |m| and |n|.
+ test0<Input1, Input2, Output>( 1, 1, 1);
+ test0<Input1, Input2, Output>( 2, 3, 6);
+ test0<Input1, Input2, Output>( 2, 4, 4);
+ test0<Input1, Input2, Output>( 3, 17, 51);
+ test0<Input1, Input2, Output>( 36, 18, 36);
+
+ test0<Input1, Input2, Output>( -1, 1, 1);
+ test0<Input1, Input2, Output>( -2, 3, 6);
+ test0<Input1, Input2, Output>( -2, 4, 4);
+ test0<Input1, Input2, Output>( -3, 17, 51);
+ test0<Input1, Input2, Output>(-36, 18, 36);
+}
+
+template <typename Input1, typename Input2, typename Output>
+void test_mixed_second_signed()
+{
+ static_assert((!std::is_signed<Input1>::value), "" );
+ static_assert(( std::is_signed<Input2>::value), "" );
+
+// Returns: zero when either m or n is zero.
+ test0<Input1, Input2, Output>( 0, 0, 0);
+ test0<Input1, Input2, Output>( 1, 0, 0);
+ test0<Input1, Input2, Output>( 0, 1, 0);
+ test0<Input1, Input2, Output>( 0, -1, 0);
+
+// Otherwise, returns the least common multiple of |m| and |n|.
+ test0<Input1, Input2, Output>( 1, 1, 1);
+ test0<Input1, Input2, Output>( 2, 3, 6);
+ test0<Input1, Input2, Output>( 2, 4, 4);
+ test0<Input1, Input2, Output>( 3, 17, 51);
+ test0<Input1, Input2, Output>( 36, 18, 36);
+
+// Otherwise, returns the least common multiple of |m| and |n|.
+ test0<Input1, Input2, Output>( 1, -1, 1);
+ test0<Input1, Input2, Output>( 2, -3, 6);
+ test0<Input1, Input2, Output>( 2, -4, 4);
+ test0<Input1, Input2, Output>( 3, -17, 51);
+ test0<Input1, Input2, Output>( 36, -18, 36);
+}
+
+int main()
+{
+ test_same_signed<signed char>();
+ test_same_signed<short>();
+ test_same_signed<int>();
+ test_same_signed<long>();
+ test_same_signed<long long>();
+
+ test_same_signed< int8_t>();
+ test_same_signed<int16_t>();
+ test_same_signed<int32_t>();
+ test_same_signed<int64_t>();
+
+ test_same_unsigned<unsigned char>();
+ test_same_unsigned<unsigned short>();
+ test_same_unsigned<unsigned int>();
+ test_same_unsigned<unsigned long>();
+ test_same_unsigned<unsigned long long>();
+ test_same_unsigned<std::size_t>();
+
+ test_same_unsigned< uint8_t>();
+ test_same_unsigned<uint16_t>();
+ test_same_unsigned<uint32_t>();
+ test_same_unsigned<uint64_t>();
+
+ test_different_signed<signed char, int, int>();
+ test_different_signed<int, signed char, int>();
+ test_different_signed<short, int, int>();
+ test_different_signed<int, short, int>();
+ test_different_signed<int, long, long>();
+ test_different_signed<long, int, long>();
+ test_different_signed<int, long long, long long>();
+ test_different_signed<long long, int, long long>();
+
+ test_different_unsigned<unsigned char, unsigned int, unsigned int>();
+ test_different_unsigned<unsigned int, unsigned char, unsigned int>();
+ test_different_unsigned<unsigned short, unsigned int, unsigned int>();
+ test_different_unsigned<unsigned int, unsigned short, unsigned int>();
+ test_different_unsigned<unsigned int, unsigned long, unsigned long>();
+ test_different_unsigned<unsigned long, unsigned int, unsigned long>();
+ test_different_unsigned<unsigned int, unsigned long long, unsigned long long>();
+ test_different_unsigned<unsigned long long, unsigned int, unsigned long long>();
+
+ test_mixed_first_signed<signed char, unsigned char, int>();
+ test_mixed_first_signed<int, unsigned char, int>();
+ test_mixed_first_signed<int, unsigned int, unsigned int>();
+ test_mixed_first_signed<long, unsigned int, long>();
+ test_mixed_first_signed<long long, unsigned int, long long>();
+ test_mixed_first_signed<long long, unsigned long, unsigned long long>();
+
+ test_mixed_second_signed<unsigned char, signed char, int>();
+ test_mixed_second_signed<unsigned char, int, int>();
+ test_mixed_second_signed<unsigned int, int, unsigned int>();
+ test_mixed_second_signed<unsigned int, long, long>();
+ test_mixed_second_signed<unsigned int, long long, long long>();
+ test_mixed_second_signed<unsigned long, long long, unsigned long long>();
+
+// Weirdness with bool
+ test0<bool, signed char, int>(false, 'A', 0);
+ test0<bool, signed char, int>(true, 'B', 'B');
+ test0<bool, int, int>(false, 3, 0);
+ test0<bool, int, int>(true, 3, 3);
+}
Index: test/std/experimental/numeric/numeric.ops/numeric.ops.lcm/lcm.not_integral2.fail.cpp
===================================================================
--- test/std/experimental/numeric/numeric.ops/numeric.ops.lcm/lcm.not_integral2.fail.cpp
+++ test/std/experimental/numeric/numeric.ops/numeric.ops.lcm/lcm.not_integral2.fail.cpp
@@ -0,0 +1,24 @@
+//===----------------------------------------------------------------------===//
+//
+// 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.
+//
+//===----------------------------------------------------------------------===//
+//
+// UNSUPPORTED: c++98, c++03, c++11
+// <numeric>
+
+// template<class _M, class _N>
+// constexpr common_type_t<_M,_N> lcm(_M __m, _N __n)
+
+// Remarks: If either M or N is not an integer type, the program is ill-formed.
+
+#include <experimental/numeric>
+
+
+int main()
+{
+ std::experimental::lcm(4, 6.0);
+}
Index: test/std/experimental/numeric/numeric.ops/numeric.ops.lcm/lcm.not_integral1.fail.cpp
===================================================================
--- test/std/experimental/numeric/numeric.ops/numeric.ops.lcm/lcm.not_integral1.fail.cpp
+++ test/std/experimental/numeric/numeric.ops/numeric.ops.lcm/lcm.not_integral1.fail.cpp
@@ -0,0 +1,24 @@
+//===----------------------------------------------------------------------===//
+//
+// 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.
+//
+//===----------------------------------------------------------------------===//
+//
+// UNSUPPORTED: c++98, c++03, c++11
+// <numeric>
+
+// template<class _M, class _N>
+// constexpr common_type_t<_M,_N> lcm(_M __m, _N __n)
+
+// Remarks: If either M or N is not an integer type, the program is ill-formed.
+
+#include <experimental/numeric>
+
+
+int main()
+{
+ std::experimental::lcm(2.0, 4);
+}
Index: test/std/experimental/numeric/numeric.ops/numeric.ops.gcd/gcd.pass.cpp
===================================================================
--- test/std/experimental/numeric/numeric.ops/numeric.ops.gcd/gcd.pass.cpp
+++ test/std/experimental/numeric/numeric.ops/numeric.ops.gcd/gcd.pass.cpp
@@ -0,0 +1,261 @@
+//===----------------------------------------------------------------------===//
+//
+// 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.
+//
+//===----------------------------------------------------------------------===//
+//
+// UNSUPPORTED: c++98, c++03, c++11
+// <numeric>
+
+// template<class _M, class _N>
+// constexpr common_type_t<_M,_N> gcd(_M __m, _N __n)
+
+#include <experimental/numeric>
+#include <cassert>
+#include <iostream>
+
+template <typename Input1, typename Input2, typename Output>
+constexpr void test0(const Input1 &in1, const Input2 &in2, const Output &out)
+{
+ static_assert((std::is_same<Output, decltype(std::experimental::gcd(in1, in2))>::value), "" );
+ static_assert((std::is_same<Output, decltype(std::experimental::gcd(in2, in1))>::value), "" );
+ assert(out == std::experimental::gcd(in1, in2));
+ assert(out == std::experimental::gcd(in2, in1));
+// static_assert((0 <= std::experimental::gcd(in1, in2)), "");
+// static_assert((0 <= std::experimental::gcd(in2, in1)), "");
+}
+
+
+template <typename Input>
+constexpr void test_same_signed()
+{
+ static_assert(( std::is_signed<Input>::value), "" );
+
+// Returns: zero when m and n are both zero.
+ test0<Input, Input, Input>( 0, 0, 0);
+ test0<Input, Input, Input>( 1, 0, 1);
+ test0<Input, Input, Input>( 0, 1, 1);
+ test0<Input, Input, Input>(-1, 0, 1);
+ test0<Input, Input, Input>( 0, -1, 1);
+
+// Otherwise, returns the greatest common divisor of |m| and |n|.
+ test0<Input, Input, Input>( 1, 1, 1);
+ test0<Input, Input, Input>( 2, 3, 1); // relatively prime
+ test0<Input, Input, Input>( 2, 4, 2);
+ test0<Input, Input, Input>( 36, 17, 1); // relatively prime
+ test0<Input, Input, Input>( 36, 18, 18);
+
+ test0<Input, Input, Input>( -1, 1, 1);
+ test0<Input, Input, Input>( -2, 3, 1);
+ test0<Input, Input, Input>( -2, 4, 2);
+ test0<Input, Input, Input>(-36, 17, 1);
+ test0<Input, Input, Input>(-36, 18, 18);
+
+ test0<Input, Input, Input>( 1, -1, 1);
+ test0<Input, Input, Input>( 2, -3, 1);
+ test0<Input, Input, Input>( 2, -4, 2);
+ test0<Input, Input, Input>( 36, -17, 1);
+ test0<Input, Input, Input>( 36, -18, 18);
+
+ test0<Input, Input, Input>( -1, -1, 1);
+ test0<Input, Input, Input>( -2, -3, 1);
+ test0<Input, Input, Input>( -2, -4, 2);
+ test0<Input, Input, Input>(-36, -17, 1);
+ test0<Input, Input, Input>(-36, -18, 18);
+}
+
+template <typename Input>
+constexpr void test_same_unsigned()
+{
+ static_assert((!std::is_signed<Input>::value), "" );
+
+// Returns: zero when m and n are both zero.
+ test0<Input, Input, Input>( 0, 0, 0);
+ test0<Input, Input, Input>( 1, 0, 1);
+ test0<Input, Input, Input>( 0, 1, 1);
+
+// Otherwise, returns the greatest common divisor of |m| and |n|.
+ test0<Input, Input, Input>( 1, 1, 1);
+ test0<Input, Input, Input>( 2, 3, 1); // relatively prime
+ test0<Input, Input, Input>( 2, 4, 2);
+ test0<Input, Input, Input>( 36, 17, 1); // relatively prime
+ test0<Input, Input, Input>( 36, 18, 18);
+}
+
+
+template <typename Input1, typename Input2, typename Output>
+constexpr void test_different_signed()
+{
+ static_assert(( std::is_signed<Input1>::value), "" );
+ static_assert(( std::is_signed<Input2>::value), "" );
+
+// Returns: zero when m and n are both zero.
+ test0<Input1, Input2, Output>( 0, 0, 0);
+ test0<Input1, Input2, Output>( 1, 0, 1);
+ test0<Input1, Input2, Output>( 0, 1, 1);
+ test0<Input1, Input2, Output>(-1, 0, 1);
+ test0<Input1, Input2, Output>( 0, -1, 1);
+
+// Otherwise, returns the greatest common divisor of |m| and |n|.
+ test0<Input1, Input2, Output>( 1, 1, 1);
+ test0<Input1, Input2, Output>( 2, 3, 1); // relatively prime
+ test0<Input1, Input2, Output>( 2, 4, 2);
+ test0<Input1, Input2, Output>( 36, 17, 1); // relatively prime
+ test0<Input1, Input2, Output>( 36, 18, 18);
+
+ test0<Input1, Input2, Output>( -1, 1, 1);
+ test0<Input1, Input2, Output>( -2, 3, 1);
+ test0<Input1, Input2, Output>( -2, 4, 2);
+ test0<Input1, Input2, Output>(-36, 17, 1);
+ test0<Input1, Input2, Output>(-36, 18, 18);
+
+ test0<Input1, Input2, Output>( 1, -1, 1);
+ test0<Input1, Input2, Output>( 2, -3, 1);
+ test0<Input1, Input2, Output>( 2, -4, 2);
+ test0<Input1, Input2, Output>( 36, -17, 1);
+ test0<Input1, Input2, Output>( 36, -18, 18);
+
+ test0<Input1, Input2, Output>( -1, -1, 1);
+ test0<Input1, Input2, Output>( -2, -3, 1);
+ test0<Input1, Input2, Output>( -2, -4, 2);
+ test0<Input1, Input2, Output>(-36, -17, 1);
+ test0<Input1, Input2, Output>(-36, -18, 18);
+}
+
+template <typename Input1, typename Input2, typename Output>
+constexpr void test_different_unsigned()
+{
+ static_assert((!std::is_signed<Input1>::value), "" );
+ static_assert((!std::is_signed<Input2>::value), "" );
+
+// Returns: zero when m and n are both zero.
+ test0<Input1, Input2, Output>( 0, 0, 0);
+ test0<Input1, Input2, Output>( 1, 0, 1);
+ test0<Input1, Input2, Output>( 0, 1, 1);
+
+// Otherwise, returns the greatest common divisor of |m| and |n|.
+ test0<Input1, Input2, Output>( 1, 1, 1);
+ test0<Input1, Input2, Output>( 2, 3, 1); // relatively prime
+ test0<Input1, Input2, Output>( 2, 4, 2);
+ test0<Input1, Input2, Output>( 36, 17, 1); // relatively prime
+ test0<Input1, Input2, Output>( 36, 18, 18);
+}
+
+template <typename Input1, typename Input2, typename Output>
+constexpr void test_mixed_first_signed()
+{
+ static_assert(( std::is_signed<Input1>::value), "" );
+ static_assert((!std::is_signed<Input2>::value), "" );
+
+// Returns: zero when m and n are both zero.
+ test0<Input1, Input2, Output>( 0, 0, 0);
+ test0<Input1, Input2, Output>( 1, 0, 1);
+ test0<Input1, Input2, Output>( 0, 1, 1);
+
+// Otherwise, returns the greatest common divisor of |m| and |n|.
+ test0<Input1, Input2, Output>( 1, 1, 1);
+ test0<Input1, Input2, Output>( 2, 3, 1); // relatively prime
+ test0<Input1, Input2, Output>( 2, 4, 2);
+ test0<Input1, Input2, Output>( 36, 17, 1); // relatively prime
+ test0<Input1, Input2, Output>( 36, 18, 18);
+
+// Otherwise, returns the greatest common divisor of |m| and |n|.
+ test0<Input1, Input2, Output>( -1, 1, 1);
+ test0<Input1, Input2, Output>( -2, 3, 1); // relatively prime
+ test0<Input1, Input2, Output>( -2, 4, 2);
+ test0<Input1, Input2, Output>(-36, 17, 1); // relatively prime
+ test0<Input1, Input2, Output>(-36, 18, 18);
+}
+
+template <typename Input1, typename Input2, typename Output>
+constexpr void test_mixed_second_signed()
+{
+ static_assert((!std::is_signed<Input1>::value), "" );
+ static_assert(( std::is_signed<Input2>::value), "" );
+
+// Returns: zero when m and n are both zero.
+ test0<Input1, Input2, Output>( 0, 0, 0);
+ test0<Input1, Input2, Output>( 1, 0, 1);
+ test0<Input1, Input2, Output>( 0, 1, 1);
+
+// Otherwise, returns the greatest common divisor of |m| and |n|.
+ test0<Input1, Input2, Output>( 1, 1, 1);
+ test0<Input1, Input2, Output>( 2, 3, 1); // relatively prime
+ test0<Input1, Input2, Output>( 2, 4, 2);
+ test0<Input1, Input2, Output>( 36, 17, 1); // relatively prime
+ test0<Input1, Input2, Output>( 36, 18, 18);
+
+// Otherwise, returns the greatest common divisor of |m| and |n|.
+ test0<Input1, Input2, Output>( 1, -1, 1);
+ test0<Input1, Input2, Output>( 2, -3, 1); // relatively prime
+ test0<Input1, Input2, Output>( 2, -4, 2);
+ test0<Input1, Input2, Output>( 36, -17, 1); // relatively prime
+ test0<Input1, Input2, Output>( 36, -18, 18);
+}
+
+int main()
+{
+ test_same_signed<signed char>();
+ test_same_signed<short>();
+ test_same_signed<int>();
+ test_same_signed<long>();
+ test_same_signed<long long>();
+
+ test_same_signed< int8_t>();
+ test_same_signed<int16_t>();
+ test_same_signed<int32_t>();
+ test_same_signed<int64_t>();
+
+ test_same_unsigned<unsigned char>();
+ test_same_unsigned<unsigned short>();
+ test_same_unsigned<unsigned int>();
+ test_same_unsigned<unsigned long>();
+ test_same_unsigned<unsigned long long>();
+ test_same_unsigned<std::size_t>();
+
+ test_same_unsigned< uint8_t>();
+ test_same_unsigned<uint16_t>();
+ test_same_unsigned<uint32_t>();
+ test_same_unsigned<uint64_t>();
+
+ test_different_signed<signed char, int, int>();
+ test_different_signed<int, signed char, int>();
+ test_different_signed<short, int, int>();
+ test_different_signed<int, short, int>();
+ test_different_signed<int, long, long>();
+ test_different_signed<long, int, long>();
+ test_different_signed<int, long long, long long>();
+ test_different_signed<long long, int, long long>();
+
+ test_different_unsigned<unsigned char, unsigned int, unsigned int>();
+ test_different_unsigned<unsigned int, unsigned char, unsigned int>();
+ test_different_unsigned<unsigned short, unsigned int, unsigned int>();
+ test_different_unsigned<unsigned int, unsigned short, unsigned int>();
+ test_different_unsigned<unsigned int, unsigned long, unsigned long>();
+ test_different_unsigned<unsigned long, unsigned int, unsigned long>();
+ test_different_unsigned<unsigned int, unsigned long long, unsigned long long>();
+ test_different_unsigned<unsigned long long, unsigned int, unsigned long long>();
+
+ test_mixed_first_signed<signed char, unsigned char, int>();
+ test_mixed_first_signed<int, unsigned char, int>();
+ test_mixed_first_signed<int, unsigned int, unsigned int>();
+ test_mixed_first_signed<long, unsigned int, long>();
+ test_mixed_first_signed<long long, unsigned int, long long>();
+ test_mixed_first_signed<long long, unsigned long, unsigned long long>();
+
+ test_mixed_second_signed<unsigned char, signed char, int>();
+ test_mixed_second_signed<unsigned char, int, int>();
+ test_mixed_second_signed<unsigned int, int, unsigned int>();
+ test_mixed_second_signed<unsigned int, long, long>();
+ test_mixed_second_signed<unsigned int, long long, long long>();
+ test_mixed_second_signed<unsigned long, long long, unsigned long long>();
+
+// Weirdness with bool
+ test0<bool, signed char, int>(false, 'A', 'A');
+ test0<bool, signed char, int>(true, 'B', 1);
+ test0<bool, int, int>(false, 3, 3);
+ test0<bool, int, int>(true, 3, 1);
+}
Index: test/std/experimental/numeric/numeric.ops/numeric.ops.gcd/gcd.not_integral2.fail.cpp
===================================================================
--- test/std/experimental/numeric/numeric.ops/numeric.ops.gcd/gcd.not_integral2.fail.cpp
+++ test/std/experimental/numeric/numeric.ops/numeric.ops.gcd/gcd.not_integral2.fail.cpp
@@ -0,0 +1,24 @@
+//===----------------------------------------------------------------------===//
+//
+// 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.
+//
+//===----------------------------------------------------------------------===//
+//
+// UNSUPPORTED: c++98, c++03, c++11
+// <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, the program is ill-formed.
+
+#include <experimental/numeric>
+
+
+int main()
+{
+ std::experimental::gcd(4, 6.0);
+}
Index: test/std/experimental/numeric/numeric.ops/numeric.ops.gcd/gcd.not_integral1.fail.cpp
===================================================================
--- test/std/experimental/numeric/numeric.ops/numeric.ops.gcd/gcd.not_integral1.fail.cpp
+++ test/std/experimental/numeric/numeric.ops/numeric.ops.gcd/gcd.not_integral1.fail.cpp
@@ -0,0 +1,24 @@
+//===----------------------------------------------------------------------===//
+//
+// 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.
+//
+//===----------------------------------------------------------------------===//
+//
+// UNSUPPORTED: c++98, c++03, c++11
+// <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, the program is ill-formed.
+
+#include <experimental/numeric>
+
+
+int main()
+{
+ std::experimental::gcd(2.0, 4);
+}
Index: test/std/experimental/numeric/numeric.ops/nothing_to_do.pass.cpp
===================================================================
--- test/std/experimental/numeric/numeric.ops/nothing_to_do.pass.cpp
+++ test/std/experimental/numeric/numeric.ops/nothing_to_do.pass.cpp
@@ -0,0 +1,15 @@
+//===----------------------------------------------------------------------===//
+//
+// 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.
+//
+//===----------------------------------------------------------------------===//
+//
+// UNSUPPORTED: c++98, c++03, c++11
+// <numeric>
+
+#include <experimental/numeric>
+
+int main () {}
Index: include/experimental/numeric
===================================================================
--- include/experimental/numeric
+++ include/experimental/numeric
@@ -0,0 +1,100 @@
+// -*- 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<class M, class N>
+ constexpr common_type_t<M,N> gcd(M m, N n);
+
+ // 13.1.3, Least common multiple
+ template<class M, class N>
+ constexpr common_type_t<M,N> lcm(M m, N n);
+
+} // namespace fundamentals_v2
+} // namespace experimental
+} // namespace std
+
+ */
+
+#include <experimental/__config>
+#include <numeric>
+#include <type_traits> // is_integral
+#include <limits> // numeric_limits
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_LFTS
+
+template <typename _Tp, bool _IsSigned = is_signed<_Tp>::value> struct __abs;
+
+template <typename _Tp>
+struct __abs<_Tp, true> {
+ _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
+ _Tp operator()(_Tp __t) const noexcept { return __t >= 0 ? __t : -__t; }
+};
+
+template <typename _Tp>
+struct __abs<_Tp, false> {
+ _LIBCPP_CONSTEXPR _LIBCPP_INLINE_VISIBILITY
+ _Tp operator()(_Tp __t) const noexcept { return __t; }
+};
+
+
+template<class _Tp>
+_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<class _Tp, class _Up>
+_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<class _Tp, class _Up>
+_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
+
+#endif /* _LIBCPP_EXPERIMENTAL_MAP */
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits