master
ブランチ master
ShaderPlayground / deps / glm / glm / gtc / round.inl
9.1 KB、343行 生 Blame 履歴
1/// @ref gtc_round
2
3#include "../integer.hpp"
4
5namespace glm{
6namespace detail
7{
8 template<length_t L, typename T, qualifier Q, bool compute = false>
9 struct compute_ceilShift
10 {
11 GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& v, T)
12 {
13 return v;
14 }
15 };
16
17 template<length_t L, typename T, qualifier Q>
18 struct compute_ceilShift<L, T, Q, true>
19 {
20 GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& v, T Shift)
21 {
22 return v | (v >> Shift);
23 }
24 };
25
26 template<length_t L, typename T, qualifier Q, bool isSigned = true>
27 struct compute_ceilPowerOfTwo
28 {
29 GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x)
30 {
31 GLM_STATIC_ASSERT(!std::numeric_limits<T>::is_iec559, "'ceilPowerOfTwo' only accept integer scalar or vector inputs");
32
33 vec<L, T, Q> const Sign(sign(x));
34
35 vec<L, T, Q> v(abs(x));
36
37 v = v - static_cast<T>(1);
38 v = v | (v >> static_cast<T>(1));
39 v = v | (v >> static_cast<T>(2));
40 v = v | (v >> static_cast<T>(4));
41 v = compute_ceilShift<L, T, Q, sizeof(T) >= 2>::call(v, 8);
42 v = compute_ceilShift<L, T, Q, sizeof(T) >= 4>::call(v, 16);
43 v = compute_ceilShift<L, T, Q, sizeof(T) >= 8>::call(v, 32);
44 return (v + static_cast<T>(1)) * Sign;
45 }
46 };
47
48 template<length_t L, typename T, qualifier Q>
49 struct compute_ceilPowerOfTwo<L, T, Q, false>
50 {
51 GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x)
52 {
53 GLM_STATIC_ASSERT(!std::numeric_limits<T>::is_iec559, "'ceilPowerOfTwo' only accept integer scalar or vector inputs");
54
55 vec<L, T, Q> v(x);
56
57 v = v - static_cast<T>(1);
58 v = v | (v >> static_cast<T>(1));
59 v = v | (v >> static_cast<T>(2));
60 v = v | (v >> static_cast<T>(4));
61 v = compute_ceilShift<L, T, Q, sizeof(T) >= 2>::call(v, 8);
62 v = compute_ceilShift<L, T, Q, sizeof(T) >= 4>::call(v, 16);
63 v = compute_ceilShift<L, T, Q, sizeof(T) >= 8>::call(v, 32);
64 return v + static_cast<T>(1);
65 }
66 };
67
68 template<bool is_float, bool is_signed>
69 struct compute_ceilMultiple{};
70
71 template<>
72 struct compute_ceilMultiple<true, true>
73 {
74 template<typename genType>
75 GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
76 {
77 if(Source > genType(0))
78 return Source + (Multiple - std::fmod(Source, Multiple));
79 else
80 return Source + std::fmod(-Source, Multiple);
81 }
82 };
83
84 template<>
85 struct compute_ceilMultiple<false, false>
86 {
87 template<typename genType>
88 GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
89 {
90 genType Tmp = Source - genType(1);
91 return Tmp + (Multiple - (Tmp % Multiple));
92 }
93 };
94
95 template<>
96 struct compute_ceilMultiple<false, true>
97 {
98 template<typename genType>
99 GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
100 {
101 if(Source > genType(0))
102 {
103 genType Tmp = Source - genType(1);
104 return Tmp + (Multiple - (Tmp % Multiple));
105 }
106 else
107 return Source + (-Source % Multiple);
108 }
109 };
110
111 template<bool is_float, bool is_signed>
112 struct compute_floorMultiple{};
113
114 template<>
115 struct compute_floorMultiple<true, true>
116 {
117 template<typename genType>
118 GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
119 {
120 if(Source >= genType(0))
121 return Source - std::fmod(Source, Multiple);
122 else
123 return Source - std::fmod(Source, Multiple) - Multiple;
124 }
125 };
126
127 template<>
128 struct compute_floorMultiple<false, false>
129 {
130 template<typename genType>
131 GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
132 {
133 if(Source >= genType(0))
134 return Source - Source % Multiple;
135 else
136 {
137 genType Tmp = Source + genType(1);
138 return Tmp - Tmp % Multiple - Multiple;
139 }
140 }
141 };
142
143 template<>
144 struct compute_floorMultiple<false, true>
145 {
146 template<typename genType>
147 GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
148 {
149 if(Source >= genType(0))
150 return Source - Source % Multiple;
151 else
152 {
153 genType Tmp = Source + genType(1);
154 return Tmp - Tmp % Multiple - Multiple;
155 }
156 }
157 };
158
159 template<bool is_float, bool is_signed>
160 struct compute_roundMultiple{};
161
162 template<>
163 struct compute_roundMultiple<true, true>
164 {
165 template<typename genType>
166 GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
167 {
168 if(Source >= genType(0))
169 return Source - std::fmod(Source, Multiple);
170 else
171 {
172 genType Tmp = Source + genType(1);
173 return Tmp - std::fmod(Tmp, Multiple) - Multiple;
174 }
175 }
176 };
177
178 template<>
179 struct compute_roundMultiple<false, false>
180 {
181 template<typename genType>
182 GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
183 {
184 if(Source >= genType(0))
185 return Source - Source % Multiple;
186 else
187 {
188 genType Tmp = Source + genType(1);
189 return Tmp - Tmp % Multiple - Multiple;
190 }
191 }
192 };
193
194 template<>
195 struct compute_roundMultiple<false, true>
196 {
197 template<typename genType>
198 GLM_FUNC_QUALIFIER static genType call(genType Source, genType Multiple)
199 {
200 if(Source >= genType(0))
201 return Source - Source % Multiple;
202 else
203 {
204 genType Tmp = Source + genType(1);
205 return Tmp - Tmp % Multiple - Multiple;
206 }
207 }
208 };
209}//namespace detail
210
211 ////////////////
212 // isPowerOfTwo
213
214 template<typename genType>
215 GLM_FUNC_QUALIFIER bool isPowerOfTwo(genType Value)
216 {
217 genType const Result = glm::abs(Value);
218 return !(Result & (Result - 1));
219 }
220
221 template<length_t L, typename T, qualifier Q>
222 GLM_FUNC_QUALIFIER vec<L, bool, Q> isPowerOfTwo(vec<L, T, Q> const& Value)
223 {
224 vec<L, T, Q> const Result(abs(Value));
225 return equal(Result & (Result - 1), vec<L, T, Q>(0));
226 }
227
228 //////////////////
229 // ceilPowerOfTwo
230
231 template<typename genType>
232 GLM_FUNC_QUALIFIER genType ceilPowerOfTwo(genType value)
233 {
234 return detail::compute_ceilPowerOfTwo<1, genType, defaultp, std::numeric_limits<genType>::is_signed>::call(vec<1, genType, defaultp>(value)).x;
235 }
236
237 template<length_t L, typename T, qualifier Q>
238 GLM_FUNC_QUALIFIER vec<L, T, Q> ceilPowerOfTwo(vec<L, T, Q> const& v)
239 {
240 return detail::compute_ceilPowerOfTwo<L, T, Q, std::numeric_limits<T>::is_signed>::call(v);
241 }
242
243 ///////////////////
244 // floorPowerOfTwo
245
246 template<typename genType>
247 GLM_FUNC_QUALIFIER genType floorPowerOfTwo(genType value)
248 {
249 return isPowerOfTwo(value) ? value : static_cast<genType>(1) << findMSB(value);
250 }
251
252 template<length_t L, typename T, qualifier Q>
253 GLM_FUNC_QUALIFIER vec<L, T, Q> floorPowerOfTwo(vec<L, T, Q> const& v)
254 {
255 return detail::functor1<vec, L, T, T, Q>::call(floorPowerOfTwo, v);
256 }
257
258 ///////////////////
259 // roundPowerOfTwo
260
261 template<typename genIUType>
262 GLM_FUNC_QUALIFIER genIUType roundPowerOfTwo(genIUType value)
263 {
264 if(isPowerOfTwo(value))
265 return value;
266
267 genIUType const prev = static_cast<genIUType>(1) << findMSB(value);
268 genIUType const next = prev << static_cast<genIUType>(1);
269 return (next - value) < (value - prev) ? next : prev;
270 }
271
272 template<length_t L, typename T, qualifier Q>
273 GLM_FUNC_QUALIFIER vec<L, T, Q> roundPowerOfTwo(vec<L, T, Q> const& v)
274 {
275 return detail::functor1<vec, L, T, T, Q>::call(roundPowerOfTwo, v);
276 }
277
278 ////////////////
279 // isMultiple
280
281 template<typename genType>
282 GLM_FUNC_QUALIFIER bool isMultiple(genType Value, genType Multiple)
283 {
284 return isMultiple(vec<1, genType>(Value), vec<1, genType>(Multiple)).x;
285 }
286
287 template<length_t L, typename T, qualifier Q>
288 GLM_FUNC_QUALIFIER vec<L, bool, Q> isMultiple(vec<L, T, Q> const& Value, T Multiple)
289 {
290 return (Value % Multiple) == vec<L, T, Q>(0);
291 }
292
293 template<length_t L, typename T, qualifier Q>
294 GLM_FUNC_QUALIFIER vec<L, bool, Q> isMultiple(vec<L, T, Q> const& Value, vec<L, T, Q> const& Multiple)
295 {
296 return (Value % Multiple) == vec<L, T, Q>(0);
297 }
298
299 //////////////////////
300 // ceilMultiple
301
302 template<typename genType>
303 GLM_FUNC_QUALIFIER genType ceilMultiple(genType Source, genType Multiple)
304 {
305 return detail::compute_ceilMultiple<std::numeric_limits<genType>::is_iec559, std::numeric_limits<genType>::is_signed>::call(Source, Multiple);
306 }
307
308 template<length_t L, typename T, qualifier Q>
309 GLM_FUNC_QUALIFIER vec<L, T, Q> ceilMultiple(vec<L, T, Q> const& Source, vec<L, T, Q> const& Multiple)
310 {
311 return detail::functor2<vec, L, T, Q>::call(ceilMultiple, Source, Multiple);
312 }
313
314 //////////////////////
315 // floorMultiple
316
317 template<typename genType>
318 GLM_FUNC_QUALIFIER genType floorMultiple(genType Source, genType Multiple)
319 {
320 return detail::compute_floorMultiple<std::numeric_limits<genType>::is_iec559, std::numeric_limits<genType>::is_signed>::call(Source, Multiple);
321 }
322
323 template<length_t L, typename T, qualifier Q>
324 GLM_FUNC_QUALIFIER vec<L, T, Q> floorMultiple(vec<L, T, Q> const& Source, vec<L, T, Q> const& Multiple)
325 {
326 return detail::functor2<vec, L, T, Q>::call(floorMultiple, Source, Multiple);
327 }
328
329 //////////////////////
330 // roundMultiple
331
332 template<typename genType>
333 GLM_FUNC_QUALIFIER genType roundMultiple(genType Source, genType Multiple)
334 {
335 return detail::compute_roundMultiple<std::numeric_limits<genType>::is_iec559, std::numeric_limits<genType>::is_signed>::call(Source, Multiple);
336 }
337
338 template<length_t L, typename T, qualifier Q>
339 GLM_FUNC_QUALIFIER vec<L, T, Q> roundMultiple(vec<L, T, Q> const& Source, vec<L, T, Q> const& Multiple)
340 {
341 return detail::functor2<vec, L, T, Q>::call(roundMultiple, Source, Multiple);
342 }
343}//namespace glm