strafe-client-jed/fixed_wide_vectors/src/macros/vector.rs

200 lines
5.7 KiB
Rust
Raw Normal View History

2024-08-30 19:05:52 +00:00
// Stolen from https://github.com/c1m50c/fixed-vectors (MIT license)
#[doc(hidden)]
#[macro_export(local_inner_macros)]
macro_rules! impl_vector {
2024-09-03 16:20:43 +00:00
( $struct: ident { $($field: ident), + }, $size: expr ) => {
$crate::impl_common!($struct { $($field), + }, $size);
2024-08-30 19:05:52 +00:00
impl<T> From<[T; $size]> for $struct<T> {
fn from(from: [T; $size]) -> Self {
let mut iterator = from.into_iter();
Self {
// SAFETY: We know the size of `from` so `iterator.next()` is always `Some(..)`
$( $field: unsafe { iterator.next().unwrap_unchecked() } ), +
}
}
}
impl<T: core::fmt::Debug> core::fmt::Debug for $struct<T> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let identifier = core::stringify!($struct);
f.debug_struct(identifier)
$( .field( core::stringify!($field), &self.$field ) ) +
.finish()
}
}
impl<T: PartialEq> PartialEq for $struct<T> {
fn eq(&self, other: &Self) -> bool {
$( self.$field == other.$field ) && +
}
}
impl<T: Eq> Eq for $struct<T> { }
impl<T: core::hash::Hash> core::hash::Hash for $struct<T> {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
$( self.$field.hash(state); ) +
}
}
impl<T: Clone> Clone for $struct<T> {
fn clone(&self) -> Self {
Self {
$( $field: self.$field.clone() ), +
}
}
}
impl<T: Copy> Copy for $struct<T> { }
impl<T: Default> Default for $struct<T> {
fn default() -> Self {
Self {
$( $field: T::default() ), +
}
}
}
impl<T: Ord> $struct<T> {
pub fn min(self, rhs: Self) -> $struct<T> {
$struct{
$( $field: self.$field.min(rhs.$field) ), +
}
}
pub fn max(self, rhs: Self) -> $struct<T> {
$struct{
$( $field: self.$field.max(rhs.$field) ), +
}
}
pub fn cmp(self, rhs: Self) -> $struct<core::cmp::Ordering> {
$struct{
$( $field: self.$field.cmp(&rhs.$field) ), +
}
}
pub fn lt(self, rhs: Self) -> $struct<bool> {
$struct{
$( $field: self.$field.lt(&rhs.$field) ), +
}
}
pub fn gt(self, rhs: Self) -> $struct<bool> {
$struct{
$( $field: self.$field.gt(&rhs.$field) ), +
}
}
pub fn ge(self, rhs: Self) -> $struct<bool> {
$struct{
$( $field: self.$field.ge(&rhs.$field) ), +
}
}
pub fn le(self, rhs: Self) -> $struct<bool> {
$struct{
$( $field: self.$field.le(&rhs.$field) ), +
}
}
}
impl $struct<bool>{
pub fn all(&self)->bool{
const ALL:[bool;$size]=[true;$size];
core::matches!(self.to_array(),ALL)
}
pub fn any(&self)->bool{
$( self.$field )|| +
}
}
impl<T: core::ops::Neg<Output = T>> core::ops::Neg for $struct<T> {
type Output = Self;
fn neg(self) -> Self::Output {
Self {
$( $field: -self.$field ), +
}
}
}
// Impl arithmetic pperators
$crate::impl_vector_operator!( $struct { $($field), + }, AddAssign, add_assign );
$crate::impl_vector_operator!( $struct { $($field), + }, Add, add, Self );
$crate::impl_vector_operator!( $struct { $($field), + }, SubAssign, sub_assign );
$crate::impl_vector_operator!( $struct { $($field), + }, Sub, sub, Self );
$crate::impl_vector_operator!( $struct { $($field), + }, MulAssign, mul_assign );
$crate::impl_vector_operator!( $struct { $($field), + }, Mul, mul, Self );
$crate::impl_vector_operator!( $struct { $($field), + }, DivAssign, div_assign );
$crate::impl_vector_operator!( $struct { $($field), + }, Div, div, Self );
$crate::impl_vector_operator!( $struct { $($field), + }, RemAssign, rem_assign );
$crate::impl_vector_operator!( $struct { $($field), + }, Rem, rem, Self );
// Impl bitwise operators
$crate::impl_vector_operator!( $struct { $($field), + }, BitAndAssign, bitand_assign );
$crate::impl_vector_operator!( $struct { $($field), + }, BitAnd, bitand, Self );
$crate::impl_vector_operator!( $struct { $($field), + }, BitOrAssign, bitor_assign );
$crate::impl_vector_operator!( $struct { $($field), + }, BitOr, bitor, Self );
$crate::impl_vector_operator!( $struct { $($field), + }, BitXorAssign, bitxor_assign );
$crate::impl_vector_operator!( $struct { $($field), + }, BitXor, bitxor, Self );
// Impl floating-point based methods
2024-09-03 00:41:54 +00:00
#[cfg(feature="fixed_wide")]
2024-08-30 19:05:52 +00:00
$crate::impl_wide_vector_operations!( $struct { $($field), + }, $size );
};
}
2024-08-30 19:41:25 +00:00
#[doc(hidden)]
#[macro_export(local_inner_macros)]
2024-08-30 20:49:23 +00:00
macro_rules! impl_extend {
2024-08-30 20:25:50 +00:00
( $struct: ident { $($field: ident), + }, $struct_extended: ident, $field_extended: ident ) => {
2024-08-30 19:41:25 +00:00
impl<T> $struct<T> {
#[inline(always)]
pub fn extend(self,value:T) -> $struct_extended<T> {
$struct_extended {
$( $field:self.$field, ) +
$field_extended:value
}
}
}
};
}
2024-08-30 19:05:52 +00:00
#[doc(hidden)]
#[macro_export(local_inner_macros)]
macro_rules! impl_vector_operator {
( $struct: ident { $($field: ident), + }, $trait: ident, $method: ident, $output: ty ) => {
impl<T:core::ops::$trait<Output=T>> core::ops::$trait for $struct<T> {
type Output = $output;
fn $method(self, other: Self) -> Self::Output {
Self {
$( $field: self.$field.$method(other.$field) ), +
}
}
}
impl<T:core::ops::$trait<Output=T>+Copy> core::ops::$trait<T> for $struct<T>{
type Output = $output;
fn $method(self, other: T) -> Self::Output {
$struct {
$( $field: self.$field.$method(other) ), +
}
}
}
};
( $struct: ident { $($field: ident), + }, $trait: ident, $method: ident ) => {
impl<T: core::ops::$trait> core::ops::$trait for $struct<T> {
fn $method(&mut self, other: Self) {
$( self.$field.$method(other.$field) ); +
}
}
impl<T: core::ops::$trait + Copy> core::ops::$trait<T> for $struct<T> {
fn $method(&mut self, other: T) {
$( self.$field.$method(other) ); +
}
}
};
}