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}