master
ブランチ master
VulkanExample / dep / include / glm / detail / func_common.inl
27 KB、849行 生 Blame 履歴
1/// @ref core
2/// @file glm/detail/func_common.inl
3
4#include "../vector_relational.hpp"
5#include "compute_common.hpp"
6#include "type_vec1.hpp"
7#include "type_vec2.hpp"
8#include "type_vec3.hpp"
9#include "type_vec4.hpp"
10#include "_vectorize.hpp"
11#include <limits>
12
13namespace glm
14{
15 // min
16 template<typename genType>
17 GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType min(genType x, genType y)
18 {
19 static_assert(std::numeric_limits<genType>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || std::numeric_limits<genType>::is_integer, "'min' only accept floating-point or integer inputs");
20 return (y < x) ? y : x;
21 }
22
23 // max
24 template<typename genType>
25 GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType max(genType x, genType y)
26 {
27 static_assert(std::numeric_limits<genType>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || std::numeric_limits<genType>::is_integer, "'max' only accept floating-point or integer inputs");
28
29 return (x < y) ? y : x;
30 }
31
32 using ::std::round;
33
34 using ::std::trunc;
35
36 // abs
37 template<>
38 GLM_FUNC_QUALIFIER GLM_CONSTEXPR int abs(int x)
39 {
40 int const y = x >> (sizeof(int) * 8 - 1);
41 return (x ^ y) - y;
42 }
43}//namespace glm
44
45namespace glm{
46namespace detail
47{
48 template<typename T>
49 struct TMin {
50 GLM_FUNC_QUALIFIER GLM_CONSTEXPR T operator()(const T& a, const T& b) { return min(a, b); }
51 };
52
53 template<typename T>
54 struct TMax {
55 GLM_FUNC_QUALIFIER GLM_CONSTEXPR T operator()(const T& a, const T& b) { return max(a, b); }
56 };
57
58 template<typename T>
59 struct TAbs {
60 T operator()(const T& a) { return abs(a); }
61 };
62
63 template<typename T>
64 struct TRound {
65 T operator()(const T& a) { return round(a); }
66 };
67
68 template<typename T>
69 struct TTrunc {
70 T operator()(const T& a) { return trunc(a); }
71 };
72
73 template<typename T>
74 struct TFmod {
75 T operator()(const T& a, const T& b) { return std::fmod(a, b); }
76 };
77
78 template<length_t L, typename T, qualifier Q, bool Aligned>
79 struct compute_abs_vector
80 {
81 GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<L, T, Q> call(vec<L, T, Q> const& x)
82 {
83 return detail::functor1<vec, L, T, T, Q>::call(abs, x);
84 }
85 };
86
87 template<length_t L, typename T, typename U, qualifier Q, bool Aligned>
88 struct compute_mix_vector
89 {
90 GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, U, Q> const& a)
91 {
92 static_assert(std::numeric_limits<U>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'mix' only accept floating-point inputs for the interpolator a");
93
94 return vec<L, T, Q>(vec<L, U, Q>(x) * (static_cast<U>(1) - a) + vec<L, U, Q>(y) * a);
95 }
96 };
97
98 template<length_t L, typename T, qualifier Q, bool Aligned>
99 struct compute_mix_vector<L, T, bool, Q, Aligned>
100 {
101 GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, bool, Q> const& a)
102 {
103 vec<L, T, Q> Result(0);
104 for(length_t i = 0; i < x.length(); ++i)
105 Result[i] = a[i] ? y[i] : x[i];
106 return Result;
107 }
108 };
109
110 template<length_t L, typename T, typename U, qualifier Q, bool Aligned>
111 struct compute_mix_scalar
112 {
113 GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& y, U const& a)
114 {
115 static_assert(std::numeric_limits<U>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'mix' only accept floating-point inputs for the interpolator a");
116
117 return vec<L, T, Q>(vec<L, U, Q>(x) * (static_cast<U>(1) - a) + vec<L, U, Q>(y) * a);
118 }
119 };
120
121 template<length_t L, typename T, qualifier Q, bool Aligned>
122 struct compute_mix_scalar<L, T, bool, Q, Aligned>
123 {
124 GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& y, bool const& a)
125 {
126 return a ? y : x;
127 }
128 };
129
130 template<typename T, typename U>
131 struct compute_mix
132 {
133 GLM_FUNC_QUALIFIER GLM_CONSTEXPR static T call(T const& x, T const& y, U const& a)
134 {
135 static_assert(std::numeric_limits<U>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'mix' only accept floating-point inputs for the interpolator a");
136
137 return static_cast<T>(static_cast<U>(x) * (static_cast<U>(1) - a) + static_cast<U>(y) * a);
138 }
139 };
140
141 template<typename T>
142 struct compute_mix<T, bool>
143 {
144 GLM_FUNC_QUALIFIER GLM_CONSTEXPR static T call(T const& x, T const& y, bool const& a)
145 {
146 return a ? y : x;
147 }
148 };
149
150 template<length_t L, typename T, qualifier Q, bool isFloat, bool Aligned>
151 struct compute_sign
152 {
153 GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x)
154 {
155 return vec<L, T, Q>(glm::lessThan(vec<L, T, Q>(0), x)) - vec<L, T, Q>(glm::lessThan(x, vec<L, T, Q>(0)));
156 }
157 };
158
159# if GLM_ARCH == GLM_ARCH_X86
160 template<length_t L, typename T, qualifier Q, bool Aligned>
161 struct compute_sign<L, T, Q, false, Aligned>
162 {
163 GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x)
164 {
165 T const Shift(static_cast<T>(sizeof(T) * 8 - 1));
166 vec<L, T, Q> const y(vec<L, typename std::make_unsigned<T>::type, Q>(-x) >> typename std::make_unsigned<T>::type(Shift));
167
168 return (x >> Shift) | y;
169 }
170 };
171# endif
172
173 template<length_t L, typename T, qualifier Q, bool Aligned>
174 struct compute_floor
175 {
176 GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x)
177 {
178 return detail::functor1<vec, L, T, T, Q>::call(std::floor, x);
179 }
180 };
181
182 template<length_t L, typename T, qualifier Q, bool Aligned>
183 struct compute_ceil
184 {
185 GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x)
186 {
187 return detail::functor1<vec, L, T, T, Q>::call(std::ceil, x);
188 }
189 };
190
191 template<length_t L, typename T, qualifier Q, bool Aligned>
192 struct compute_fract
193 {
194 GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x)
195 {
196 return x - floor(x);
197 }
198 };
199
200 template<length_t L, typename T, qualifier Q, bool Aligned>
201 struct compute_trunc
202 {
203 GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x)
204 {
205 return detail::functor1<vec, L, T, T, Q>::call(trunc, x);
206 }
207 };
208
209 template<length_t L, typename T, qualifier Q, bool Aligned>
210 struct compute_round
211 {
212 GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& x)
213 {
214 return detail::functor1<vec, L, T, T, Q>::call(round, x);
215 }
216 };
217
218 template<length_t L, typename T, qualifier Q, bool Aligned>
219 struct compute_mod
220 {
221 GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& a, vec<L, T, Q> const& b)
222 {
223 static_assert(std::numeric_limits<T>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'mod' only accept floating-point inputs. Include <glm/gtc/integer.hpp> for integer inputs.");
224 return a - b * floor(a / b);
225 }
226 };
227
228 template<length_t L, typename T, qualifier Q, bool Aligned>
229 struct compute_fma
230 {
231 GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& a, vec<L, T, Q> const& b, vec<L, T, Q> const& c)
232 {
233 return a * b + c;
234 }
235 };
236
237 template<length_t L, typename T, qualifier Q, bool Aligned>
238 struct compute_min_vector
239 {
240 GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& y)
241 {
242 return detail::functor2<vec, L, T, Q>::call(TMin<T>(), x, y);
243 }
244 };
245
246 template<length_t L, typename T, qualifier Q, bool Aligned>
247 struct compute_max_vector
248 {
249 GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& y)
250 {
251 return detail::functor2<vec, L, T, Q>::call(TMax<T>(), x, y);
252 }
253 };
254
255 template<length_t L, typename T, qualifier Q, bool Aligned>
256 struct compute_clamp_vector
257 {
258 GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<L, T, Q> call(vec<L, T, Q> const& x, vec<L, T, Q> const& minVal, vec<L, T, Q> const& maxVal)
259 {
260 return min(max(x, minVal), maxVal);
261 }
262 };
263
264 template<length_t L, typename T, qualifier Q, bool Aligned>
265 struct compute_step_vector
266 {
267 GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& edge, vec<L, T, Q> const& x)
268 {
269 return mix(vec<L, T, Q>(1), vec<L, T, Q>(0), glm::lessThan(x, edge));
270 }
271 };
272
273 template<length_t L, typename T, qualifier Q, bool Aligned>
274 struct compute_smoothstep_vector
275 {
276 GLM_FUNC_QUALIFIER static vec<L, T, Q> call(vec<L, T, Q> const& edge0, vec<L, T, Q> const& edge1, vec<L, T, Q> const& x)
277 {
278 static_assert(std::numeric_limits<T>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'smoothstep' only accept floating-point inputs");
279 vec<L, T, Q> const tmp(clamp((x - edge0) / (edge1 - edge0), static_cast<T>(0), static_cast<T>(1)));
280 return tmp * tmp * (static_cast<T>(3) - static_cast<T>(2) * tmp);
281 }
282 };
283
284 template<typename T, qualifier Q, bool Aligned>
285 struct convert_vec3_to_vec4W0
286 {
287 GLM_FUNC_QUALIFIER static vec<4, T, Q> call(vec<3, T, Q> const& a)
288 {
289 return vec<4, T, Q>(a.x, a.y, a.z, 0.0f);
290 }
291 };
292
293 template<typename T, qualifier Q, bool Aligned>
294 struct convert_vec3_to_vec4WZ
295 {
296 GLM_FUNC_QUALIFIER static vec<4, T, Q> call(vec<3, T, Q> const& a)
297 {
298 return vec<4, T, Q>(a.x, a.y, a.z, a.z);
299 }
300 };
301
302 template<typename T, qualifier Q, bool Aligned>
303 struct convert_vec3_to_vec4W1
304 {
305 GLM_FUNC_QUALIFIER static vec<4, T, Q> call(vec<3, T, Q> const& a)
306 {
307 return vec<4, T, Q>(a.x, a.y, a.z, 1.0f);
308 }
309 };
310
311 template<typename T, qualifier Q, bool Aligned>
312 struct convert_vec4_to_vec3
313 {
314 GLM_FUNC_QUALIFIER static vec<3, T, Q> call(vec<4, T, Q> const& a)
315 {
316 return vec<3, T, Q>(a.x, a.y, a.z);
317 }
318 };
319
320 template<length_t L, typename T, qualifier Q, bool Aligned>
321 struct convert_splat {
322 template<int c>
323 GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<L, T, Q> call(vec<L, T, Q> const& a)
324 {
325 vec<L, T, Q> v(T(0));
326 for (int i = 0; i < L; ++i)
327 v[i] = a[c];
328 return v;
329 }
330 };
331
332
333}//namespace detail
334
335 template<typename genFIType>
336 GLM_FUNC_QUALIFIER GLM_CONSTEXPR genFIType abs(genFIType x)
337 {
338 return detail::compute_abs<genFIType, std::numeric_limits<genFIType>::is_signed>::call(x);
339 }
340
341 template<length_t L, typename T, qualifier Q>
342 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> abs(vec<L, T, Q> const& x)
343 {
344 return detail::compute_abs_vector<L, T, Q, detail::is_aligned<Q>::value>::call(x);
345 }
346
347 // sign
348 // fast and works for any type
349 template<typename genFIType>
350 GLM_FUNC_QUALIFIER GLM_CONSTEXPR genFIType sign(genFIType x)
351 {
352 static_assert(
353 std::numeric_limits<genFIType>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || (std::numeric_limits<genFIType>::is_signed && std::numeric_limits<genFIType>::is_integer),
354 "'sign' only accept signed inputs");
355
356 return detail::compute_sign<1, genFIType, defaultp,
357 std::numeric_limits<genFIType>::is_iec559, detail::is_aligned<highp>::value>::call(vec<1, genFIType>(x)).x;
358 }
359
360 template<length_t L, typename T, qualifier Q>
361 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> sign(vec<L, T, Q> const& x)
362 {
363 static_assert(
364 std::numeric_limits<T>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || (std::numeric_limits<T>::is_signed && std::numeric_limits<T>::is_integer),
365 "'sign' only accept signed inputs");
366
367 return detail::compute_sign<L, T, Q, std::numeric_limits<T>::is_iec559, detail::is_aligned<Q>::value>::call(x);
368 }
369
370 // floor
371 using ::std::floor;
372 template<length_t L, typename T, qualifier Q>
373 GLM_FUNC_QUALIFIER vec<L, T, Q> floor(vec<L, T, Q> const& x)
374 {
375 static_assert(std::numeric_limits<T>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'floor' only accept floating-point inputs.");
376 return detail::compute_floor<L, T, Q, detail::is_aligned<Q>::value>::call(x);
377 }
378
379 template<length_t L, typename T, qualifier Q>
380 GLM_FUNC_QUALIFIER vec<L, T, Q> trunc(vec<L, T, Q> const& x)
381 {
382 static_assert(std::numeric_limits<T>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'trunc' only accept floating-point inputs");
383 return detail::compute_trunc<L, T, Q, detail::is_aligned<Q>::value>::call(x);
384 }
385
386 template<length_t L, typename T, qualifier Q>
387 GLM_FUNC_QUALIFIER vec<L, T, Q> round(vec<L, T, Q> const& x)
388 {
389 static_assert(std::numeric_limits<T>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'round' only accept floating-point inputs");
390 return detail::compute_round<L, T, Q, detail::is_aligned<Q>::value>::call(x);
391 }
392
393/*
394 // roundEven
395 template<typename genType>
396 GLM_FUNC_QUALIFIER genType roundEven(genType const& x)
397 {
398 static_assert(std::numeric_limits<genType>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'roundEven' only accept floating-point inputs");
399 return genType(int(x + genType(int(x) % 2)));
400 }
401*/
402
403 // roundEven
404 template<typename genType>
405 GLM_FUNC_QUALIFIER genType roundEven(genType x)
406 {
407 static_assert(std::numeric_limits<genType>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'roundEven' only accept floating-point inputs");
408
409 int Integer = static_cast<int>(x);
410 genType IntegerPart = static_cast<genType>(Integer);
411 genType FractionalPart = fract(x);
412
413 if(FractionalPart > static_cast<genType>(0.5) || FractionalPart < static_cast<genType>(0.5))
414 {
415 return round(x);
416 }
417 else if((Integer % 2) == 0)
418 {
419 return IntegerPart;
420 }
421 else if(x <= static_cast<genType>(0)) // Work around...
422 {
423 return IntegerPart - static_cast<genType>(1);
424 }
425 else
426 {
427 return IntegerPart + static_cast<genType>(1);
428 }
429 //else // Bug on MinGW 4.5.2
430 //{
431 // return mix(IntegerPart + genType(-1), IntegerPart + genType(1), x <= genType(0));
432 //}
433 }
434
435 template<length_t L, typename T, qualifier Q>
436 GLM_FUNC_QUALIFIER vec<L, T, Q> roundEven(vec<L, T, Q> const& x)
437 {
438 static_assert(std::numeric_limits<T>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'roundEven' only accept floating-point inputs");
439 return detail::functor1<vec, L, T, T, Q>::call(roundEven, x);
440 }
441
442 // ceil
443 using ::std::ceil;
444 template<length_t L, typename T, qualifier Q>
445 GLM_FUNC_QUALIFIER vec<L, T, Q> ceil(vec<L, T, Q> const& x)
446 {
447 static_assert(std::numeric_limits<T>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'ceil' only accept floating-point inputs");
448 return detail::compute_ceil<L, T, Q, detail::is_aligned<Q>::value>::call(x);
449 }
450
451 // fract
452 template<typename genType>
453 GLM_FUNC_QUALIFIER genType fract(genType x)
454 {
455 return fract(vec<1, genType>(x)).x;
456 }
457
458 template<length_t L, typename T, qualifier Q>
459 GLM_FUNC_QUALIFIER vec<L, T, Q> fract(vec<L, T, Q> const& x)
460 {
461 static_assert(std::numeric_limits<T>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'fract' only accept floating-point inputs");
462 return detail::compute_fract<L, T, Q, detail::is_aligned<Q>::value>::call(x);
463 }
464
465 // mod
466 template<typename genType>
467 GLM_FUNC_QUALIFIER genType mod(genType x, genType y)
468 {
469# if (GLM_COMPILER & GLM_COMPILER_CUDA) || (GLM_COMPILER & GLM_COMPILER_HIP)
470 // Another Cuda compiler bug https://github.com/g-truc/glm/issues/530
471 vec<1, genType, defaultp> Result(mod(vec<1, genType, defaultp>(x), y));
472 return Result.x;
473# else
474 return mod(vec<1, genType, defaultp>(x), y).x;
475# endif
476 }
477
478 template<length_t L, typename T, qualifier Q>
479 GLM_FUNC_QUALIFIER vec<L, T, Q> mod(vec<L, T, Q> const& x, T y)
480 {
481 return detail::compute_mod<L, T, Q, detail::is_aligned<Q>::value>::call(x, vec<L, T, Q>(y));
482 }
483
484 template<length_t L, typename T, qualifier Q>
485 GLM_FUNC_QUALIFIER vec<L, T, Q> mod(vec<L, T, Q> const& x, vec<L, T, Q> const& y)
486 {
487 return detail::compute_mod<L, T, Q, detail::is_aligned<Q>::value>::call(x, y);
488 }
489
490 template<length_t L, typename T, qualifier Q>
491 GLM_FUNC_QUALIFIER vec<L, T, Q> fma(vec<L, T, Q> const& a, vec<L, T, Q> const& b, vec<L, T, Q> const& c)
492 {
493 return detail::compute_fma<L, T, Q, detail::is_aligned<Q>::value>::call(a, b, c);
494 }
495
496 template<typename T, qualifier Q>
497 GLM_FUNC_QUALIFIER vec<4, T, Q> xyz0(vec<3, T, Q> const& a)
498 {
499 return detail::convert_vec3_to_vec4W0<T, Q, detail::is_aligned<Q>::value>::call(a);
500 }
501
502 template<typename T, qualifier Q>
503 GLM_FUNC_QUALIFIER vec<4, T, Q> xyz1(vec<3, T, Q> const& a)
504 {
505 return detail::convert_vec3_to_vec4W1<T, Q, detail::is_aligned<Q>::value>::call(a);
506 }
507
508 template<typename T, qualifier Q>
509 GLM_FUNC_QUALIFIER vec<4, T, Q> xyzz(vec<3, T, Q> const& a)
510 {
511 return detail::convert_vec3_to_vec4WZ<T, Q, detail::is_aligned<Q>::value>::call(a);
512 }
513
514 template<typename T, qualifier Q>
515 GLM_FUNC_QUALIFIER vec<3, T, Q> xyz(vec<4, T, Q> const& a)
516 {
517 return detail::convert_vec4_to_vec3<T, Q, detail::is_aligned<Q>::value>::call(a);
518 }
519
520 template<length_t L, typename T, qualifier Q>
521 GLM_FUNC_QUALIFIER vec<L, T, Q> splatX(vec<L, T, Q> const& a)
522 {
523 return detail::convert_splat<L, T, Q, detail::is_aligned<Q>::value>::template call<0>(a);
524 }
525
526 template<length_t L, typename T, qualifier Q>
527 GLM_FUNC_QUALIFIER vec<L, T, Q> splatY(vec<L, T, Q> const& a)
528 {
529 return detail::convert_splat<L, T, Q, detail::is_aligned<Q>::value>::template call<1>(a);
530 }
531
532 template<length_t L, typename T, qualifier Q>
533 GLM_FUNC_QUALIFIER vec<L, T, Q> splatZ(vec<L, T, Q> const& a)
534 {
535 return detail::convert_splat<L, T, Q, detail::is_aligned<Q>::value>::template call<2>(a);
536 }
537
538 template<length_t L, typename T, qualifier Q>
539 GLM_FUNC_QUALIFIER vec<L, T, Q> splatW(vec<L, T, Q> const& a)
540 {
541 return detail::convert_splat<L, T, Q, detail::is_aligned<Q>::value>::template call<3>(a);
542 }
543
544
545 // modf
546 template<typename genType>
547 GLM_FUNC_QUALIFIER genType modf(genType x, genType & i)
548 {
549 static_assert(std::numeric_limits<genType>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'modf' only accept floating-point inputs");
550 return std::modf(x, &i);
551 }
552
553 template<typename T, qualifier Q>
554 GLM_FUNC_QUALIFIER vec<1, T, Q> modf(vec<1, T, Q> const& x, vec<1, T, Q> & i)
555 {
556 return vec<1, T, Q>(
557 modf(x.x, i.x));
558 }
559
560 template<typename T, qualifier Q>
561 GLM_FUNC_QUALIFIER vec<2, T, Q> modf(vec<2, T, Q> const& x, vec<2, T, Q> & i)
562 {
563 return vec<2, T, Q>(
564 modf(x.x, i.x),
565 modf(x.y, i.y));
566 }
567
568 template<typename T, qualifier Q>
569 GLM_FUNC_QUALIFIER vec<3, T, Q> modf(vec<3, T, Q> const& x, vec<3, T, Q> & i)
570 {
571 return vec<3, T, Q>(
572 modf(x.x, i.x),
573 modf(x.y, i.y),
574 modf(x.z, i.z));
575 }
576
577 template<typename T, qualifier Q>
578 GLM_FUNC_QUALIFIER vec<4, T, Q> modf(vec<4, T, Q> const& x, vec<4, T, Q> & i)
579 {
580 return vec<4, T, Q>(
581 modf(x.x, i.x),
582 modf(x.y, i.y),
583 modf(x.z, i.z),
584 modf(x.w, i.w));
585 }
586
587 //// Only valid if (INT_MIN <= x-y <= INT_MAX)
588 //// min(x,y)
589 //r = y + ((x - y) & ((x - y) >> (sizeof(int) *
590 //CHAR_BIT - 1)));
591 //// max(x,y)
592 //r = x - ((x - y) & ((x - y) >> (sizeof(int) *
593 //CHAR_BIT - 1)));
594
595 // min
596 template<length_t L, typename T, qualifier Q>
597 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> min(vec<L, T, Q> const& a, T b)
598 {
599 static_assert(std::numeric_limits<T>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || std::numeric_limits<T>::is_integer, "'min' only accept floating-point or integer inputs");
600 return detail::compute_min_vector<L, T, Q, detail::is_aligned<Q>::value>::call(a, vec<L, T, Q>(b));
601 }
602
603 template<length_t L, typename T, qualifier Q>
604 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> min(vec<L, T, Q> const& a, vec<L, T, Q> const& b)
605 {
606 return detail::compute_min_vector<L, T, Q, detail::is_aligned<Q>::value>::call(a, b);
607 }
608
609 // max
610 template<length_t L, typename T, qualifier Q>
611 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> max(vec<L, T, Q> const& a, T b)
612 {
613 static_assert(std::numeric_limits<T>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || std::numeric_limits<T>::is_integer, "'max' only accept floating-point or integer inputs");
614 return detail::compute_max_vector<L, T, Q, detail::is_aligned<Q>::value>::call(a, vec<L, T, Q>(b));
615 }
616
617 template<length_t L, typename T, qualifier Q>
618 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> max(vec<L, T, Q> const& a, vec<L, T, Q> const& b)
619 {
620 return detail::compute_max_vector<L, T, Q, detail::is_aligned<Q>::value>::call(a, b);
621 }
622
623 // clamp
624 template<typename genType>
625 GLM_FUNC_QUALIFIER GLM_CONSTEXPR genType clamp(genType x, genType minVal, genType maxVal)
626 {
627 static_assert(std::numeric_limits<genType>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || std::numeric_limits<genType>::is_integer, "'clamp' only accept floating-point or integer inputs");
628 return min(max(x, minVal), maxVal);
629 }
630
631 template<length_t L, typename T, qualifier Q>
632 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> clamp(vec<L, T, Q> const& x, T minVal, T maxVal)
633 {
634 static_assert(std::numeric_limits<T>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || std::numeric_limits<T>::is_integer, "'clamp' only accept floating-point or integer inputs");
635 return detail::compute_clamp_vector<L, T, Q, detail::is_aligned<Q>::value>::call(x, vec<L, T, Q>(minVal), vec<L, T, Q>(maxVal));
636 }
637
638 template<length_t L, typename T, qualifier Q>
639 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> clamp(vec<L, T, Q> const& x, vec<L, T, Q> const& minVal, vec<L, T, Q> const& maxVal)
640 {
641 static_assert(std::numeric_limits<T>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || std::numeric_limits<T>::is_integer, "'clamp' only accept floating-point or integer inputs");
642 return detail::compute_clamp_vector<L, T, Q, detail::is_aligned<Q>::value>::call(x, minVal, maxVal);
643 }
644
645 template<typename genTypeT, typename genTypeU>
646 GLM_FUNC_QUALIFIER GLM_CONSTEXPR genTypeT mix(genTypeT x, genTypeT y, genTypeU a)
647 {
648 return detail::compute_mix<genTypeT, genTypeU>::call(x, y, a);
649 }
650
651 template<length_t L, typename T, typename U, qualifier Q>
652 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> mix(vec<L, T, Q> const& x, vec<L, T, Q> const& y, U a)
653 {
654 return detail::compute_mix_scalar<L, T, U, Q, detail::is_aligned<Q>::value>::call(x, y, a);
655 }
656
657 template<length_t L, typename T, typename U, qualifier Q>
658 GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<L, T, Q> mix(vec<L, T, Q> const& x, vec<L, T, Q> const& y, vec<L, U, Q> const& a)
659 {
660 return detail::compute_mix_vector<L, T, U, Q, detail::is_aligned<Q>::value>::call(x, y, a);
661 }
662
663 // step
664 template<typename genType>
665 GLM_FUNC_QUALIFIER genType step(genType edge, genType x)
666 {
667 return mix(static_cast<genType>(1), static_cast<genType>(0), x < edge);
668 }
669
670 template<length_t L, typename T, qualifier Q>
671 GLM_FUNC_QUALIFIER vec<L, T, Q> step(T edge, vec<L, T, Q> const& x)
672 {
673 return detail::compute_step_vector<L, T, Q, detail::is_aligned<Q>::value>::call(vec<L, T, Q>(edge), x);
674 }
675
676 template<length_t L, typename T, qualifier Q>
677 GLM_FUNC_QUALIFIER vec<L, T, Q> step(vec<L, T, Q> const& edge, vec<L, T, Q> const& x)
678 {
679 return detail::compute_step_vector<L, T, Q, detail::is_aligned<Q>::value>::call(edge, x);
680 }
681
682 // smoothstep
683 template<typename genType>
684 GLM_FUNC_QUALIFIER genType smoothstep(genType edge0, genType edge1, genType x)
685 {
686 static_assert(std::numeric_limits<genType>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT || GLM_CONFIG_UNRESTRICTED_GENTYPE, "'smoothstep' only accept floating-point inputs");
687
688 genType const tmp(clamp((x - edge0) / (edge1 - edge0), genType(0), genType(1)));
689 return tmp * tmp * (genType(3) - genType(2) * tmp);
690 }
691
692 template<length_t L, typename T, qualifier Q>
693 GLM_FUNC_QUALIFIER vec<L, T, Q> smoothstep(T edge0, T edge1, vec<L, T, Q> const& x)
694 {
695 return detail::compute_smoothstep_vector<L, T, Q, detail::is_aligned<Q>::value>::call(vec<L, T, Q>(edge0), vec<L, T, Q>(edge1), x);
696 }
697
698 template<length_t L, typename T, qualifier Q>
699 GLM_FUNC_QUALIFIER vec<L, T, Q> smoothstep(vec<L, T, Q> const& edge0, vec<L, T, Q> const& edge1, vec<L, T, Q> const& x)
700 {
701 return detail::compute_smoothstep_vector<L, T, Q, detail::is_aligned<Q>::value>::call(edge0, edge1, x);
702 }
703
704 using std::isnan;
705
706 template<length_t L, typename T, qualifier Q>
707 GLM_FUNC_QUALIFIER vec<L, bool, Q> isnan(vec<L, T, Q> const& v)
708 {
709 static_assert(std::numeric_limits<T>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'isnan' only accept floating-point inputs");
710
711 vec<L, bool, Q> Result(0);
712 for (length_t l = 0; l < v.length(); ++l)
713 Result[l] = glm::isnan(v[l]);
714 return Result;
715 }
716
717 using std::isinf;
718
719 template<length_t L, typename T, qualifier Q>
720 GLM_FUNC_QUALIFIER vec<L, bool, Q> isinf(vec<L, T, Q> const& v)
721 {
722 static_assert(std::numeric_limits<T>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'isinf' only accept floating-point inputs");
723
724 vec<L, bool, Q> Result(0);
725 for (length_t l = 0; l < v.length(); ++l)
726 Result[l] = glm::isinf(v[l]);
727 return Result;
728 }
729
730 GLM_FUNC_QUALIFIER int floatBitsToInt(float v)
731 {
732 union
733 {
734 float in;
735 int out;
736 } u;
737
738 u.in = v;
739
740 return u.out;
741 }
742
743 template<length_t L, qualifier Q>
744 GLM_FUNC_QUALIFIER vec<L, int, Q> floatBitsToInt(vec<L, float, Q> const& v)
745 {
746 return detail::functor1<vec, L, int, float, Q>::call(floatBitsToInt, v);
747 }
748
749 GLM_FUNC_QUALIFIER uint floatBitsToUint(float v)
750 {
751 union
752 {
753 float in;
754 uint out;
755 } u;
756
757 u.in = v;
758
759 return u.out;
760 }
761
762 template<length_t L, qualifier Q>
763 GLM_FUNC_QUALIFIER vec<L, uint, Q> floatBitsToUint(vec<L, float, Q> const& v)
764 {
765 return detail::functor1<vec, L, uint, float, Q>::call(floatBitsToUint, v);
766 }
767
768 GLM_FUNC_QUALIFIER float intBitsToFloat(int v)
769 {
770 union
771 {
772 int in;
773 float out;
774 } u;
775
776 u.in = v;
777
778 return u.out;
779 }
780
781 template<length_t L, qualifier Q>
782 GLM_FUNC_QUALIFIER vec<L, float, Q> intBitsToFloat(vec<L, int, Q> const& v)
783 {
784 return detail::functor1<vec, L, float, int, Q>::call(intBitsToFloat, v);
785 }
786
787 GLM_FUNC_QUALIFIER float uintBitsToFloat(uint v)
788 {
789 union
790 {
791 uint in;
792 float out;
793 } u;
794
795 u.in = v;
796
797 return u.out;
798 }
799
800 template<length_t L, qualifier Q>
801 GLM_FUNC_QUALIFIER vec<L, float, Q> uintBitsToFloat(vec<L, uint, Q> const& v)
802 {
803 return reinterpret_cast<vec<L, float, Q>&>(const_cast<vec<L, uint, Q>&>(v));
804 }
805
806 using std::fma;
807
808 template<typename genType>
809 GLM_FUNC_QUALIFIER genType frexp(genType x, int& exp)
810 {
811 static_assert(std::numeric_limits<genType>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'frexp' only accept floating-point inputs");
812
813 return std::frexp(x, &exp);
814 }
815
816 template<length_t L, typename T, qualifier Q>
817 GLM_FUNC_QUALIFIER vec<L, T, Q> frexp(vec<L, T, Q> const& v, vec<L, int, Q>& exp)
818 {
819 static_assert(std::numeric_limits<T>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'frexp' only accept floating-point inputs");
820
821 vec<L, T, Q> Result(0);
822 for (length_t l = 0; l < v.length(); ++l)
823 Result[l] = std::frexp(v[l], &exp[l]);
824 return Result;
825 }
826
827 template<typename genType>
828 GLM_FUNC_QUALIFIER genType ldexp(genType const& x, int const& exp)
829 {
830 static_assert(std::numeric_limits<genType>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'ldexp' only accept floating-point inputs");
831
832 return std::ldexp(x, exp);
833 }
834
835 template<length_t L, typename T, qualifier Q>
836 GLM_FUNC_QUALIFIER vec<L, T, Q> ldexp(vec<L, T, Q> const& v, vec<L, int, Q> const& exp)
837 {
838 static_assert(std::numeric_limits<T>::is_iec559 || GLM_CONFIG_UNRESTRICTED_FLOAT, "'ldexp' only accept floating-point inputs");
839
840 vec<L, T, Q> Result(0);
841 for (length_t l = 0; l < v.length(); ++l)
842 Result[l] = std::ldexp(v[l], exp[l]);
843 return Result;
844 }
845}//namespace glm
846
847#if GLM_CONFIG_SIMD == GLM_ENABLE
848# include "func_common_simd.inl"
849#endif