From: Joshua Simmons Date: Thu, 8 Sep 2022 19:13:44 +0000 (+0200) Subject: Improve documentation for maths library X-Git-Url: https://git.nega.tv//gitweb.cgi?a=commitdiff_plain;h=7421095d69fd9e33c25598f046ebd7f89f4d66c2;p=josh%2Fnarcissus Improve documentation for maths library --- diff --git a/narcissus-maths/src/lib.rs b/narcissus-maths/src/lib.rs index 0159592..5a26fcd 100644 --- a/narcissus-maths/src/lib.rs +++ b/narcissus-maths/src/lib.rs @@ -64,6 +64,9 @@ impl From for Rad { } } +/// 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 { @@ -73,6 +76,9 @@ pub fn min(x: f32, y: f32) -> f32 { } } +/// 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 { @@ -82,6 +88,9 @@ pub fn max(x: f32, y: f32) -> f32 { } } +/// 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); @@ -92,50 +101,67 @@ pub fn clamp(x: f32, lo: f32, hi: f32) -> f32 { 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) } } } @@ -153,13 +179,15 @@ macro_rules! impl_shared { 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() } } @@ -170,11 +198,13 @@ macro_rules! impl_affine { 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) diff --git a/narcissus-maths/src/point2.rs b/narcissus-maths/src/point2.rs index 4e1a60a..5351cd1 100644 --- a/narcissus-maths/src/point2.rs +++ b/narcissus-maths/src/point2.rs @@ -12,16 +12,13 @@ impl_shared!(Point2, f32, 2); 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(self, mut f: F) -> Self where @@ -33,7 +30,7 @@ impl Point2 { } } - /// 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(self, rhs: Self, mut f: F) -> Self where diff --git a/narcissus-maths/src/point3.rs b/narcissus-maths/src/point3.rs index c3aa2e4..c3b9ebb 100644 --- a/narcissus-maths/src/point3.rs +++ b/narcissus-maths/src/point3.rs @@ -13,36 +13,32 @@ impl_shared!(Point3, f32, 3); 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(self, mut f: F) -> Self + pub fn map(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(self, rhs: Self, mut f: F) -> Self + pub fn map2(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), diff --git a/narcissus-maths/src/vec2.rs b/narcissus-maths/src/vec2.rs index 156d104..8ca9ed4 100644 --- a/narcissus-maths/src/vec2.rs +++ b/narcissus-maths/src/vec2.rs @@ -11,39 +11,40 @@ impl_shared!(Vec2, f32, 2); 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(self, mut f: F) -> Self + pub fn map(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(self, rhs: Self, mut f: F) -> Self + pub fn map2(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 diff --git a/narcissus-maths/src/vec3.rs b/narcissus-maths/src/vec3.rs index 507d9af..b758641 100644 --- a/narcissus-maths/src/vec3.rs +++ b/narcissus-maths/src/vec3.rs @@ -12,52 +12,54 @@ impl_shared!(Vec3, f32, 3); 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(self, mut f: F) -> Self + pub fn map(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(self, rhs: Self, mut f: F) -> Self + pub fn map2(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() diff --git a/narcissus-maths/src/vec4.rs b/narcissus-maths/src/vec4.rs index a73b976..6f678fa 100644 --- a/narcissus-maths/src/vec4.rs +++ b/narcissus-maths/src/vec4.rs @@ -13,20 +13,20 @@ impl_shared!(Vec4, f32, 4); 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(self, mut f: F) -> Self + pub fn map(self, mut f: F) -> Vec4 where F: FnMut(f32) -> f32, { @@ -38,13 +38,13 @@ impl Vec4 { } } - /// 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(self, rhs: Self, mut f: F) -> Self + pub fn map2(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), @@ -52,8 +52,9 @@ impl Vec4 { } } + /// 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 } }