glm/builtin/common.rs
1//
2// GLSL Mathematics for Rust.
3//
4// Copyright (c) 2015, 2025 The glm-rs authors.
5//
6// Permission is hereby granted, free of charge, to any person obtaining a copy
7// of this software and associated documentation files (the "Software"), to deal
8// in the Software without restriction, including without limitation the rights
9// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10// copies of the Software, and to permit persons to whom the Software is
11// furnished to do so, subject to the following conditions:
12//
13// The above copyright notice and this permission notice shall be included in
14// all copies or substantial portions of the Software.
15//
16// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22// THE SOFTWARE.
23
24// The GLSL Specification, ch 8.3, Common Functions.
25
26use core::mem;
27use core::ops::Rem;
28
29use num_traits::{Float, Zero};
30
31use crate::basenum::*;
32use crate::traits::*;
33use crate::vec::traits::{GenFloatVec, GenNumVec, GenVec};
34use crate::vec::vec::{Vector2, Vector3, Vector4};
35
36pub trait FloatIntRel<E: BaseFloat, I: BaseInt, GI: GenInt<I>>: GenFloat<E> {
37 // float -> int
38 fn map_int<F: Fn(E) -> I>(&self, fun: F) -> GI;
39 // (float) -> (float, int)
40 fn split_int<F: Fn(E) -> (E, I)>(&self, fun: F) -> (Self, GI);
41}
42
43pub trait IntFloatRel<I: BaseInt, E: BaseFloat, GF: GenFloat<E>>: GenInt<I> {
44 // int -> float
45 fn map_flt<F: Fn(I) -> E>(&self, fun: F) -> GF;
46 // (int, float) -> float
47 fn zip_flt<F: Fn(I, E) -> E>(&self, f: &GF, fun: F) -> GF;
48}
49
50pub trait NumBoolRel<N: BaseNum, B: GenBType>: GenNum<N> {
51 // num -> bool
52 fn map_bool<F: Fn(N) -> bool>(&self, fun: F) -> B;
53 // (num, bool) -> num
54 fn zip_bool<F: Fn(N, bool) -> N>(&self, b: &B, fun: F) -> Self;
55}
56
57macro_rules! impl_scalar_FloatIntRel {
58 ($($t: ident),+) => {
59 $(
60 impl<I: BaseInt + GenInt<I>> FloatIntRel<$t, I, I> for $t {
61 #[inline(always)]
62 fn map_int<F: Fn($t) -> I>(&self, fun: F) -> I {
63 fun(*self)
64 }
65 #[inline(always)]
66 fn split_int<F: Fn($t) -> ($t, I)>(&self, fun: F) -> ($t, I) {
67 fun(*self)
68 }
69 }
70 )+
71 }
72}
73
74impl_scalar_FloatIntRel! { f32, f64 }
75
76macro_rules! impl_vec_FloatIntRel {
77 ($({ $t: ident, $($field: ident),+ }),+) => {
78 $(
79 impl<E: BaseFloat, I: BaseInt> FloatIntRel<E, I, $t<I>> for $t<E> {
80 #[inline]
81 fn map_int<F: Fn(E) -> I>(&self, fun: F) -> $t<I> {
82 $t::new($(fun(self.$field)),+)
83 }
84 #[inline]
85 fn split_int<F: Fn(E) -> (E, I)>(&self, fun: F) -> ($t<E>, $t<I>) {
86 let mut f = $t::<E>::zero();
87 let mut i = $t::<I>::zero();
88 let dim = $t::<E>::dim();
89 for j in 0..dim {
90 let (a, b) = fun(self[j]);
91 f[j] = a;
92 i[j] = b;
93 }
94 (f, i)
95 }
96 }
97 )+
98 }
99}
100
101impl_vec_FloatIntRel! {
102 { Vector2, x, y },
103 { Vector3, x, y, z },
104 { Vector4, x, y, z, w }
105}
106
107macro_rules! impl_scalar_IntFloatRel {
108 ($($t: ident),+) => {
109 $(
110 impl<E: BaseFloat + GenFloat<E>> IntFloatRel<$t, E, E> for $t {
111 #[inline]
112 fn map_flt<F: Fn($t) -> E>(&self, fun: F) -> E {
113 fun(*self)
114 }
115 #[inline]
116 fn zip_flt<F: Fn($t, E) -> E>(&self, f: &E, fun: F) -> E {
117 fun(*self, *f)
118 }
119 }
120 )+
121 }
122}
123
124impl_scalar_IntFloatRel! { i32, u32 }
125
126macro_rules! impl_vec_IntFloatRel {
127 ($({ $t: ident, $($field: ident),+ }),+) => {
128 $(
129 impl<I: BaseInt, E: BaseFloat> IntFloatRel<I, E, $t<E>> for $t<I> {
130 #[inline]
131 fn map_flt<F: Fn(I) -> E>(&self, fun: F) -> $t<E> {
132 $t::new($(fun(self.$field)),+)
133 }
134 #[inline]
135 fn zip_flt<F: Fn(I, E) -> E>(&self, f: &$t<E>, fun: F) -> $t<E> {
136 $t::new($(fun(self.$field, f.$field)),+)
137 }
138 }
139 )+
140 }
141}
142
143impl_vec_IntFloatRel! {
144 { Vector2, x, y },
145 { Vector3, x, y, z },
146 { Vector4, x, y, z, w }
147}
148
149macro_rules! impl_scalar_NumBoolRel {
150 ($($t: ident),+) => {
151 $(
152 impl NumBoolRel<$t, bool> for $t {
153 #[inline]
154 fn map_bool<F: Fn($t) -> bool>(&self, fun: F) -> bool {
155 fun(*self)
156 }
157 #[inline]
158 fn zip_bool<F: Fn($t, bool) -> $t>(&self, b: &bool, fun: F) -> $t {
159 fun(*self, *b)
160 }
161 }
162 )+
163 }
164}
165
166impl_scalar_NumBoolRel! { i32, u32, f32, f64 }
167
168macro_rules! impl_vec_NumBoolRel {
169 ($({ $t: ident, $($field: ident),+ }),+) => {
170 $(
171 impl<N: BaseNum> NumBoolRel<N, $t<bool>> for $t<N> {
172 #[inline]
173 fn map_bool<F: Fn(N) -> bool>(&self, fun: F) -> $t<bool> {
174 $t::new($(fun(self.$field)),+)
175 }
176 #[inline]
177 fn zip_bool<F: Fn(N, bool) -> N>(&self, b: &$t<bool>, fun: F) -> $t<N> {
178 $t::new($(fun(self.$field, b.$field)),+)
179 }
180 }
181 )+
182 }
183}
184
185impl_vec_NumBoolRel! {
186 { Vector2, x, y },
187 { Vector3, x, y, z },
188 { Vector4, x, y, z, w }
189}
190
191/// Returns `x` if `x ≥ 0`, otherwise it returns `–x`.
192///
193/// # Example
194///
195/// ```
196/// use glm::{ abs, dvec4, SignedNum };
197///
198/// assert_eq!(abs(-1_f32), 1.);
199/// let v4 = dvec4(0., 100., -2., -3.);
200/// assert_eq!(abs(v4), v4.abs());
201/// assert_eq!(abs(v4), dvec4(0., 100., 2., 3.));
202/// ```
203#[inline(always)]
204pub fn abs<S: SignedNum + BaseNum, T: GenNum<S>>(x: T) -> T {
205 x.map(|s: S| SignedNum::abs(&s))
206}
207
208/// Returns `1.0` if `x > 0`, `0.0` if `x = 0`, or `–1.0` if `x < 0`.
209///
210/// # Example
211///
212/// ```
213/// use glm::{ sign, vec3 };
214///
215/// assert_eq!(sign(-0_f32), 0.);
216/// assert_eq!(sign(vec3(-100., 2., 0.)), vec3(-1., 1., 0.));
217/// ```
218#[inline(always)]
219pub fn sign<S: SignedNum + BaseNum, T: GenNum<S>>(x: T) -> T {
220 x.map(|s: S| SignedNum::sign(&s))
221}
222
223/// Returns a value equal to the nearest integer that is less than or
224/// equal to `x`.
225///
226/// # Example
227///
228/// ```
229/// assert_eq!(glm::floor(-3.14_f32), -4.);
230/// assert_eq!(glm::floor(glm::vec3(-1.7, 4., 4.9)), glm::vec3(-2., 4., 4.));
231/// ```
232#[inline(always)]
233pub fn floor<F: BaseFloat, T: GenFloat<F>>(x: T) -> T {
234 x.map(Float::floor)
235}
236
237/// Returns a value equal to the nearest integer to `x` whose absolute value
238/// is not larger than the absolute value of `x`.
239///
240/// # Example
241///
242/// ```
243/// assert_eq!(glm::trunc(-3.14_f32), -3.);
244/// assert_eq!(glm::trunc(glm::vec3(-1.7, 4., 4.9)), glm::vec3(-1., 4., 4.));
245/// ```
246#[inline(always)]
247pub fn trunc<F: BaseFloat, T: GenFloat<F>>(x: T) -> T {
248 x.map(Float::trunc)
249}
250
251/// Returns a value equal to the nearest integer to `x`.
252///
253/// The fraction `0.5` will round in a direction chosen by the implementation,
254/// presumably the direction that is fastest. This includes the possibility
255/// that `round(x)` returns the same value as `roundEven(x)` for all values of
256/// `x`.
257///
258/// # Example
259///
260/// ```
261/// use glm::{ round, vec3 };
262///
263/// assert_eq!(round(-3.14_f32), -3.);
264/// assert_eq!(round(vec3(-1.7, 4., 4.9)), vec3(-2., 4., 5.));
265/// ```
266#[inline(always)]
267pub fn round<F: BaseFloat, T: GenFloat<F>>(x: T) -> T {
268 x.map(Float::round)
269}
270
271/// Returns a value equal to the nearest integer to `x`.
272///
273/// A fractional part of `0.5` will round toward the nearest even integer.
274/// (Both `3.5` and `4.5` for x will return `4.0`.)
275///
276/// # Example
277///
278/// ```
279/// use glm::{ roundEven, vec4 };
280///
281/// assert_eq!(roundEven(2.5_f32), 2.);
282/// assert_eq!(roundEven(1.5_f32), 2.);
283/// assert_eq!(roundEven(vec4(3.14, -3.14, -1.5, -2.5)), vec4(3., -3., -2., -2.));
284/// ```
285#[inline(always)]
286#[allow(non_snake_case)]
287pub fn roundEven<F: BaseFloat, T: GenFloat<F>>(x: T) -> T {
288 x.map(|f| -> F {
289 let ling = F::zero();
290 let yi = F::one();
291 let er = yi + yi;
292
293 let int = f.trunc();
294 if f.fract().abs() != F::from(0.5).unwrap() {
295 f.round()
296 } else if int % er == ling {
297 int
298 } else if int < ling {
299 int - yi
300 } else {
301 int + yi
302 }
303 })
304}
305
306/// Returns a value equal to the nearest integer that is greater than or
307/// equal to `x`.
308///
309/// # Example
310///
311/// ```
312/// use glm::{ ceil, dvec3 };
313///
314/// assert_eq!(ceil(-3.14_f32), -3.);
315/// assert_eq!(ceil(3.14_f32), 4.);
316/// assert_eq!(ceil(dvec3(-1.8, 1., 1.8)), dvec3(-1., 1., 2.));
317/// ```
318#[inline(always)]
319pub fn ceil<F: BaseFloat, T: GenFloat<F>>(x: T) -> T {
320 x.map(Float::ceil)
321}
322
323/// Returns `x – floor(x)`.
324///
325/// # Example
326///
327/// ```
328/// use glm::{ fract, vec2 };
329///
330/// assert_eq!(fract(3.25_f32), 0.25);
331/// assert_eq!(fract(vec2(-1.5, 1.)), vec2(-0.5, 0.));
332/// ```
333#[inline(always)]
334pub fn fract<F: BaseFloat, T: GenFloat<F>>(x: T) -> T {
335 x.map(Float::fract)
336}
337
338/// Modulus. Returns `x – y ∗ floor(x/y)`.
339///
340/// # Note
341///
342/// Original function name `mod` is renamed to `fmod` because **mod** is
343/// a keyword in Rust.
344///
345/// # Example
346///
347/// ```
348/// assert_eq!(glm::fmod(3.5_f32, 3.), 0.5);
349/// ```
350#[inline(always)]
351pub fn fmod<F: BaseFloat, T: GenFloat<F>>(x: T, y: T) -> T {
352 x.zip(y, Rem::rem)
353}
354
355/// Modulus with a scalar number.
356///
357/// # Note
358///
359/// `mod_s` is not a GLSL function name. It is a variant of original `mod`
360/// function and is introduced because Rust does not support function name
361/// overloading.
362///
363/// # Example
364///
365/// ```
366/// use glm::{ mod_s, dvec3 };
367///
368/// let v = dvec3(-1.5, 1.5, 10.5);
369/// assert_eq!(mod_s(v, 2.), dvec3(-1.5, 1.5, 0.5));
370/// ```
371#[inline(always)]
372pub fn mod_s<F: BaseFloat, T: GenFloatVec<F>>(x: T, y: F) -> T {
373 x.map(|f| -> F { f.rem(y) })
374}
375
376/// Returns the fractional and integer parts of `x`.
377///
378/// Both parts will have the same sign as `x`.
379///
380/// # Note
381///
382/// In GLSL, the integer part is returned via a output parameter `i`.
383/// In Rust we can return both parts using a tuple *(interger part, fractional part)*.
384///
385/// # Example
386///
387/// ```
388/// use glm::{ modf, vec3 };
389///
390/// assert_eq!(modf(1.5_f32), (1., 0.5));
391/// assert_eq!(modf(vec3(0., -1.25, 3.75)), (vec3(0., -1., 3.), vec3(0., -0.25, 0.75)));
392/// ```
393#[inline(always)]
394pub fn modf<F: BaseFloat, T: GenFloat<F>>(x: T) -> (T, T) {
395 (trunc(x), fract(x))
396}
397
398/// Returns `y` if `y < x`, otherwise it returns `x`.
399///
400/// # Example
401///
402/// ```
403/// let v1 = glm::vec2(1., 4.);
404/// let v2 = glm::vec2(2., 3.);
405/// assert_eq!(glm::min(v1, v2), glm::vec2(1., 3.));
406/// ```
407#[inline(always)]
408pub fn min<S: BaseNum, T: GenNum<S>>(x: T, y: T) -> T {
409 x.zip(y, BaseNum::min)
410}
411
412/// A variant of function `min` that uses a scalar value as comparator.
413///
414/// # Note
415///
416/// `mod_s` is not a GLSL function name.
417///
418/// # Example
419///
420/// ```
421/// let v = glm::vec2(1., 3.);
422/// let y = 2_f32;
423/// assert_eq!(glm::min_s(v, y), glm::vec2(1., 2.));
424/// ```
425#[inline(always)]
426pub fn min_s<S: BaseNum, T: GenNumVec<S>>(x: T, y: S) -> T {
427 x.map(|c| -> S { BaseNum::min(c, y) })
428}
429
430/// Returns `y` if `x < y`, otherwise it returns `x`.
431///
432/// # Example
433///
434/// ```
435/// let v1 = glm::vec2(1., 4.);
436/// let v2 = glm::vec2(2., 3.);
437/// assert_eq!(glm::max(v1, v2), glm::vec2(2., 4.));
438/// ```
439#[inline(always)]
440pub fn max<S: BaseNum, T: GenNum<S>>(x: T, y: T) -> T {
441 x.zip(y, BaseNum::max)
442}
443
444/// A variant of `max` that always uses a scalar value as the comparator.
445///
446/// # Note
447///
448/// `max_s` is not a GLSL function name. It is introduced because Rust does
449/// not support function name overloading.
450///
451/// # Example
452///
453/// ```
454/// let v = glm::vec2(1., 3.);
455/// let y = 2_f32;
456/// assert_eq!(glm::max_s(v, y), glm::vec2(2., 3.));
457/// ```
458#[inline(always)]
459pub fn max_s<S: BaseNum, T: GenNumVec<S>>(x: T, y: S) -> T {
460 x.map(|s| -> S { BaseNum::max(s, y) })
461}
462
463/// Returns `min (max (x, min_val), max_val)`.
464///
465/// # Example
466///
467/// ```
468/// use glm::{ clamp, vec3 };
469///
470/// assert_eq!(clamp(3.14_f32, 0., 1.), 1.);
471/// let v = vec3(-1., 0., 100.);
472/// let min = vec3(0., 0., 0.);
473/// let max = vec3(1., 1., 1.);
474/// assert_eq!(clamp(v, min, max), vec3(0., 0., 1.));
475/// ```
476#[inline(always)]
477pub fn clamp<S: BaseNum, T: GenNum<S>>(x: T, min_val: T, max_val: T) -> T {
478 min(max(x, min_val), max_val)
479}
480
481/// A variant of function `clamp` that uses scalar values as thresholds.
482///
483/// # Note
484///
485/// `clamp_s` is not a GLSL function name.
486///
487/// # Example
488///
489/// ```
490/// use glm::{ clamp_s, dvec2 };
491///
492/// let dv2 = dvec2(-1., 3.14);
493/// assert_eq!(clamp_s(dv2, 0., 1.), dvec2(0., 1.));
494/// ```
495#[inline(always)]
496pub fn clamp_s<S: BaseNum, T: GenNumVec<S>>(x: T, min_val: S, max_val: S) -> T {
497 min_s(max_s(x, min_val), max_val)
498}
499
500/// Returns the linear blend of `x` and `y`, i.e., `x⋅(1−a)+y⋅a`.
501///
502/// # Example
503///
504/// ```
505/// use glm::{ mix, vec2 };
506///
507/// assert_eq!(mix(0_f32, 1_f32, 0.5), 0.5);
508/// let x = vec2(1., 2.);
509/// let y = vec2(3., 4.);
510/// let a = vec2(0.5, 2.);
511/// let r = vec2(2., 6.);
512/// assert_eq!(mix(x, y, a), r);
513/// ```
514#[inline(always)]
515pub fn mix<F: BaseFloat, T: GenFloat<F>>(x: T, y: T, a: T) -> T {
516 let yi = T::one();
517 x * (yi - a) + y * a
518}
519
520/// A variant of function `mix` that parameter `a` is a scalar.
521///
522/// # Note
523///
524/// `mix_s` is not a GLSL function name. It is introduced because Rust does
525/// not support function name overloading.
526///
527/// # Example
528///
529/// ```
530/// use glm::{ mix_s, dvec3 };
531///
532/// let x = dvec3(10., 20., 30.);
533/// let y = dvec3(100., 200., 300.);
534/// assert_eq!(mix_s(x, y, 0.5), dvec3(55., 110., 165.));
535/// ```
536#[inline(always)]
537pub fn mix_s<F: BaseFloat, T: GenFloatVec<F>>(x: T, y: T, a: F) -> T {
538 let yi = F::one();
539 x * (yi - a) + y * a
540}
541
542/// Selects which vector each returned component comes from.
543///
544/// For a component of `a` that is `false`, the corresponding component of `x`
545/// is returned. For a component of `a` that is `true`, the corresponding
546/// component of `y` is returned. Components of `x` and `y` that are not
547/// selected are allowed to be invalid floating point values and will have no
548/// effect on the results.
549///
550/// # Note
551///
552/// 1. `mix_bool` is not a GLSL function name. It is a variant of `mix`
553/// function and is introduced becasue Rust does not support function name
554/// overloading.
555/// 1. This function works for scalar types too.
556///
557/// # Example
558///
559/// ```
560/// use glm::{ bvec4, dvec4, mix_bool };
561///
562/// let a = bvec4(true, false, false, true);
563/// let x = dvec4(1., 1., 1., 1.);
564/// let y = dvec4(2., 2., 2., 2.);
565/// assert_eq!(mix_bool(x, y, a), dvec4(2., 1., 1., 2.));
566/// // works for scalars too.
567/// assert_eq!(mix_bool(1_f32, 2., false), 1.);
568/// ```
569#[inline(always)]
570pub fn mix_bool<F: BaseFloat, B: GenBType, T: NumBoolRel<F, B>>(x: T, y: T, a: B) -> T {
571 let ling = F::zero();
572 x.zip_bool(&a, |f, b| -> F {
573 if b {
574 ling
575 } else {
576 f
577 }
578 }) + y.zip_bool(&a, |f, b| -> F {
579 if b {
580 f
581 } else {
582 ling
583 }
584 })
585}
586
587/// Returns `0.0` if `x` < `edge`, otherwise it returns `1.0`.
588///
589/// # Example
590///
591/// ```
592/// use glm::{ step, dvec2 };
593/// assert_eq!(step(1f32, 1.), 1.);
594/// assert_eq!(step(dvec2(1., 2.), dvec2(2., 1.)), dvec2(1., 0.));
595/// ```
596#[inline(always)]
597pub fn step<F: BaseFloat, T: GenFloat<F>>(edge: T, x: T) -> T {
598 x.zip(edge, |f, e| -> F {
599 if f < e {
600 F::zero()
601 } else {
602 F::one()
603 }
604 })
605}
606
607/// A variant of `step` function that use scalar as the edge.
608///
609/// # Note
610///
611/// `step_s` is not a GLSL function name.
612///
613/// # Example
614///
615/// ```
616/// use glm::{ step_s, vec3 };
617///
618/// assert_eq!(step_s(0_f32, vec3(-1., 0., 1.)), vec3(0., 1., 1.));
619/// ```
620#[inline(always)]
621pub fn step_s<F: BaseFloat, T: GenFloatVec<F>>(edge: F, x: T) -> T {
622 x.map(|f| -> F {
623 if f < edge {
624 F::zero()
625 } else {
626 F::one()
627 }
628 })
629}
630
631/// Returns `0.0` if `x ≤ edge0` and `1.0` if `x ≥ edge1` and performs
632/// smooth Hermite interpolation between 0 and 1 when `edge0 < x < edge1`.
633///
634/// This is useful in cases where you would want a threshold function with
635/// a smooth transition.
636///
637/// Results are undefined if `edge0 ≥ edge1`.
638///
639/// # Example
640///
641/// ```
642/// use glm::{ smoothstep, dvec2 };
643///
644/// assert_eq!(smoothstep(0f32, 1., -1.), 0.);
645/// let e0 = dvec2(0., -100.);
646/// let e1 = dvec2(1., 100.);
647/// let v = dvec2(1., 50.);
648/// assert_eq!(smoothstep(e0, e1, v), dvec2(1., 0.84375));
649/// ```
650#[inline]
651pub fn smoothstep<F: BaseFloat, T: GenFloat<F>>(edge0: T, edge1: T, x: T) -> T {
652 let ling = T::zero();
653 let yi = T::one();
654 let er = yi + yi;
655 let san = er + yi;
656
657 let t = clamp((x - edge0) / (edge1 - edge0), ling, yi);
658 t * t * (t * -er + san)
659}
660
661/// A variant of `smoothstep` function that use scalar as edges.
662///
663/// # Note
664///
665/// `smoothstep_s` is not a GLSL function name.
666#[inline]
667pub fn smoothstep_s<F: BaseFloat + GenNum<F>, T: GenFloatVec<F>>(edge0: F, edge1: F, x: T) -> T {
668 let ling = F::zero();
669 let yi = F::one();
670 let er = yi + yi;
671 let san = er + yi;
672
673 x.map(|f| -> F {
674 let t = clamp((f - edge0) / (edge1 - edge0), ling, yi);
675 t * t * (san - er * t)
676 })
677}
678
679/// Returns `true` if `x` holds a *NaN*. Returns `false` otherwise.
680///
681/// # Example
682///
683/// ```
684/// # fn main() {
685/// use glm::{ bvec3, dvec3, isnan };
686/// use num_traits::Float;
687///
688/// let nan: f64 = Float::nan();
689/// assert!(isnan(nan));
690/// assert_eq!(isnan(dvec3(nan, 1., -0.)), bvec3(true, false, false));
691/// # }
692/// ```
693#[inline(always)]
694pub fn isnan<F: BaseFloat, B: GenBType, T: NumBoolRel<F, B>>(x: T) -> B {
695 x.map_bool(Float::is_nan)
696}
697
698/// Returns true if x holds a positive infinity or negative infinity.
699/// Returns false otherwise.
700///
701/// # Example
702///
703/// ```
704/// # fn main() {
705/// use num_traits::Float;
706///
707/// let inf: f32 = Float::infinity();
708/// assert!(glm::isinf(inf));
709/// assert_eq!(glm::isinf(glm::vec2(inf, 0.)), glm::bvec2(true, false));
710/// # }
711/// ```
712#[inline(always)]
713pub fn isinf<F: BaseFloat, B: GenBType, T: NumBoolRel<F, B>>(x: T) -> B {
714 x.map_bool(Float::is_infinite)
715}
716
717/// Returns a signed integer value representing the encoding of
718/// a floating-point value.
719///
720/// The floating-point value's bit-level representation is preserved.
721///
722/// # Example
723///
724/// ```
725/// # fn main() {
726/// use glm::*;
727/// use num_traits::Float;
728///
729/// let f = 1_f32;
730/// let i = floatBitsToInt(f);
731/// assert_eq!(i, 0x3F800000);
732/// let inf: f32 = Float::infinity();
733/// let v = vec3(0.2, 0., inf);
734/// assert_eq!(floatBitsToInt(v), ivec3(0x3E4CCCCD, 0, 0x7f800000));
735/// # }
736/// ```
737#[inline(always)]
738#[allow(non_snake_case)]
739pub fn floatBitsToInt<G: GenIType, T: FloatIntRel<f32, i32, G>>(value: T) -> G {
740 value.map_int(|f| -> i32 {
741 let i: i32 = unsafe { mem::transmute(f) };
742 i
743 })
744}
745
746/// Returns a unsigned integer value representing the encoding of
747/// a floating-point value.
748///
749/// The floating- point value's bit-level representation is preserved.
750///
751/// # Example
752///
753/// ```
754/// # fn main() {
755/// use glm::{ floatBitsToUint, vec3, uvec3 };
756/// use num_traits::Float;
757///
758/// let f = 1_f32;
759/// let u = floatBitsToUint(f);
760/// assert_eq!(u, 0x3F800000);
761/// let inf: f32 = Float::infinity();
762/// let v = vec3(0.2, 0., inf);
763/// assert_eq!(floatBitsToUint(v), uvec3(0x3E4CCCCD, 0, 0x7f800000));
764/// # }
765/// ```
766#[inline(always)]
767#[allow(non_snake_case)]
768pub fn floatBitsToUint<G: GenUType, T: FloatIntRel<f32, u32, G>>(value: T) -> G {
769 value.map_int(|f| -> u32 {
770 let u: u32 = unsafe { mem::transmute(f) };
771 u
772 })
773}
774
775/// Returns a floating-point value corresponding to a signed integer encoding
776/// of a floating-point value.
777///
778/// # Example
779///
780/// ```
781/// # fn main() {
782/// use glm::{ intBitsToFloat, vec3, ivec3 };
783/// use num_traits::Float;
784///
785/// let i: i32 = 0x3F800000;
786/// let f = intBitsToFloat(i);
787/// assert_eq!(f, 1.);
788/// let inf: f32 = Float::infinity();
789/// let vi = ivec3(0x3E4CCCCD, 0, 0x7f800000);
790/// let vf = vec3(0.2, 0., inf);
791/// assert_eq!(intBitsToFloat(vi), vf);
792/// # }
793/// ```
794#[inline(always)]
795#[allow(non_snake_case)]
796pub fn intBitsToFloat<G: GenType, T: IntFloatRel<i32, f32, G>>(value: T) -> G {
797 value.map_flt(|i| -> f32 {
798 let f: f32 = unsafe { mem::transmute(i) };
799 f
800 })
801}
802
803/// Returns a floating-point value corresponding to a unsigned integer encoding
804/// of a floating-point value.
805///
806/// # Example
807///
808/// ```
809/// # fn main() {
810/// use glm::{ uintBitsToFloat, vec3, uvec3 };
811/// use num_traits::Float;
812///
813/// let i: u32 = 0x3F800000;
814/// let f = uintBitsToFloat(i);
815/// assert_eq!(f, 1.);
816/// let inf: f32 = Float::infinity();
817/// let vu = uvec3(0x3E4CCCCD, 0, 0x7f800000);
818/// let vf = vec3(0.2, 0., inf);
819/// assert_eq!(uintBitsToFloat(vu), vf);
820/// # }
821/// ```
822#[inline(always)]
823#[allow(non_snake_case)]
824pub fn uintBitsToFloat<G: GenType, T: IntFloatRel<u32, f32, G>>(value: T) -> G {
825 value.map_flt(|u| -> f32 {
826 let f: f32 = unsafe { mem::transmute(u) };
827 f
828 })
829}
830
831/// Computes and returns `a * b + c`.
832///
833/// # Example
834///
835/// ```
836/// use glm::{ fma, vec3 };
837/// assert_eq!(fma(1.5_f32, 2.25, 3.125), 6.5);
838/// let a = vec3(-1., 2., 3.);
839/// let b = vec3(4., 5., 6.);
840/// let c = vec3(7., 8., 0.);
841/// assert_eq!(fma(a, b, c), vec3(3., 18., 18.));
842/// ```
843#[inline(always)]
844pub fn fma<F: BaseFloat, T: GenFloat<F>>(a: T, b: T, c: T) -> T {
845 a.fma(&b, &c)
846}
847
848/// Splits `x` into a floating-point significand in the range [0.5, 1.0) and
849/// an integral exponent of two, such that:
850/// *x = significand⋅2<sup>exponent</sup>*.
851///
852/// For a floating-point value of zero, the significant and exponent are both
853/// zero.
854///
855/// For a floating-point value that is an infinity or is not a number,
856/// the results are undefined.
857///
858/// # Note
859///
860/// In GLSL, the significand is returned by the function and the exponent is
861/// returned in the output parameter `exp`. In Rust, we have the luxury to
862/// return both of them very naturally via a tuple.
863///
864/// # Example
865///
866/// ```
867/// use glm::{ frexp, dvec3, ivec3 };
868///
869/// assert_eq!(frexp(0_f32), (0., 0));
870/// let v3 = dvec3(1024., 1., 3.);
871/// let s = dvec3(0.5, 0.5, glm::exp2(glm::log2(3.) - 2.));
872/// let e = ivec3(11, 1, 2);
873/// assert_eq!((s, e), frexp(v3));
874/// ```
875#[inline(always)]
876pub fn frexp<F: BaseFloat, I: GenIType, T: FloatIntRel<F, i32, I>>(x: T) -> (T, I) {
877 x.split_int(|f| -> (F, i32) {
878 let (s, e) = BaseFloat::frexp(f);
879 (s, e as i32)
880 })
881}
882
883/// Builds a floating-point number from `x` and the corresponding integral
884/// exponent of two in `exp`, returning:
885/// *significand ⋅ 2<sup>exponent</sup>*.
886///
887/// If this product is too large to be represented in the floating-point type,
888/// the result is undefined.
889///
890/// # Example
891///
892/// ```
893/// use glm::{ ldexp, vec3, ivec3 };
894///
895/// assert_eq!(ldexp(2_f32, 2), 8.);
896/// let vf = vec3(1., 2., 3.);
897/// let vi = ivec3(-1, 1, 2);
898/// assert_eq!(ldexp(vf, vi), vec3(0.5, 4., 12.));
899/// ```
900#[inline(always)]
901pub fn ldexp<F: BaseFloat, G: GenFloat<F>, T: IntFloatRel<i32, F, G>>(x: G, exp: T) -> G {
902 exp.zip_flt(&x, |i, f| -> F { BaseFloat::ldexp(f, i as isize) })
903}