}
}
+/// Returns the minimum of `x` and `y`.
+///
+/// Rust's standard `f32::min` function produces not-ideal code, so it's re-implemented here.
#[inline(always)]
pub fn min(x: f32, y: f32) -> f32 {
if x < y {
}
}
+/// Returns the maximum of `x` and `y`.
+///
+/// Rust's standard `f32::max` function produces not-ideal code, so it's re-implemented here.
#[inline(always)]
pub fn max(x: f32, y: f32) -> f32 {
if x > y {
}
}
+/// Returns the value `x` clamped between `lo` and `hi`.
+///
+/// Rust's standard `f32::clamp` function produces not-ideal code, so it's re-implemented here.
#[inline(always)]
pub fn clamp(x: f32, lo: f32, hi: f32) -> f32 {
debug_assert!(lo <= hi);
macro_rules! impl_shared {
($name:ty, $t:ty, $n:expr) => {
impl $name {
- pub const ZERO: Self = Self::splat(0.0);
- pub const ONE: Self = Self::splat(1.0);
- pub const NAN: Self = Self::splat(0.0 / 0.0);
-
+ #[doc = concat!("[`", stringify!($name), "`] with all elements initialized to `0.0`.")]
+ pub const ZERO: $name = Self::splat(0.0);
+ #[doc = concat!("[`", stringify!($name), "`] with all elements initialized to `1.0`.")]
+ pub const ONE: $name = Self::splat(1.0);
+ #[doc = concat!("[`", stringify!($name), "`] with all elements initialized to `NaN`.")]
+ pub const NAN: $name = Self::splat(0.0 / 0.0);
+
+ #[doc = concat!("Constructs a new [`", stringify!($name), "`] where each element is initialized with the given `value`.")]
#[inline(always)]
- pub const fn splat(value: $t) -> Self {
+ 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.
unsafe { std::mem::transmute([value; $n]) }
}
+ #[doc = concat!("Returns a [`", stringify!($name), "`] where each element is initialized with the minimum of the respective elements from `a` and `b`.")]
#[inline]
- pub fn min(a: Self, b: Self) -> Self {
+ pub fn min(a: $name, b: $name) -> $name {
a.map2(b, |a, b| crate::min(a, b))
}
+ #[doc = concat!("Returns a [`", stringify!($name), "`] where each element is initialized with the maximum of the respective elements from `a` and `b`.")]
#[inline]
- pub fn max(a: Self, b: Self) -> Self {
+ pub fn max(a: $name, b: $name) -> $name {
a.map2(b, |a, b| crate::max(a, b))
}
+ #[doc = concat!("Returns a [`", stringify!($name), "`] where each element of `x` is clamped between the respective elements in `a` and `b`.")]
#[inline]
- pub fn clamp(x: Self, lo: Self, hi: Self) -> Self {
+ 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]
+ pub fn abs(self) -> $name {
+ self.map(|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)]
- pub fn ceil(self) -> Self {
+ pub fn ceil(self) -> $name {
self.map(|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)]
- pub fn floor(self) -> Self {
+ pub fn floor(self) -> $name {
self.map(|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)]
- pub fn round(self) -> Self {
+ pub fn round(self) -> $name {
self.map(|x| x.round())
}
}
impl From<[$t; $n]> for $name {
#[inline(always)]
- fn from(x: [$t; $n]) -> Self {
+ fn from(x: [$t; $n]) -> $name {
unsafe { std::mem::transmute(x) }
}
}
macro_rules! impl_affine {
($name:ty, $t:ty, $n:expr) => {
impl $name {
+ /// Calculates the euclidean distance between the two points `a` and `b`.
#[inline]
- pub fn distance(a: Self, b: Self) -> $t {
+ pub fn distance(a: $name, b: $name) -> $t {
(b - a).length()
}
+ /// Calculates the squared euclidean distance between the two points `a` and `b`.
#[inline]
- pub fn distance_sq(a: Self, b: Self) -> $t {
+ pub fn distance_sq(a: $name, b: $name) -> $t {
(b - a).length_sq()
}
}
macro_rules! impl_vector {
($name:ty, $t:ty, $n:expr) => {
impl $name {
+ /// Calculates the length of the vector `self`.
#[inline]
pub fn length(self) -> $t {
self.length_sq().sqrt()
}
+ /// Calculate the squared length of the vector `self`.
#[inline]
pub fn length_sq(self) -> $t {
Self::dot(self, self)
impl_affine!(Point2, f32, 2);
impl Point2 {
- pub const X: Self = Self::new(1.0, 0.0);
- pub const Y: Self = Self::new(0.0, 1.0);
-
- /// Creates a new `Point2` with the given `x` and `y` coordinates.
+ /// Constructs a new [`Point2`] with the given `x` and `y` coordinates.
#[inline(always)]
pub const fn new(x: f32, y: f32) -> Self {
Self { x, y }
}
- /// Returns a new `Point2` with the function `f` applied to each coordinate in order.
+ /// Returns a new [`Point2`] with the function `f` applied to each coordinate of `self` in order.
#[inline(always)]
pub fn map<F>(self, mut f: F) -> Self
where
}
}
- /// Returns a new point in 2d space with the function `f` applied to each pair of components from `self` and `rhs` in order.
+ /// Returns a new [`Point2`] with the function `f` applied to each pair of components from `self` and `rhs` in order.
#[inline(always)]
pub fn map2<F>(self, rhs: Self, mut f: F) -> Self
where
impl_affine!(Point3, f32, 3);
impl Point3 {
- pub const X: Self = Self::new(1.0, 0.0, 0.0);
- pub const Y: Self = Self::new(0.0, 1.0, 0.0);
- pub const Z: Self = Self::new(0.0, 0.0, 1.0);
-
- /// Creates a new point in 3d space with the given `x`, `y` and `z` coordinates.
+ /// Constructs a new [`Point3`] with the given `x`, `y`, and `z` coordinates.
#[inline(always)]
- pub const fn new(x: f32, y: f32, z: f32) -> Self {
- Self { x, y, z }
+ pub const fn new(x: f32, y: f32, z: f32) -> Point3 {
+ Point3 { x, y, z }
}
- /// Returns a new point in 3d space with the function `f` applied to each coordinate in order.
+ /// Returns a new [`Point3`] with the function `f` applied to each coordinate of `self` in order.
#[inline(always)]
- pub fn map<F>(self, mut f: F) -> Self
+ pub fn map<F>(self, mut f: F) -> Point3
where
F: FnMut(f32) -> f32,
{
- Self {
+ Point3 {
x: f(self.x),
y: f(self.y),
z: f(self.z),
}
}
- /// Returns a new point in 3d space with the function `f` applied to each pair of components from `self` and `rhs` in order.
+ /// Returns a new [`Point3`] with the function `f` applied to each pair of components from `self` and `rhs` in order.
#[inline(always)]
- pub fn map2<F>(self, rhs: Self, mut f: F) -> Self
+ pub fn map2<F>(self, rhs: Point3, mut f: F) -> Point3
where
F: FnMut(f32, f32) -> f32,
{
- Self {
+ Point3 {
x: f(self.x, rhs.x),
y: f(self.y, rhs.y),
z: f(self.z, rhs.z),
impl_vector!(Vec2, f32, 2);
impl Vec2 {
- pub const X: Self = Self::new(1.0, 0.0);
- pub const Y: Self = Self::new(0.0, 1.0);
+ pub const X: Vec2 = Vec2::new(1.0, 0.0);
+ pub const Y: Vec2 = Vec2::new(0.0, 1.0);
- /// Creates a new 2d vector with the given `x` and `y` components.
+ /// Constructs a new [`Vec2`] with the given `x` and `y` components.
#[inline(always)]
pub const fn new(x: f32, y: f32) -> Self {
Self { x, y }
}
- /// Returns a new 2d vector with the function `f` applied to each component in order.
+ /// Returns a [`Vec2`] with the function `f` applied to each component in order.
#[inline(always)]
- pub fn map<F>(self, mut f: F) -> Self
+ pub fn map<F>(self, mut f: F) -> Vec2
where
F: FnMut(f32) -> f32,
{
- Self {
+ Vec2 {
x: f(self.x),
y: f(self.y),
}
}
- /// Returns a new 2d vector with the function `f` applied to each pair of components from `self` and `rhs` in order.
+ /// Returns a new [`Vec2`] with the function `f` applied to each pair of components from `self` and `rhs` in order.
#[inline(always)]
- pub fn map2<F>(self, rhs: Self, mut f: F) -> Self
+ pub fn map2<F>(self, rhs: Vec2, mut f: F) -> Vec2
where
F: FnMut(f32, f32) -> f32,
{
- Self {
+ Vec2 {
x: f(self.x, rhs.x),
y: f(self.y, rhs.y),
}
}
+ /// Returns the dot product of `a` and `b`.
#[inline]
pub fn dot(a: Self, b: Self) -> f32 {
a.x * b.x + a.y * b.y
impl_vector!(Vec3, f32, 3);
impl Vec3 {
- pub const X: Self = Self::new(1.0, 0.0, 0.0);
- pub const Y: Self = Self::new(0.0, 1.0, 0.0);
- pub const Z: Self = Self::new(0.0, 0.0, 1.0);
+ pub const X: Vec3 = Vec3::new(1.0, 0.0, 0.0);
+ pub const Y: Vec3 = Vec3::new(0.0, 1.0, 0.0);
+ pub const Z: Vec3 = Vec3::new(0.0, 0.0, 1.0);
- /// Creates a new 3d vector with the given `x`, `y` and `z` components.
+ /// Constructs a new [`Vec3`] with the given `x`, `y` and `z` components.
#[inline(always)]
- pub const fn new(x: f32, y: f32, z: f32) -> Self {
- Self { x, y, z }
+ pub const fn new(x: f32, y: f32, z: f32) -> Vec3 {
+ Vec3 { x, y, z }
}
- /// Returns a new 3d vector with the function `f` applied to each component in order.
+ /// Returns a [`Vec3`] with the function `f` applied to each component in order.
#[inline(always)]
- pub fn map<F>(self, mut f: F) -> Self
+ pub fn map<F>(self, mut f: F) -> Vec3
where
F: FnMut(f32) -> f32,
{
- Self {
+ Vec3 {
x: f(self.x),
y: f(self.y),
z: f(self.z),
}
}
- /// Returns a new 3d vector with the function `f` applied to each pair of components from `self` and `rhs` in order.
+ /// Returns a new [`Vec3`] with the function `f` applied to each pair of components from `self` and `rhs` in order.
#[inline(always)]
- pub fn map2<F>(self, rhs: Self, mut f: F) -> Self
+ pub fn map2<F>(self, rhs: Self, mut f: F) -> Vec3
where
F: FnMut(f32, f32) -> f32,
{
- Self {
+ Vec3 {
x: f(self.x, rhs.x),
y: f(self.y, rhs.y),
z: f(self.z, rhs.z),
}
}
+ /// Returns the dot product of `a` and `b`.
#[inline]
- pub fn dot(a: Self, b: Self) -> f32 {
+ 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]
- pub fn cross(a: Self, b: Self) -> Vec3 {
+ pub fn cross(a: Vec3, b: Vec3) -> Vec3 {
[
a.y * b.z - a.z * b.y,
- -(a.x * b.z - a.z * b.x),
+ a.x * b.z - a.z * b.x,
a.x * b.y - a.y * b.x,
]
.into()
impl_vector!(Vec4, f32, 4);
impl Vec4 {
- pub const X: Self = Self::new(1.0, 0.0, 0.0, 0.0);
- pub const Y: Self = Self::new(0.0, 1.0, 0.0, 0.0);
- pub const Z: Self = Self::new(0.0, 0.0, 1.0, 0.0);
- pub const W: Self = Self::new(0.0, 0.0, 0.0, 1.0);
+ pub const X: Vec4 = Vec4::new(1.0, 0.0, 0.0, 0.0);
+ pub const Y: Vec4 = Vec4::new(0.0, 1.0, 0.0, 0.0);
+ pub const Z: Vec4 = Vec4::new(0.0, 0.0, 1.0, 0.0);
+ pub const W: Vec4 = Vec4::new(0.0, 0.0, 0.0, 1.0);
- /// Creates a new 4d vector with the given `x`, `y`, `z` and `w` components.
+ /// Constructs a new [`Vec4`] with the given `x`, `y`, `z` and `w` components.
#[inline(always)]
- pub const fn new(x: f32, y: f32, z: f32, w: f32) -> Self {
- Self { x, y, z, w }
+ pub const fn new(x: f32, y: f32, z: f32, w: f32) -> Vec4 {
+ Vec4 { x, y, z, w }
}
- /// Returns a new 4d vector with the function `f` applied to each component in order.
+ /// Returns a [`Vec4`] with the function `f` applied to each component in order.
#[inline(always)]
- pub fn map<F>(self, mut f: F) -> Self
+ pub fn map<F>(self, mut f: F) -> Vec4
where
F: FnMut(f32) -> f32,
{
}
}
- /// Returns a new 3d vector with the function `f` applied to each pair of components from `self` and `rhs` in order.
+ /// Returns a new [`Vec4`] with the function `f` applied to each pair of components from `self` and `rhs` in order.
#[inline(always)]
- pub fn map2<F>(self, rhs: Self, mut f: F) -> Self
+ pub fn map2<F>(self, rhs: Self, mut f: F) -> Vec4
where
F: FnMut(f32, f32) -> f32,
{
- Self {
+ Vec4 {
x: f(self.x, rhs.x),
y: f(self.y, rhs.y),
z: f(self.z, rhs.z),
}
}
+ /// Returns the dot product of `a` and `b`.
#[inline]
- pub fn dot(a: Self, b: Self) -> f32 {
+ pub fn dot(a: Vec4, b: Vec4) -> f32 {
a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w
}
}