1
2 //
3 // This source file is part of appleseed.
4 // Visit https://appleseedhq.net/ for additional information and resources.
5 //
6 // This software is released under the MIT license.
7 //
8 // Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited
9 // Copyright (c) 2014-2018 Francois Beaune, The appleseedhq Organization
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining a copy
12 // of this software and associated documentation files (the "Software"), to deal
13 // in the Software without restriction, including without limitation the rights
14 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 // copies of the Software, and to permit persons to whom the Software is
16 // furnished to do so, subject to the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be included in
19 // all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27 // THE SOFTWARE.
28 //
29
30 #pragma once
31
32 // Standard headers.
33 #include <algorithm>
34 #include <cstddef>
35
36 namespace foundation
37 {
38
39 //
40 // Import std::min() and std::max() into the foundation namespace, otherwise they'll be shadowed.
41 //
42
43 using std::min;
44 using std::max;
45
46
47 //
48 // Return the lesser of a set of objects.
49 //
50
51 template <typename T>
52 T min(const T a, const T b, const T c);
53
54 template <typename T>
55 T min(const T a, const T b, const T c, const T d);
56
57
58 //
59 // Return the greater of a set of objects.
60 //
61
62 template <typename T>
63 T max(const T a, const T b, const T c);
64
65 template <typename T>
66 T max(const T a, const T b, const T c, const T d);
67
68
69 //
70 // Return both the lesser and greater of a set of objects.
71 //
72
73 template <typename T>
74 void minmax(const T a, const T b, T& min, T& max);
75
76 template <typename T>
77 void minmax(const T a, const T b, const T c, T& min, T& max);
78
79
80 //
81 // Return the lesser (resp. greater) of two objects with the exact
82 // same semantics as the SSE instructions 'minps' (resp. 'maxps').
83 //
84 // An important property guaranteed by these functions is that if
85 // a, b or both are NaN, b will always be returned. Thus, if b is
86 // never NaN, the min/max of a and b is guaranteed not to be NaN.
87 //
88 // References:
89 //
90 // http://www.sesp.cse.clrc.ac.uk/html/SoftwareTools/vtune/users_guide/mergedProjects/analyzer_ec/mergedProjects/reference_olh/mergedProjects/instructions/instruct32_hh/vc174.htm
91 // http://www.sesp.cse.clrc.ac.uk/html/SoftwareTools/vtune/users_guide/mergedProjects/analyzer_ec/mergedProjects/reference_olh/mergedProjects/instructions/instruct32_hh/vc169.htm
92 //
93
94 template <typename T>
95 T ssemin(const T a, const T b);
96
97 template <typename T>
98 T ssemax(const T a, const T b);
99
100
101 //
102 // Return the index of the lesser or greater of a set of objects.
103 //
104
105 template <typename T>
106 size_t min_index(const T& a, const T& b);
107
108 template <typename T>
109 size_t min_index(const T& a, const T& b, const T& c);
110
111 template <typename T>
112 size_t max_index(const T& a, const T& b);
113
114 template <typename T>
115 size_t max_index(const T& a, const T& b, const T& c);
116
117
118 //
119 // Implementation.
120 //
121
122 template <typename T>
min(const T a,const T b,const T c)123 inline T min(const T a, const T b, const T c)
124 {
125 return std::min(std::min(a, b), c);
126 }
127
128 template <typename T>
min(const T a,const T b,const T c,const T d)129 inline T min(const T a, const T b, const T c, const T d)
130 {
131 return std::min(std::min(std::min(a, b), c), d);
132 }
133
134 template <typename T>
max(const T a,const T b,const T c)135 inline T max(const T a, const T b, const T c)
136 {
137 return std::max(std::max(a, b), c);
138 }
139
140 template <typename T>
max(const T a,const T b,const T c,const T d)141 inline T max(const T a, const T b, const T c, const T d)
142 {
143 return std::max(std::max(std::max(a, b), c), d);
144 }
145
146 template <typename T>
minmax(const T a,const T b,T & min,T & max)147 inline void minmax(const T a, const T b, T& min, T& max)
148 {
149 if (a < b)
150 {
151 min = a;
152 max = b;
153 }
154 else
155 {
156 min = b;
157 max = a;
158 }
159 }
160
161 template <typename T>
minmax(const T a,const T b,const T c,T & min,T & max)162 inline void minmax(const T a, const T b, const T c, T& min, T& max)
163 {
164 minmax(a, b, min, max);
165
166 if (c < min) min = c;
167 if (c > max) max = c;
168 }
169
170 template <typename T>
ssemin(const T a,const T b)171 inline T ssemin(const T a, const T b)
172 {
173 return a < b ? a : b;
174 }
175
176 template <typename T>
ssemax(const T a,const T b)177 inline T ssemax(const T a, const T b)
178 {
179 return a > b ? a : b;
180 }
181
182 template <typename T>
min_index(const T & a,const T & b)183 inline size_t min_index(const T& a, const T& b)
184 {
185 return a < b ? 0 : 1;
186 }
187
188 template <typename T>
min_index(const T & a,const T & b,const T & c)189 inline size_t min_index(const T& a, const T& b, const T& c)
190 {
191 if (a < b)
192 return a < c ? 0 : 2;
193 else return b < c ? 1 : 2;
194 }
195
196 template <typename T>
max_index(const T & a,const T & b)197 inline size_t max_index(const T& a, const T& b)
198 {
199 return a > b ? 0 : 1;
200 }
201
202 template <typename T>
max_index(const T & a,const T & b,const T & c)203 inline size_t max_index(const T& a, const T& b, const T& c)
204 {
205 if (a > b)
206 return a > c ? 0 : 2;
207 else return b > c ? 1 : 2;
208 }
209
210 } // namespace foundation
211