Initial Commit
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
65
Cargo.lock
generated
Normal file
65
Cargo.lock
generated
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytemuck"
|
||||||
|
version = "1.23.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9134a6ef01ce4b366b50689c94f82c14bc72bc5d0386829828a2e2752ef7958c"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytemuck_derive"
|
||||||
|
version = "1.9.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7ecc273b49b3205b83d648f0690daa588925572cc5063745bfe547fe7ec8e1a1"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "geometry"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.95"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.40"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.101"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||||
12
Cargo.toml
Normal file
12
Cargo.toml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
[package]
|
||||||
|
name = "geometry"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
publish = false
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
bytemuck = { version = "1.22.0", features = ["derive", "extern_crate_alloc"] }
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "geometry_lib"
|
||||||
|
path = "src/lib.rs"
|
||||||
2
examples/custom_coord.rs
Normal file
2
examples/custom_coord.rs
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
fn main() {
|
||||||
|
}
|
||||||
155
src/basic/basic_coord2d.rs
Normal file
155
src/basic/basic_coord2d.rs
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
use crate::{Numeric, SqrtUnit, Widen};
|
||||||
|
|
||||||
|
/// A Simple 2D Coordinate with a AxisUnitag Unit
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct Point2D<AxisUnit: Numeric + Copy, U> {
|
||||||
|
pub x: AxisUnit,
|
||||||
|
pub y: AxisUnit,
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
tag: PhantomData<U>
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A representation of some point on a 2D plane.
|
||||||
|
impl<AxisUnit: Numeric + Copy, U> Point2D<AxisUnit, U> {
|
||||||
|
#[inline]
|
||||||
|
pub const fn new(x: AxisUnit, y: AxisUnit) -> Self {
|
||||||
|
Self {
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
tag: PhantomData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn min_point(&self, other: &Self) -> Self {
|
||||||
|
let min_x = self.min_x(other);
|
||||||
|
let min_y = self.min_y(other);
|
||||||
|
Self::new(min_x, min_y)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn max_point(&self, other: &Self) -> Self {
|
||||||
|
let max_x = self.max_x(other);
|
||||||
|
let max_y = self.max_y(other);
|
||||||
|
Self::new(max_x, max_y)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn min_x(&self, other: &Self) -> AxisUnit {
|
||||||
|
if self.x < other.x { self.x } else { other.x }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn min_y(&self, other: &Self) -> AxisUnit {
|
||||||
|
if self.y < other.y { self.y } else { other.y }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn max_x(&self, other: &Self) -> AxisUnit {
|
||||||
|
if self.x > other.x { self.x } else { other.x }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn max_y(&self, other: &Self) -> AxisUnit {
|
||||||
|
if self.y > other.y { self.y } else { other.y }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn order_x(&self, other: &Self) -> (AxisUnit, AxisUnit) {
|
||||||
|
if self.x < other.x { (self.x, other.x) } else { (other.x, self.x) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn order_y(&self, other: &Self) -> (AxisUnit, AxisUnit) {
|
||||||
|
if self.y < other.y { (self.y, other.y) } else { (other.y, self.y) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn midpoint(&self, other: &Self) -> Self {
|
||||||
|
// This function could be a lot better if we could specialize, but unfortunately we can't.
|
||||||
|
// As we are (potentially) working with discrete values, we want to avoid the situation
|
||||||
|
// where we are incorrect about the midpoint due to rounding. If we divide both operands by
|
||||||
|
// two, and they both happen to be odd, we'll be incorrect as we'll have rounded down an
|
||||||
|
// extra unit. To circumvent this, we need to do things the long way.
|
||||||
|
//
|
||||||
|
// Consider two points at x unit 3 and 9. The midpoint should be 6. But if we divide first,
|
||||||
|
// we truncate and end up with (3/2 + 9/2) = (1 + 4) = 5. So we have to add first. But if
|
||||||
|
// we add first, there is a chance we could overflow for very large numbers. To avoid this,
|
||||||
|
// we need to offset the numbers by their smallest value, ensuring the addition does not
|
||||||
|
// overflow.
|
||||||
|
let (min_x, max_x) = self.order_x(other);
|
||||||
|
let (min_y, max_y) = self.order_y(other);
|
||||||
|
|
||||||
|
let x = min_x + ((max_x - min_x) / AxisUnit::TWO);
|
||||||
|
let y = min_y + ((max_y - min_y) / AxisUnit::TWO);
|
||||||
|
|
||||||
|
Self::new(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn distance_x(&self, other: &Self) -> AxisUnit {
|
||||||
|
let (min_x, max_x) = self.order_x(other);
|
||||||
|
max_x - min_x
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn distance_y(&self, other: &Self) -> AxisUnit {
|
||||||
|
let (min_y, max_y) = self.order_y(other);
|
||||||
|
max_y - min_y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<AxisUnit: Numeric + Copy + Widen, U> Point2D<AxisUnit, U> {
|
||||||
|
#[inline]
|
||||||
|
pub fn area(&self, other: &Self) -> <AxisUnit as Widen>::Target {
|
||||||
|
let dx = self.distance_x(other);
|
||||||
|
let dy = self.distance_y(other);
|
||||||
|
|
||||||
|
dx.widen() * dy.widen()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn manhattan_distance(&self, other: &Self) -> <AxisUnit as Widen>::Target {
|
||||||
|
self.distance_x(other).widen() + self.distance_y(other).widen()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<AxisUnit: Numeric + Copy + Widen<Target: Widen + Copy>, U> Point2D<AxisUnit, U> {
|
||||||
|
fn distance_squared(&self, other: &Self) -> <<AxisUnit as Widen>::Target as Widen>::Target {
|
||||||
|
let dx = self.distance_x(other).widen();
|
||||||
|
let dy = self.distance_y(other).widen();
|
||||||
|
|
||||||
|
let dx2 = (dx*dx).widen();
|
||||||
|
let dy2 = (dy*dy).widen();
|
||||||
|
|
||||||
|
dx2 + dy2
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn dot_product(&self, other: &Self) -> <<AxisUnit as Widen>::Target as Widen>::Target {
|
||||||
|
let square_x = (self.x.widen() * other.x.widen()).widen();
|
||||||
|
let square_y = (self.x.widen() * other.y.widen()).widen();
|
||||||
|
square_x + square_y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <AxisUnit: Numeric + Copy + Widen<Target: Widen<Target: SqrtUnit> + Copy>, U> Point2D<AxisUnit, U> {
|
||||||
|
fn distance(&self, other: &Self) -> <<AxisUnit as Widen>::Target as Widen>::Target {
|
||||||
|
let ds = self.distance_squared(other);
|
||||||
|
ds.sqrt_unit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<AxisUnit: Numeric + Copy, U> From<(AxisUnit, AxisUnit)> for Point2D<AxisUnit, U> {
|
||||||
|
fn from(value: (AxisUnit, AxisUnit)) -> Self {
|
||||||
|
Self::new(value.0, value.1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<AxisUnit: Numeric + Copy, U> From<Point2D<AxisUnit, U>> for (AxisUnit, AxisUnit) {
|
||||||
|
fn from(value: Point2D<AxisUnit, U>) -> Self {
|
||||||
|
(value.x, value.y)
|
||||||
|
}
|
||||||
|
}
|
||||||
0
src/basic/basic_rect2d.rs
Normal file
0
src/basic/basic_rect2d.rs
Normal file
3
src/basic/mod.rs
Normal file
3
src/basic/mod.rs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
mod basic_coord2d;
|
||||||
|
|
||||||
|
pub use basic_coord2d::*;
|
||||||
11
src/lib.rs
Normal file
11
src/lib.rs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#![deny(clippy::all)]
|
||||||
|
#![forbid(unsafe_code)]
|
||||||
|
#![allow(dead_code)]
|
||||||
|
#![allow(clippy::module_inception)]
|
||||||
|
|
||||||
|
mod traits;
|
||||||
|
mod round;
|
||||||
|
pub mod basic;
|
||||||
|
|
||||||
|
pub use round::*;
|
||||||
|
pub use traits::*;
|
||||||
9
src/round.rs
Normal file
9
src/round.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
||||||
|
#[allow(clippy::enum_variant_names)]
|
||||||
|
pub enum Round {
|
||||||
|
Floor,
|
||||||
|
Ceiling,
|
||||||
|
|
||||||
|
#[default]
|
||||||
|
Round,
|
||||||
|
}
|
||||||
5
src/traits/mod.rs
Normal file
5
src/traits/mod.rs
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
mod numeric;
|
||||||
|
mod primitives;
|
||||||
|
|
||||||
|
pub use numeric::*;
|
||||||
|
pub use primitives::*;
|
||||||
86
src/traits/numeric.rs
Normal file
86
src/traits/numeric.rs
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
use std::ops::{Add, Div, Mul, Shl, Shr, Sub};
|
||||||
|
use std::hash::Hash;
|
||||||
|
|
||||||
|
use bytemuck::Zeroable;
|
||||||
|
|
||||||
|
/// Numeric is a partial trait that more generally represents all numeric types supported by the
|
||||||
|
/// engine. This should include both integers and floats, plus any custom types we implement.
|
||||||
|
pub trait Numeric:
|
||||||
|
Add<Self, Output = Self>
|
||||||
|
+ Sub<Self, Output = Self>
|
||||||
|
+ Mul<Self, Output = Self>
|
||||||
|
+ Div<Self, Output = Self>
|
||||||
|
+ PartialEq
|
||||||
|
+ PartialOrd
|
||||||
|
+ Zeroable
|
||||||
|
{
|
||||||
|
const ZERO: Self;
|
||||||
|
const ONE: Self;
|
||||||
|
const TWO: Self;
|
||||||
|
const MAX: Self;
|
||||||
|
const MIN: Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// /// Integer is a trait representing any of the supported engine numeric types.
|
||||||
|
pub trait Integer: Numeric + Shl + Shr + Ord + Eq + Hash {}
|
||||||
|
|
||||||
|
/// Float is a trait representing any of the supported engine floating point types.
|
||||||
|
pub trait Float: Numeric {}
|
||||||
|
|
||||||
|
/// Signed is a trait representing any value supporting both positive and negative values.
|
||||||
|
pub trait Signed: Numeric {}
|
||||||
|
|
||||||
|
/// Unsigned is a trait representing any value that cannot be negative.
|
||||||
|
pub trait Unsigned: Numeric {}
|
||||||
|
|
||||||
|
/// SignedInteger is a convenience trait implemented for all Signed + Integer values
|
||||||
|
pub trait SignedInteger: Integer + Signed {}
|
||||||
|
impl<T: Integer + Signed> SignedInteger for T {}
|
||||||
|
|
||||||
|
/// UnsignedInteger is a convenience trait implemented for all Unsigned + Integer values
|
||||||
|
pub trait UnsignedInteger: Integer + Unsigned {}
|
||||||
|
impl<T: Integer + Unsigned> UnsignedInteger for T {}
|
||||||
|
|
||||||
|
/// UnitSqrt provies a universal sqrt operator for all values which can have their root taken and
|
||||||
|
/// the value represented in the unit itself. For integers, this would be equivalent to isqrt, and
|
||||||
|
/// for floats, the standard sqrt operation.
|
||||||
|
pub trait SqrtUnit {
|
||||||
|
fn sqrt_unit(self) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait SqrtReal {
|
||||||
|
fn sqrt_real(self) -> f64;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// WidenInto guarantees that a type U can be "widened" into some type T such that T:
|
||||||
|
/// 1. Can hold the result of any multiplication of two U values, including T::MAX * T::MAX.
|
||||||
|
/// 2. No data is lost when converting from U to T.
|
||||||
|
///
|
||||||
|
/// In addition, while it isn't guaranteed, preferably any U can be turned into T with little to no
|
||||||
|
/// overhead, such as converting a u16 to u32 with `as`.
|
||||||
|
pub trait WidenInto<T: Numeric>: Numeric {
|
||||||
|
fn widen_into(self) -> T;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Widen is similar to WidenInto, but only specifies a single associated type to widen into. This
|
||||||
|
/// is useful for code where the context doesn't care what type exactly is widened, only that the
|
||||||
|
/// resulting type is large enough to contain any single math operation on the narrower type.
|
||||||
|
pub trait Widen: Numeric {
|
||||||
|
type Target: Numeric;
|
||||||
|
|
||||||
|
fn widen(self) -> Self::Target;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure WidenInto is also implemented for T => U if the basic Widen trait is implemented.
|
||||||
|
impl<T> WidenInto<<T as Widen>::Target> for T
|
||||||
|
where
|
||||||
|
T: Widen,
|
||||||
|
<T as Widen>::Target: Numeric,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn widen_into(self) -> <Self as Widen>::Target {
|
||||||
|
self.widen()
|
||||||
|
}
|
||||||
|
}
|
||||||
191
src/traits/primitives.rs
Normal file
191
src/traits/primitives.rs
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
use private::PrimitiveNumSealed;
|
||||||
|
|
||||||
|
use super::{Float, Integer, Numeric, Signed, SqrtReal, SqrtUnit, Unsigned, Widen, WidenInto};
|
||||||
|
|
||||||
|
mod private {
|
||||||
|
pub trait PrimitiveNumSealed: Copy + Clone {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PrimitiveNumSealed for u8 {}
|
||||||
|
impl PrimitiveNumSealed for u16 {}
|
||||||
|
impl PrimitiveNumSealed for u32 {}
|
||||||
|
impl PrimitiveNumSealed for u64 {}
|
||||||
|
impl PrimitiveNumSealed for u128 {}
|
||||||
|
impl PrimitiveNumSealed for usize {}
|
||||||
|
impl PrimitiveNumSealed for i8 {}
|
||||||
|
impl PrimitiveNumSealed for i16 {}
|
||||||
|
impl PrimitiveNumSealed for i32 {}
|
||||||
|
impl PrimitiveNumSealed for i64 {}
|
||||||
|
impl PrimitiveNumSealed for i128 {}
|
||||||
|
impl PrimitiveNumSealed for isize {}
|
||||||
|
impl PrimitiveNumSealed for f32 {}
|
||||||
|
impl PrimitiveNumSealed for f64 {}
|
||||||
|
|
||||||
|
/// A marker trait used to define only primitive Rust number types.
|
||||||
|
pub trait PrimitiveNum: Numeric {}
|
||||||
|
impl<T: PrimitiveNumSealed + Numeric> PrimitiveNum for T {}
|
||||||
|
|
||||||
|
macro_rules! impl_numeric_for_primitive_int {
|
||||||
|
($unit:ty) => {
|
||||||
|
impl Numeric for $unit {
|
||||||
|
const ZERO: Self = 0;
|
||||||
|
const ONE: Self = 1;
|
||||||
|
const TWO: Self = 2;
|
||||||
|
const MAX: Self = <$unit>::MAX;
|
||||||
|
const MIN: Self = <$unit>::MIN;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_numeric_for_primitive_float {
|
||||||
|
($unit:ty) => {
|
||||||
|
impl Numeric for $unit {
|
||||||
|
const ZERO: Self = 0.0;
|
||||||
|
const ONE: Self = 1.0;
|
||||||
|
const TWO: Self = 2.0;
|
||||||
|
const MAX: Self = <$unit>::MAX;
|
||||||
|
const MIN: Self = <$unit>::MIN;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_numeric_for_primitive_int!(u8);
|
||||||
|
impl_numeric_for_primitive_int!(u16);
|
||||||
|
impl_numeric_for_primitive_int!(u32);
|
||||||
|
impl_numeric_for_primitive_int!(u64);
|
||||||
|
impl_numeric_for_primitive_int!(u128);
|
||||||
|
impl_numeric_for_primitive_int!(usize);
|
||||||
|
impl_numeric_for_primitive_int!(i8);
|
||||||
|
impl_numeric_for_primitive_int!(i16);
|
||||||
|
impl_numeric_for_primitive_int!(i32);
|
||||||
|
impl_numeric_for_primitive_int!(i64);
|
||||||
|
impl_numeric_for_primitive_int!(i128);
|
||||||
|
impl_numeric_for_primitive_int!(isize);
|
||||||
|
impl_numeric_for_primitive_float!(f32);
|
||||||
|
impl_numeric_for_primitive_float!(f64);
|
||||||
|
|
||||||
|
impl Integer for u8 {}
|
||||||
|
impl Integer for u16 {}
|
||||||
|
impl Integer for u32 {}
|
||||||
|
impl Integer for u64 {}
|
||||||
|
impl Integer for u128 {}
|
||||||
|
impl Integer for usize {}
|
||||||
|
impl Integer for i8 {}
|
||||||
|
impl Integer for i16 {}
|
||||||
|
impl Integer for i32 {}
|
||||||
|
impl Integer for i64 {}
|
||||||
|
impl Integer for i128 {}
|
||||||
|
impl Integer for isize {}
|
||||||
|
|
||||||
|
impl Float for f32 {}
|
||||||
|
impl Float for f64 {}
|
||||||
|
|
||||||
|
impl Signed for i8 {}
|
||||||
|
impl Signed for i16 {}
|
||||||
|
impl Signed for i32 {}
|
||||||
|
impl Signed for i64 {}
|
||||||
|
impl Signed for i128 {}
|
||||||
|
impl Signed for isize {}
|
||||||
|
impl Signed for f32 {}
|
||||||
|
impl Signed for f64 {}
|
||||||
|
|
||||||
|
impl Unsigned for u8 {}
|
||||||
|
impl Unsigned for u16 {}
|
||||||
|
impl Unsigned for u32 {}
|
||||||
|
impl Unsigned for u64 {}
|
||||||
|
impl Unsigned for u128 {}
|
||||||
|
impl Unsigned for usize {}
|
||||||
|
|
||||||
|
macro_rules! impl_unit_isqrt_unit {
|
||||||
|
($unit:ty) => {
|
||||||
|
impl SqrtUnit for $unit {
|
||||||
|
fn sqrt_unit(self) -> Self {
|
||||||
|
self.isqrt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_unit_sqrt_unit {
|
||||||
|
($unit:ty) => {
|
||||||
|
impl SqrtUnit for $unit {
|
||||||
|
fn sqrt_unit(self) -> Self {
|
||||||
|
self.sqrt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_sqrt_real {
|
||||||
|
($unit:ty) => {
|
||||||
|
impl SqrtReal for $unit {
|
||||||
|
fn sqrt_real(self) -> f64 {
|
||||||
|
Into::<f64>::into(self).sqrt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_unit_isqrt_unit!(u8);
|
||||||
|
impl_unit_isqrt_unit!(u16);
|
||||||
|
impl_unit_isqrt_unit!(u32);
|
||||||
|
impl_unit_isqrt_unit!(u64);
|
||||||
|
impl_unit_isqrt_unit!(u128);
|
||||||
|
impl_unit_isqrt_unit!(usize);
|
||||||
|
impl_unit_isqrt_unit!(i8);
|
||||||
|
impl_unit_isqrt_unit!(i16);
|
||||||
|
impl_unit_isqrt_unit!(i32);
|
||||||
|
impl_unit_isqrt_unit!(i64);
|
||||||
|
impl_unit_isqrt_unit!(i128);
|
||||||
|
impl_unit_isqrt_unit!(isize);
|
||||||
|
impl_unit_sqrt_unit!(f32);
|
||||||
|
impl_unit_sqrt_unit!(f64);
|
||||||
|
|
||||||
|
impl_sqrt_real!(u8);
|
||||||
|
impl_sqrt_real!(u16);
|
||||||
|
impl_sqrt_real!(u32);
|
||||||
|
impl_sqrt_real!(i8);
|
||||||
|
impl_sqrt_real!(i16);
|
||||||
|
impl_sqrt_real!(i32);
|
||||||
|
impl_sqrt_real!(f32);
|
||||||
|
impl_sqrt_real!(f64);
|
||||||
|
|
||||||
|
macro_rules! impl_widen_into {
|
||||||
|
($from:ty => [$($to:ty),+]) => {
|
||||||
|
$(
|
||||||
|
impl WidenInto<$to> for $from { fn widen_into(self) -> $to { self as $to } }
|
||||||
|
)+
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_widen {
|
||||||
|
($from:ty => $to:ty) => {
|
||||||
|
impl Widen for $from {
|
||||||
|
type Target=$to;
|
||||||
|
|
||||||
|
fn widen(self) -> $to {
|
||||||
|
self as $to
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_widen!(u8 => u16);
|
||||||
|
impl_widen!(u16 => u32);
|
||||||
|
impl_widen!(u32 => u64);
|
||||||
|
impl_widen!(u64 => u128);
|
||||||
|
impl_widen!(i8 => i16);
|
||||||
|
impl_widen!(i16 => i32);
|
||||||
|
impl_widen!(i32 => i64);
|
||||||
|
impl_widen!(i64 => i128);
|
||||||
|
impl_widen!(f32 => f64);
|
||||||
|
|
||||||
|
// Additional widen options for the primitive types
|
||||||
|
impl_widen_into!(u8 => [u32, u64, u128, usize]);
|
||||||
|
impl_widen_into!(u16 => [u64, u128, usize]);
|
||||||
|
impl_widen_into!(u32 => [u128, usize]);
|
||||||
|
impl_widen_into!(u64 => [usize]);
|
||||||
|
impl_widen_into!(i8 => [i32, i64, i128, isize]);
|
||||||
|
impl_widen_into!(i16 => [i64, i128, isize]);
|
||||||
|
impl_widen_into!(i32 => [i128, isize]);
|
||||||
|
impl_widen_into!(i64 => [isize]);
|
||||||
Reference in New Issue
Block a user