diff --git a/fixed_wide/src/wide.rs b/fixed_wide/src/wide.rs index ff46c6b..192bead 100644 --- a/fixed_wide/src/wide.rs +++ b/fixed_wide/src/wide.rs @@ -1,6 +1,6 @@ use bnum::cast::As; use bnum::types::{I256,I512}; -use fixed::FixedI128; +use fixed::{FixedI64,FixedI128}; use typenum::{Sum,Unsigned}; #[derive(Clone,Copy,Debug)] @@ -33,6 +33,16 @@ pub trait WideMul{ } //going wide from foreign fixed type +impl WideMul> for FixedI64 + where + A:std::ops::Add, + B:Unsigned, +{ + type Output=FixedI128>; + fn wide_mul(self,rhs:FixedI64)->Self::Output{ + self.wide_mul(rhs) + } +} impl WideMul> for FixedI128 where A:std::ops::Add, diff --git a/src/macros/mod.rs b/src/macros/mod.rs index 4e65a86..912565a 100644 --- a/src/macros/mod.rs +++ b/src/macros/mod.rs @@ -1,5 +1,5 @@ // Stolen from https://github.com/c1m50c/fixed-vectors (MIT license) -mod wide; +pub mod wide; #[doc(hidden)] #[macro_export(local_inner_macros)] @@ -196,7 +196,7 @@ macro_rules! impl_vector { $crate::impl_operator!( $struct { $($field), + }, BitXor, bitxor, Self ); // Impl floating-point based methods - //$crate::impl_floating_point_operations!( $struct { $($field), + }, $size ); + $crate::impl_wide_operations!( $struct { $($field), + }, $size ); }; } diff --git a/src/macros/wide.rs b/src/macros/wide.rs index 23b4527..3b348a2 100644 --- a/src/macros/wide.rs +++ b/src/macros/wide.rs @@ -1,281 +1,32 @@ #[doc(hidden)] #[macro_export(local_inner_macros)] -macro_rules! impl_floating_point_operations { +macro_rules! impl_wide_operations { ( $struct: ident { $($field: ident), + }, $size: expr ) => { - impl $struct { - /// Returns the dot product of two vectors. - /// - /// # Example - /// - /// ``` - /// use fixed_vectors::Vector2; - /// - /// let a = Vector2::new(1.0, 2.0); - /// let b = Vector2::new(2.0, 4.0); - /// let dot = a.dot(&b); - /// - /// assert_eq!(dot, 10.0); - /// ``` + impl> fixed_wide::wide::WideMul for $struct { + type Output=$struct; #[inline] - pub fn dot(&self, other: &Self) -> T { + fn wide_mul(self, rhs: Self) -> Self::Output { + $struct{ + $( $field: self.$field.wide_mul(rhs.$field) ), + + } + } + } + impl+std::ops::Add> $struct { + #[inline] + pub fn wide_dot(&self, other: &Self) -> ::Output { $crate::sum_repeating!( - $( + (self.$field * other.$field) ) + + $( + (self.$field.wide_mul(other.$field)) ) + ) } - - /// Returns the squared magnitude of vector. - /// - /// # Example - /// - /// ``` - /// use fixed_vectors::Vector3; - /// - /// let vec3 = Vector3::new(3.33, 2.04, 1.337); - /// let lsq = vec3.length_squared(); - /// - /// assert!(lsq >= 17.0); - /// ``` - pub fn length_squared(&self) -> T { + pub fn length_squared(&self) -> ::Output { let squared = Self { - $( $field: self.$field * self.$field ), + + $( $field: self.$field.wide_mul(self.$field) ), + }; $crate::sum_repeating!( $( + squared.$field ) + ) } - - /// Applies [`floor`](num_traits::float::FloatCore::floor) on all fields within the vector, - /// converting each field to the largest integer less than or equal to its value. - /// - /// # Example - /// - /// ``` - /// use fixed_vectors::Vector2; - /// - /// let vec2 = Vector2::new(1.6, 2.3).floor(); - /// - /// assert_eq!(vec2, Vector2::new(1.0, 2.0)); - /// ``` - #[inline] - pub fn floor(self) -> Self { - self.map(T::floor) - } - - /// Applies [`ceil`](num_traits::float::FloatCore::ceil) on all fields within the vector, - /// converting each field to the largest integer greater than or equal to its value. - /// - /// # Example - /// - /// ``` - /// use fixed_vectors::Vector2; - /// - /// let vec2 = Vector2::new(1.6, 2.3).ceil(); - /// - /// assert_eq!(vec2, Vector2::new(2.0, 3.0)); - /// ``` - #[inline] - pub fn ceil(self) -> Self { - self.map(T::ceil) - } - - /// Applies [`round`](num_traits::float::FloatCore::round) on all fields within the vector, - /// converting each field's value to its nearest integer. - /// - /// # Example - /// - /// ``` - /// use fixed_vectors::Vector2; - /// - /// let vec2 = Vector2::new(1.6, 2.3).round(); - /// - /// assert_eq!(vec2, Vector2::new(2.0, 2.0)); - /// ``` - #[inline] - pub fn round(self) -> Self { - self.map(T::round) - } - - /// Applies [`abs`](num_traits::float::FloatCore::abs) on all fields within the vector, - /// converting each field to their absolute value. - /// - /// # Example - /// - /// ``` - /// use fixed_vectors::Vector2; - /// - /// let vec2 = Vector2::new(-2.6, 2.3).abs(); - /// - /// assert_eq!(vec2, Vector2::new(2.6, 2.3)); - /// ``` - #[inline] - pub fn abs(self) -> Self { - self.map(T::abs) - } - - /// Applies [`trunc`](num_traits::float::FloatCore::trunc) on all fields within the vector, - /// converting each field's value to their integer parts. - /// - /// # Example - /// - /// ``` - /// use fixed_vectors::Vector2; - /// - /// let vec2 = Vector2::new(-2.6, 2.3).trunc(); - /// - /// assert_eq!(vec2, Vector2::new(-2.0, 2.0)); - /// ``` - #[inline] - pub fn trunc(self) -> Self { - self.map(T::trunc) - } - - /// Applies [`fract`](num_traits::float::FloatCore::fract) on all fields within the vector, - /// converting each field's value to their fractional parts. - /// - /// # Example - /// - /// ``` - /// use fixed_vectors::Vector2; - /// - /// let vec2 = Vector2::new(-2.5, 2.25).fract(); - /// - /// assert_eq!(vec2, Vector2::new(-0.5, 0.25)); - /// ``` - #[inline] - pub fn fract(self) -> Self { - self.map(T::fract) - } - - /// Applies [`powi`](num_traits::float::FloatCore::powi) on all fields within the vector, - /// raising each field's value to an integer power. - /// - /// # Example - /// - /// ``` - /// use fixed_vectors::Vector2; - /// - /// let vec2 = Vector2::new(2.0, 4.0).powi(2); - /// - /// assert_eq!(vec2, Vector2::new(4.0, 16.0)); - /// ``` - #[inline] - pub fn powi(self, n: i32) -> Self { - self.map(|f| f.powi(n)) - } - - /// Linearly interpolates between two Vectors by a normalized `weight`. - /// - /// # Example - /// - /// ``` - /// use fixed_vectors::Vector2; - /// - /// let vec2 = Vector2::new(1.0, 2.0).lerp( - /// Vector2::new(2.0, 3.0), 1.0 - /// ); - /// - /// assert_eq!(vec2, Vector2::new(2.0, 3.0)); - /// ``` - #[inline(always)] - pub fn lerp(self, to: Self, weight: T) -> Self { - Self { - $( $field: self.$field + (weight * (to.$field - self.$field)) ), + - } - } - } - - impl $struct - where - T: $crate::macros::floating::_FloatingPoint - + num_traits::float::FloatCore - { - /// Consumes the vector and returns it with all of its fields converted to their square-root. - /// - /// # Example - /// - /// ``` - /// use fixed_vectors::Vector2; - /// - /// let vec2 = Vector2::new(64.0, 25.0).sqrt(); - /// - /// assert_eq!(vec2, Vector2::new(8.0, 5.0)); - /// ``` - #[inline] - pub fn sqrt(self) -> Self { - self.map(T::sqrt) - } - - /// Returns the magnitude of the vector. - /// - /// # Example - /// - /// ``` - /// use fixed_vectors::Vector3; - /// - /// let vec3 = Vector3::new(1.5, 2.0, 3.33); - /// let length = vec3.length(); - /// - /// assert!(length < 4.2); - /// ``` - #[inline] - pub fn length(&self) -> T { - self.length_squared().sqrt() - } - - /// Consumes the vector and returns it as normalized vector. - /// - /// # Example - /// - /// ``` - /// use fixed_vectors::Vector2; - /// - /// let vec2 = Vector2::new(14.3, 7.9).normalized(); - /// - /// assert!(vec2.x < 1.0); - /// assert!(vec2.y < 1.0); - /// ``` - pub fn normalized(self) -> Self { - let length_squared = self.length_squared(); - - if length_squared == T::zero() { - return Self { $( $field: T::zero() ), + }; - } - - let length = length_squared.sqrt(); - - Self { - $( $field: self.$field / length ), + - } - } - - /// Normalizes the vector through mutation. - /// - /// # Example - /// - /// ``` - /// use fixed_vectors::Vector2; - /// - /// let mut vec2 = Vector2::new(14.3, 7.9); - /// vec2.normalize(); - /// - /// assert!(vec2.x < 1.0); - /// assert!(vec2.y < 1.0); - /// ``` - pub fn normalize(&mut self) { - let length_squared = self.length_squared(); - - if length_squared == T::zero() { - *self = Self { $( $field: T::zero() ), + }; - return; - } - - let length = length_squared.sqrt(); - - *self = Self { - $( $field: self.$field / length ), + - } - } } }; } @@ -290,26 +41,3 @@ macro_rules! sum_repeating { $($item) * }; } - - -// Required trait for `sqrt` impls -#[doc(hidden)] -pub trait _FloatingPoint { - fn sqrt(self) -> Self; -} - - -impl _FloatingPoint for f32 { - #[inline(always)] - fn sqrt(self) -> Self { - libm::sqrtf(self) - } -} - - -impl _FloatingPoint for f64 { - #[inline(always)] - fn sqrt(self) -> Self { - libm::sqrt(self) - } -} diff --git a/src/tests/mod.rs b/src/tests/mod.rs index c91a008..c0767c7 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -18,7 +18,7 @@ fn it_works() { } #[test] -pub fn main(){ - let max=i32::MAX as i64; - println!("{} {}",max*max,i64::MAX); +pub fn wide_vec3(){ + let v=crate::vector::Vector3::from_value(Planar64::from(1)); + let v1=v.wide_mul(v); }