13e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow//===----------------------------------------------------------------------===//
23e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow//
33e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow//                     The LLVM Compiler Infrastructure
43e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow//
53e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow// This file is dual licensed under the MIT and the University of Illinois Open
63e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow// Source Licenses. See LICENSE.TXT for details.
73e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow//
83e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow//===----------------------------------------------------------------------===//
93e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow
103e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow// <algorithm>
111575e3e813f7f7cde31e699802fa1fcf8e84531cAsiri Rathnayake// XFAIL: c++98, c++03, c++11, c++14
123e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow
133e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow// template<class T>
143e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow//   const T&
153e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow//   clamp(const T& v, const T& lo, const T& hi);
163e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow
173e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow#include <algorithm>
183e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow#include <cassert>
193e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow
200b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clowstruct Tag {
210b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow	Tag() : val(0), tag("Default") {}
220b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow	Tag(int a, const char *b) : val(a), tag(b) {}
230b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow	~Tag() {}
24e33c0b01f892f8919f66a066a9c4064010104e49Stephan T. Lavavej
250b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow	int val;
260b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow	const char *tag;
270b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow	};
28e33c0b01f892f8919f66a066a9c4064010104e49Stephan T. Lavavej
290b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clowbool eq(const Tag& rhs, const Tag& lhs) { return rhs.val == lhs.val && rhs.tag == lhs.tag; }
300b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow// bool operator==(const Tag& rhs, const Tag& lhs) { return rhs.val == lhs.val; }
310b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clowbool operator< (const Tag& rhs, const Tag& lhs) { return rhs.val <  lhs.val; }
320b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow
333e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clowtemplate <class T>
343e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clowvoid
353e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clowtest(const T& a, const T& lo, const T& hi, const T& x)
363e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow{
373e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow    assert(&std::clamp(a, lo, hi) == &x);
383e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow}
393e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow
403e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clowint main()
413e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow{
423e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow    {
433e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow    int x = 0;
443e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow    int y = 0;
453e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow    int z = 0;
463e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow    test(x, y, z, x);
473e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow    test(y, x, z, y);
483e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow    }
493e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow    {
503e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow    int x = 0;
513e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow    int y = 1;
523e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow    int z = 2;
533e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow    test(x, y, z, y);
543e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow    test(y, x, z, y);
553e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow    }
563e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow    {
573e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow    int x = 1;
583e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow    int y = 0;
593e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow    int z = 1;
603e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow    test(x, y, z, x);
613e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow    test(y, x, z, x);
623e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow    }
630b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow
640b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    {
650b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow//  If they're all the same, we should get the value back.
660b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    Tag x{0, "Zero-x"};
670b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    Tag y{0, "Zero-y"};
680b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    Tag z{0, "Zero-z"};
690b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    assert(eq(std::clamp(x, y, z), x));
700b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    assert(eq(std::clamp(y, x, z), y));
710b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    }
720b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow
730b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    {
740b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow//  If it's the same as the lower bound, we get the value back.
750b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    Tag x{0, "Zero-x"};
760b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    Tag y{0, "Zero-y"};
770b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    Tag z{1, "One-z"};
780b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    assert(eq(std::clamp(x, y, z), x));
790b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    assert(eq(std::clamp(y, x, z), y));
800b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    }
810b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow
820b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    {
830b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow//  If it's the same as the upper bound, we get the value back.
840b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    Tag x{1, "One-x"};
850b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    Tag y{0, "Zero-y"};
860b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    Tag z{1, "One-z"};
870b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    assert(eq(std::clamp(x, y, z), x));
880b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    assert(eq(std::clamp(z, y, x), z));
890b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    }
900b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow
910b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    {
920b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow//  If the value is between, we should get the value back
930b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    Tag x{1, "One-x"};
940b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    Tag y{0, "Zero-y"};
950b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    Tag z{2, "Two-z"};
960b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    assert(eq(std::clamp(x, y, z), x));
970b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    assert(eq(std::clamp(y, x, z), x));
980b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    }
990b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow
1000b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    {
1010b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow//  If the value is less than the 'lo', we should get the lo back.
1020b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    Tag x{0, "Zero-x"};
1030b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    Tag y{1, "One-y"};
1040b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    Tag z{2, "Two-z"};
1050b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    assert(eq(std::clamp(x, y, z), y));
1060b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    assert(eq(std::clamp(y, x, z), y));
1070b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    }
1080b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    {
1090b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow//  If the value is greater than 'hi', we should get hi back.
1100b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    Tag x{2, "Two-x"};
1110b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    Tag y{0, "Zero-y"};
1120b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    Tag z{1, "One-z"};
1130b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    assert(eq(std::clamp(x, y, z), z));
1140b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    assert(eq(std::clamp(y, z, x), z));
1150b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow    }
1160b02cf8cf16919074f88c26d412c34ad2cffc097Marshall Clow
1173e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow    {
1183e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow    typedef int T;
1193e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow    constexpr T x = 1;
1203e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow    constexpr T y = 0;
1213e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow    constexpr T z = 1;
1223e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow    static_assert(std::clamp(x, y, z) == x, "" );
1233e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow    static_assert(std::clamp(y, x, z) == x, "" );
1243e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow    }
1253e0808efb8c19765ee86e950a8a6e340c5565c89Marshall Clow}
126