11c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow//===----------------------------------------------------------------------===//
21c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow//
31c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow//                     The LLVM Compiler Infrastructure
41c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow//
51c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow// This file is dual licensed under the MIT and the University of Illinois Open
61c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow// Source Licenses. See LICENSE.TXT for details.
71c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow//
81c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow//===----------------------------------------------------------------------===//
9e33c0b01f892f8919f66a066a9c4064010104e49Stephan T. Lavavej//
101c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow// UNSUPPORTED: c++98, c++03, c++11, c++14
111b8fc14abc2ac3bbef8a135fbc4ad2264493edc6Marshall Clow
121c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow// <numeric>
131c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow
141c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow// template<class _M, class _N>
151c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow// constexpr common_type_t<_M,_N> gcd(_M __m, _N __n)
161c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow
171c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow#include <numeric>
181c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow#include <cassert>
191c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow#include <cstdlib>    // for rand()
201c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow#include <iostream>
211c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow
221c1e91d9a35e51778b49a73b39012768770cd482Marshall Clowconstexpr struct {
231c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow  int x;
241c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow  int y;
251c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow  int expect;
261c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow} Cases[] = {
271c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    {0, 0, 0},
281c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    {1, 0, 1},
291c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    {0, 1, 1},
301c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    {1, 1, 1},
311c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    {2, 3, 1},
321c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    {2, 4, 2},
331c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    {36, 17, 1},
341c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    {36, 18, 18}
351c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow};
361c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow
371c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow
381c1e91d9a35e51778b49a73b39012768770cd482Marshall Clowtemplate <typename Input1, typename Input2, typename Output>
391c1e91d9a35e51778b49a73b39012768770cd482Marshall Clowconstexpr bool test0(Input1 in1, Input2 in2, Output out)
401c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow{
411c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    static_assert((std::is_same<Output, decltype(std::gcd(in1, in2))>::value), "" );
421c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    static_assert((std::is_same<Output, decltype(std::gcd(in2, in1))>::value), "" );
431c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    return out == std::gcd(in1, in2) ? true : (std::abort(), false);
441c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow}
451c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow
461c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow
471c1e91d9a35e51778b49a73b39012768770cd482Marshall Clowtemplate <typename Input1, typename Input2 = Input1>
480e5ebbc77c3c2cfd7d835fcfe40fcb65df0c5598Eric Fiselierconstexpr bool do_test(int = 0)
491c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow{
501c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    using S1 = typename std::make_signed<Input1>::type;
511c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    using S2 = typename std::make_signed<Input2>::type;
521c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    using U1 = typename std::make_unsigned<Input1>::type;
531c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    using U2 = typename std::make_unsigned<Input2>::type;
541c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    bool accumulate = true;
551c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    for (auto TC : Cases) {
561c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow        { // Test with two signed types
571c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow            using Output = std::common_type_t<S1, S2>;
581c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow            accumulate &= test0<S1, S2, Output>(TC.x, TC.y, TC.expect);
591c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow            accumulate &= test0<S1, S2, Output>(-TC.x, TC.y, TC.expect);
601c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow            accumulate &= test0<S1, S2, Output>(TC.x, -TC.y, TC.expect);
611c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow            accumulate &= test0<S1, S2, Output>(-TC.x, -TC.y, TC.expect);
621c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow            accumulate &= test0<S2, S1, Output>(TC.x, TC.y, TC.expect);
631c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow            accumulate &= test0<S2, S1, Output>(-TC.x, TC.y, TC.expect);
641c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow            accumulate &= test0<S2, S1, Output>(TC.x, -TC.y, TC.expect);
651c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow            accumulate &= test0<S2, S1, Output>(-TC.x, -TC.y, TC.expect);
661c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow        }
671c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow        { // test with two unsigned types
681c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow            using Output = std::common_type_t<U1, U2>;
691c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow            accumulate &= test0<U1, U2, Output>(TC.x, TC.y, TC.expect);
701c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow            accumulate &= test0<U2, U1, Output>(TC.x, TC.y, TC.expect);
711c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow        }
721c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow        { // Test with mixed signs
731c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow            using Output = std::common_type_t<S1, U2>;
741c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow            accumulate &= test0<S1, U2, Output>(TC.x, TC.y, TC.expect);
751c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow            accumulate &= test0<U2, S1, Output>(TC.x, TC.y, TC.expect);
761c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow            accumulate &= test0<S1, U2, Output>(-TC.x, TC.y, TC.expect);
771c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow            accumulate &= test0<U2, S1, Output>(TC.x, -TC.y, TC.expect);
781c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow        }
791c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow        { // Test with mixed signs
801c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow            using Output = std::common_type_t<S2, U1>;
811c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow            accumulate &= test0<S2, U1, Output>(TC.x, TC.y, TC.expect);
821c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow            accumulate &= test0<U1, S2, Output>(TC.x, TC.y, TC.expect);
831c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow            accumulate &= test0<S2, U1, Output>(-TC.x, TC.y, TC.expect);
841c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow            accumulate &= test0<U1, S2, Output>(TC.x, -TC.y, TC.expect);
851c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow        }
861c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    }
871c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    return accumulate;
881c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow}
891c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow
901c1e91d9a35e51778b49a73b39012768770cd482Marshall Clowint main()
911c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow{
921c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    auto non_cce = std::rand(); // a value that can't possibly be constexpr
931c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow
941c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    static_assert(do_test<signed char>(), "");
951c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    static_assert(do_test<short>(), "");
961c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    static_assert(do_test<int>(), "");
971c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    static_assert(do_test<long>(), "");
981c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    static_assert(do_test<long long>(), "");
991c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow
1001c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    assert(do_test<signed char>(non_cce));
1011c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    assert(do_test<short>(non_cce));
1021c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    assert(do_test<int>(non_cce));
1031c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    assert(do_test<long>(non_cce));
1041c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    assert(do_test<long long>(non_cce));
1051c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow
1061c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    static_assert(do_test< int8_t>(), "");
1071c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    static_assert(do_test<int16_t>(), "");
1081c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    static_assert(do_test<int32_t>(), "");
1091c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    static_assert(do_test<int64_t>(), "");
1101c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow
1111c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    assert(do_test< int8_t>(non_cce));
1121c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    assert(do_test<int16_t>(non_cce));
1131c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    assert(do_test<int32_t>(non_cce));
1141c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    assert(do_test<int64_t>(non_cce));
1151c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow
1161c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    static_assert(do_test<signed char, int>(), "");
1171c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    static_assert(do_test<int, signed char>(), "");
1181c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    static_assert(do_test<short, int>(), "");
1191c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    static_assert(do_test<int, short>(), "");
1201c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    static_assert(do_test<int, long>(), "");
1211c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    static_assert(do_test<long, int>(), "");
1221c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    static_assert(do_test<int, long long>(), "");
1231c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    static_assert(do_test<long long, int>(), "");
1241c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow
1251c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    assert((do_test<signed char, int>(non_cce)));
1261c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    assert((do_test<int, signed char>(non_cce)));
1271c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    assert((do_test<short, int>(non_cce)));
1281c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    assert((do_test<int, short>(non_cce)));
1291c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    assert((do_test<int, long>(non_cce)));
1301c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    assert((do_test<long, int>(non_cce)));
1311c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    assert((do_test<int, long long>(non_cce)));
1321c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow    assert((do_test<long long, int>(non_cce)));
13324597f254dc229da1aa50258b7f444a0e479460fMarshall Clow
13424597f254dc229da1aa50258b7f444a0e479460fMarshall Clow//  LWG#2837
13524597f254dc229da1aa50258b7f444a0e479460fMarshall Clow    {
13624597f254dc229da1aa50258b7f444a0e479460fMarshall Clow        auto res = std::gcd((int64_t)1234, (int32_t)-2147483648);
13724597f254dc229da1aa50258b7f444a0e479460fMarshall Clow        static_assert( std::is_same<decltype(res), std::common_type<int64_t, int32_t>::type>::value, "");
13824597f254dc229da1aa50258b7f444a0e479460fMarshall Clow        assert(res == 2);
13924597f254dc229da1aa50258b7f444a0e479460fMarshall Clow    }
1401c1e91d9a35e51778b49a73b39012768770cd482Marshall Clow}
141