use num::{One, Zero}; use std::ops::{ Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign, }; use simba::scalar::{ClosedAdd, ClosedDiv, ClosedMul, ClosedNeg, ClosedSub}; use crate::base::allocator::{Allocator, SameShapeAllocator}; use crate::base::constraint::{ AreMultipliable, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint, }; use crate::base::dimension::{Dim, U1}; use crate::base::storage::Storage; use crate::base::{Const, DefaultAllocator, Matrix, Scalar, Vector, VectorSum}; use crate::geometry::Point; /* * * Indexing. * */ impl Index for Point { type Output = T; #[inline] fn index(&self, i: usize) -> &Self::Output { &self.coords[i] } } impl IndexMut for Point { #[inline] fn index_mut(&mut self, i: usize) -> &mut Self::Output { &mut self.coords[i] } } /* * * Neg. * */ impl Neg for Point { type Output = Self; #[inline] fn neg(self) -> Self::Output { Self::Output::from(-self.coords) } } impl<'a, T: Scalar + ClosedNeg, const D: usize> Neg for &'a Point { type Output = Point; #[inline] fn neg(self) -> Self::Output { Self::Output::from(-&self.coords) } } /* * * Subtraction & Addition. * */ // Point - Point add_sub_impl!(Sub, sub, ClosedSub; (Const, U1), (Const, U1) const D; for; where; self: &'a Point, right: &'b Point, Output = VectorSum, Const>; &self.coords - &right.coords; 'a, 'b); add_sub_impl!(Sub, sub, ClosedSub; (Const, U1), (Const, U1) const D; for; where; self: &'a Point, right: Point, Output = VectorSum, Const>; &self.coords - right.coords; 'a); add_sub_impl!(Sub, sub, ClosedSub; (Const, U1), (Const, U1) const D; for; where; self: Point, right: &'b Point, Output = VectorSum, Const>; self.coords - &right.coords; 'b); add_sub_impl!(Sub, sub, ClosedSub; (Const, U1), (Const, U1) const D; for; where; self: Point, right: Point, Output = VectorSum, Const>; self.coords - right.coords; ); // Point - Vector add_sub_impl!(Sub, sub, ClosedSub; (Const, U1), (D2, U1) -> (Const) const D1; for D2, SB; where D2: Dim, SB: Storage; self: &'a Point, right: &'b Vector, Output = Point; Self::Output::from(&self.coords - right); 'a, 'b); add_sub_impl!(Sub, sub, ClosedSub; (Const, U1), (D2, U1) -> (Const) const D1; for D2, SB; where D2: Dim, SB: Storage; self: &'a Point, right: Vector, Output = Point; Self::Output::from(&self.coords - &right); 'a); // TODO: should not be a ref to `right`. add_sub_impl!(Sub, sub, ClosedSub; (Const, U1), (D2, U1) -> (Const) const D1; for D2, SB; where D2: Dim, SB: Storage; self: Point, right: &'b Vector, Output = Point; Self::Output::from(self.coords - right); 'b); add_sub_impl!(Sub, sub, ClosedSub; (Const, U1), (D2, U1) -> (Const) const D1; for D2, SB; where D2: Dim, SB: Storage; self: Point, right: Vector, Output = Point; Self::Output::from(self.coords - right); ); // Point + Vector add_sub_impl!(Add, add, ClosedAdd; (Const, U1), (D2, U1) -> (Const) const D1; for D2, SB; where D2: Dim, SB: Storage; self: &'a Point, right: &'b Vector, Output = Point; Self::Output::from(&self.coords + right); 'a, 'b); add_sub_impl!(Add, add, ClosedAdd; (Const, U1), (D2, U1) -> (Const) const D1; for D2, SB; where D2: Dim, SB: Storage; self: &'a Point, right: Vector, Output = Point; Self::Output::from(&self.coords + &right); 'a); // TODO: should not be a ref to `right`. add_sub_impl!(Add, add, ClosedAdd; (Const, U1), (D2, U1) -> (Const) const D1; for D2, SB; where D2: Dim, SB: Storage; self: Point, right: &'b Vector, Output = Point; Self::Output::from(self.coords + right); 'b); add_sub_impl!(Add, add, ClosedAdd; (Const, U1), (D2, U1) -> (Const) const D1; for D2, SB; where D2: Dim, SB: Storage; self: Point, right: Vector, Output = Point; Self::Output::from(self.coords + right); ); // TODO: replace by the shared macro: add_sub_assign_impl? macro_rules! op_assign_impl( ($($TraitAssign: ident, $method_assign: ident, $bound: ident);* $(;)*) => {$( impl<'b, T, D2: Dim, SB, const D1: usize> $TraitAssign<&'b Vector> for Point where T: Scalar + $bound, SB: Storage, ShapeConstraint: SameNumberOfRows, D2> { #[inline] fn $method_assign(&mut self, right: &'b Vector) { self.coords.$method_assign(right) } } impl $TraitAssign> for Point where T: Scalar + $bound, SB: Storage, ShapeConstraint: SameNumberOfRows, D2> { #[inline] fn $method_assign(&mut self, right: Vector) { self.coords.$method_assign(right) } } )*} ); op_assign_impl!( AddAssign, add_assign, ClosedAdd; SubAssign, sub_assign, ClosedSub; ); /* * * Matrix × Point * */ md_impl_all!( Mul, mul; (Const, Const), (Const, U1) const D2, R1, C1; for SA; where SA: Storage, Const>, ShapeConstraint: AreMultipliable, Const, Const, U1>; self: Matrix, Const, SA>, right: Point, Output = Point; [val val] => Point::from(self * right.coords); [ref val] => Point::from(self * right.coords); [val ref] => Point::from(self * &right.coords); [ref ref] => Point::from(self * &right.coords); ); /* * * Point ×/÷ Scalar * */ macro_rules! componentwise_scalarop_impl( ($Trait: ident, $method: ident, $bound: ident; $TraitAssign: ident, $method_assign: ident) => { impl $Trait for Point { type Output = Point; #[inline] fn $method(self, right: T) -> Self::Output { Point::from(self.coords.$method(right)) } } impl<'a, T: Scalar + $bound, const D: usize> $Trait for &'a Point { type Output = Point; #[inline] fn $method(self, right: T) -> Self::Output { Point::from((&self.coords).$method(right)) } } impl $TraitAssign for Point /* where DefaultAllocator: Allocator */ { #[inline] fn $method_assign(&mut self, right: T) { self.coords.$method_assign(right) } } } ); componentwise_scalarop_impl!(Mul, mul, ClosedMul; MulAssign, mul_assign); componentwise_scalarop_impl!(Div, div, ClosedDiv; DivAssign, div_assign); macro_rules! left_scalar_mul_impl( ($($T: ty),* $(,)*) => {$( impl Mul> for $T { type Output = Point<$T, D>; #[inline] fn mul(self, right: Point<$T, D>) -> Self::Output { Point::from(self * right.coords) } } impl<'b, const D: usize> Mul<&'b Point<$T, D>> for $T { type Output = Point<$T, D>; #[inline] fn mul(self, right: &'b Point<$T, D>) -> Self::Output { Point::from(self * &right.coords) } } )*} ); left_scalar_mul_impl!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize, f32, f64);