1//===----------------------------------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// <algorithm>
11// XFAIL: c++98, c++03, c++11, c++14
12
13// template<class T>
14//   const T&
15//   clamp(const T& v, const T& lo, const T& hi);
16
17#include <algorithm>
18#include <cassert>
19
20struct Tag {
21	Tag() : val(0), tag("Default") {}
22	Tag(int a, const char *b) : val(a), tag(b) {}
23	~Tag() {}
24
25	int val;
26	const char *tag;
27	};
28
29bool eq(const Tag& rhs, const Tag& lhs) { return rhs.val == lhs.val && rhs.tag == lhs.tag; }
30// bool operator==(const Tag& rhs, const Tag& lhs) { return rhs.val == lhs.val; }
31bool operator< (const Tag& rhs, const Tag& lhs) { return rhs.val <  lhs.val; }
32
33template <class T>
34void
35test(const T& a, const T& lo, const T& hi, const T& x)
36{
37    assert(&std::clamp(a, lo, hi) == &x);
38}
39
40int main()
41{
42    {
43    int x = 0;
44    int y = 0;
45    int z = 0;
46    test(x, y, z, x);
47    test(y, x, z, y);
48    }
49    {
50    int x = 0;
51    int y = 1;
52    int z = 2;
53    test(x, y, z, y);
54    test(y, x, z, y);
55    }
56    {
57    int x = 1;
58    int y = 0;
59    int z = 1;
60    test(x, y, z, x);
61    test(y, x, z, x);
62    }
63
64    {
65//  If they're all the same, we should get the value back.
66    Tag x{0, "Zero-x"};
67    Tag y{0, "Zero-y"};
68    Tag z{0, "Zero-z"};
69    assert(eq(std::clamp(x, y, z), x));
70    assert(eq(std::clamp(y, x, z), y));
71    }
72
73    {
74//  If it's the same as the lower bound, we get the value back.
75    Tag x{0, "Zero-x"};
76    Tag y{0, "Zero-y"};
77    Tag z{1, "One-z"};
78    assert(eq(std::clamp(x, y, z), x));
79    assert(eq(std::clamp(y, x, z), y));
80    }
81
82    {
83//  If it's the same as the upper bound, we get the value back.
84    Tag x{1, "One-x"};
85    Tag y{0, "Zero-y"};
86    Tag z{1, "One-z"};
87    assert(eq(std::clamp(x, y, z), x));
88    assert(eq(std::clamp(z, y, x), z));
89    }
90
91    {
92//  If the value is between, we should get the value back
93    Tag x{1, "One-x"};
94    Tag y{0, "Zero-y"};
95    Tag z{2, "Two-z"};
96    assert(eq(std::clamp(x, y, z), x));
97    assert(eq(std::clamp(y, x, z), x));
98    }
99
100    {
101//  If the value is less than the 'lo', we should get the lo back.
102    Tag x{0, "Zero-x"};
103    Tag y{1, "One-y"};
104    Tag z{2, "Two-z"};
105    assert(eq(std::clamp(x, y, z), y));
106    assert(eq(std::clamp(y, x, z), y));
107    }
108    {
109//  If the value is greater than 'hi', we should get hi back.
110    Tag x{2, "Two-x"};
111    Tag y{0, "Zero-y"};
112    Tag z{1, "One-z"};
113    assert(eq(std::clamp(x, y, z), z));
114    assert(eq(std::clamp(y, z, x), z));
115    }
116
117    {
118    typedef int T;
119    constexpr T x = 1;
120    constexpr T y = 0;
121    constexpr T z = 1;
122    static_assert(std::clamp(x, y, z) == x, "" );
123    static_assert(std::clamp(y, x, z) == x, "" );
124    }
125}
126