/// ---
/// On `x86` If either input is `NaN`, returns the value of `y`. Other platforms follow IEEE754-2008 semantics, where if
/// either input is `NaN` the other input is returned. `NaN` propagates when both inputs are `NaN`.
+#[must_use]
#[inline(always)]
pub fn min(x: f32, y: f32) -> f32 {
#[cfg(target_arch = "x86_64")]
/// # Platform Specific Behavior
/// On `x86` If either input is `NaN`, returns the value of `y`. Other platforms follow IEEE754-2008 semantics, where if
/// either input is `NaN` the other input is returned. `NaN` propagates when both inputs are `NaN`.
+#[must_use]
#[inline(always)]
pub fn max(x: f32, y: f32) -> f32 {
#[cfg(target_arch = "x86_64")]
/// # Panics
///
/// Panics if `lo` is greater than `hi`.
+#[must_use]
#[inline(always)]
pub fn clamp(x: f32, lo: f32, hi: f32) -> f32 {
debug_assert!(lo <= hi);
/// Linearly interpolate between `a` and `b` with the control value `t`.
///
/// Returns the exact value of `a` when `t == 0.0` and the exact value of `b` when `t == 1.0`.
+#[must_use]
#[inline(always)]
pub fn lerp(t: f32, a: f32, b: f32) -> f32 {
t.mul_add(b, t.mul_add(-a, a))
///
/// This function performs the same operation, but returns an implementation
/// defined value for these cases.
+#[must_use]
#[inline(always)]
pub fn f32_to_i32(x: f32) -> i32 {
#[cfg(not(target_arch = "x86_64"))]
#[doc = concat!("Constructs a new [`", stringify!($name), "`] where each element is initialized with the given `value`.")]
#[inline(always)]
+ #[must_use]
pub const fn splat(value: $t) -> $name {
// we have to transmute here because we can't make `into()` const.
// SAFETY: $name is repr(C) struct with $n elements of type $t, so the transmute is always valid.
}
#[doc = concat!("Returns a [`", stringify!($name), "`] where each element is initialized with the minimum of the corresponding elements in `a` and `b`.\n\nThis function returns a platform dependent value if either input is `NaN`. See [`crate::min`] for exact details.")]
- #[inline]
+ #[inline(always)]
+ #[must_use]
pub fn min(a: $name, b: $name) -> $name {
- a.map2(b, |a, b| $crate::min(a, b))
+ a.map2(b, #[inline(always)] |a, b| $crate::min(a, b))
}
#[doc = concat!("Returns a [`", stringify!($name), "`] where each element is initialized with the maximum of the corresponding elements in `a` and `b`.\n\nThis function returns a platform dependent value if either input is `NaN`. See [`crate::max`] for exact details.")]
- #[inline]
+ #[inline(always)]
+ #[must_use]
pub fn max(a: $name, b: $name) -> $name {
- a.map2(b, |a, b| $crate::max(a, b))
+ a.map2(b, #[inline(always)] |a, b| $crate::max(a, b))
}
#[doc = concat!("Returns a [`", stringify!($name), "`] where each element is initalized by linearly interpolating between the corresponding elements in `a` and `b` using `t` as a control value.")]
- #[inline]
+ #[inline(always)]
#[must_use]
pub fn lerp(t: f32, a: Self, b: Self) -> Self {
- a.map2(b, |a, b| $crate::lerp(t, a, b))
+ a.map2(b, #[inline(always)] |a, b| $crate::lerp(t, a, b))
}
#[doc = concat!("Returns a [`", stringify!($name), "`] where the `i`th element `x[i]` is clamped between the corresponding elements `lo[i]` and `hi[i]`.\n\n# Panics\n\nPanics if any element of `lo` is greater than its corresponding element in `hi`.")]
- #[inline]
+ #[inline(always)]
+ #[must_use]
pub fn clamp(x: $name, lo: $name, hi: $name) -> $name {
Self::max(Self::min(x, hi), lo)
}
#[doc = concat!("Returns a [`", stringify!($name), "`] where each element is the absolute value of the corresponding element in `self`.")]
- #[inline]
+ #[inline(always)]
+ #[must_use]
pub fn abs(self) -> $name {
- self.map(|x| x.abs())
+ self.map(#[inline(always)] |x| x.abs())
}
#[doc = concat!("Returns a [`", stringify!($name), "`] where each element is the smallest integer value greater than or equal to the corresponding element in `self`.")]
#[inline(always)]
+ #[must_use]
pub fn ceil(self) -> $name {
- self.map(|x| x.ceil())
+ self.map(#[inline(always)] |x| x.ceil())
}
#[doc = concat!("Returns a [`", stringify!($name), "`] where each element is the largest integer value less than or equal to the corresponding element in `self`.")]
#[inline(always)]
+ #[must_use]
pub fn floor(self) -> $name {
- self.map(|x| x.floor())
+ self.map(#[inline(always)] |x| x.floor())
}
#[doc = concat!("Returns a [`", stringify!($name), "`] where each element is the nearest integer value to the corresponding element in `self`. Rounds half-way cases away from `0.0`.")]
#[inline(always)]
+ #[must_use]
pub fn round(self) -> $name {
- self.map(|x| x.round())
+ self.map(#[inline(always)] |x| x.round())
}
}
($name:ty, $t:ty, $n:expr) => {
impl $name {
/// Calculates the euclidean distance between the two points `a` and `b`.
- #[inline]
+ #[inline(always)]
+ #[must_use]
pub fn distance(a: $name, b: $name) -> $t {
(b - a).length()
}
/// Calculates the squared euclidean distance between the two points `a` and `b`.
/// Avoids an expensive `sqrt` operation.
- #[inline]
+ #[inline(always)]
+ #[must_use]
pub fn distance_sq(a: $name, b: $name) -> $t {
(b - a).length_sq()
}
($name:ty, $t:ty, $n:expr) => {
impl $name {
/// Calculates the length of the vector `self`.
- #[inline]
+ #[inline(always)]
+ #[must_use]
pub fn length(self) -> $t {
self.length_sq().sqrt()
}
/// Calculate the squared length of the vector `self`.
/// Avoids an expensive `sqrt` operation.
- #[inline]
+ #[inline(always)]
+ #[must_use]
pub fn length_sq(self) -> $t {
Self::dot(self, self)
}
/// Returns a vector with the same direction as `self` but with unit (1.0) length.
+ #[inline(always)]
#[must_use]
- #[inline]
pub fn normalized(self) -> $name {
self / self.length()
}
type Output = $name;
#[inline(always)]
fn neg(self) -> Self::Output {
- self.map(|x| -x)
+ self.map(
+ #[inline(always)]
+ |x| -x,
+ )
}
}
type Output = $name;
#[inline(always)]
fn add(self, rhs: $t) -> Self::Output {
- self.map(|x| x + rhs)
+ self.map(
+ #[inline(always)]
+ |x| x + rhs,
+ )
}
}
type Output = $name;
#[inline(always)]
fn sub(self, rhs: $t) -> Self::Output {
- self.map(|x| x - rhs)
+ self.map(
+ #[inline(always)]
+ |x| x - rhs,
+ )
}
}
type Output = $name;
#[inline(always)]
fn mul(self, rhs: $t) -> Self::Output {
- self.map(|x| x * rhs)
+ self.map(
+ #[inline(always)]
+ |x| x * rhs,
+ )
}
}
type Output = $name;
#[inline(always)]
fn mul(self, rhs: $name) -> Self::Output {
- rhs.map(|x| self * x)
+ rhs.map(
+ #[inline(always)]
+ |x| self * x,
+ )
}
}
type Output = $name;
#[inline(always)]
fn div(self, rhs: $t) -> Self::Output {
- self.map(|x| x / rhs)
+ self.map(
+ #[inline(always)]
+ |x| x / rhs,
+ )
}
}
/// Constructs a new [`Vec3`] with the given `x`, `y` and `z` components.
#[inline(always)]
+ #[must_use]
pub const fn new(x: f32, y: f32, z: f32) -> Vec3 {
Vec3 { x, y, z }
}
/// Converts this point to the equivalent point.
#[inline(always)]
+ #[must_use]
pub const fn as_point3(self) -> Point3 {
Point3::new(self.x, self.y, self.z)
}
/// Returns a [`Vec3`] with the function `f` applied to each component in order.
#[inline(always)]
+ #[must_use]
pub fn map<F>(self, mut f: F) -> Vec3
where
F: FnMut(f32) -> f32,
/// Returns a new [`Vec3`] with the function `f` applied to each pair of
/// components from `self` and `rhs` in order.
#[inline(always)]
+ #[must_use]
pub fn map2<F>(self, rhs: Self, mut f: F) -> Vec3
where
F: FnMut(f32, f32) -> f32,
}
/// Returns the dot product of `a` and `b`.
- #[inline]
+ #[inline(always)]
#[must_use]
pub fn dot(a: Vec3, b: Vec3) -> f32 {
a.x * b.x + a.y * b.y + a.z * b.z
}
/// Returns the cross product of `a` and `b`.
- #[inline]
+ #[inline(always)]
#[must_use]
pub fn cross(a: Vec3, b: Vec3) -> Vec3 {
[
impl std::ops::Add for Vec3 {
type Output = Vec3;
- #[inline]
+ #[inline(always)]
fn add(self, rhs: Self) -> Self::Output {
Self::Output {
x: self.x + rhs.x,
impl std::ops::Sub for Vec3 {
type Output = Vec3;
- #[inline]
+ #[inline(always)]
fn sub(self, rhs: Self) -> Self::Output {
Self::Output {
x: self.x - rhs.x,
}
impl std::ops::MulAssign for Vec3 {
- #[inline]
+ #[inline(always)]
fn mul_assign(&mut self, rhs: Self) {
self.x *= rhs.x;
self.y *= rhs.y;