use num::{One, Zero}; use std::ops::{ Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign, }; use alga::general::{ClosedAdd, ClosedDiv, ClosedMul, ClosedNeg, ClosedSub}; use crate::base::allocator::{Allocator, SameShapeAllocator}; use crate::base::constraint::{AreMultipliable, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint}; use crate::base::dimension::{Dim, DimName, U1}; use crate::base::storage::Storage; use crate::base::{DefaultAllocator, Matrix, Scalar, Vector, VectorSum}; use crate::geometry::Point; /* * * Indexing. * */ impl Index for Point where DefaultAllocator: Allocator { type Output = N; #[inline] fn index(&self, i: usize) -> &Self::Output { &self.coords[i] } } impl IndexMut for Point where DefaultAllocator: Allocator { #[inline] fn index_mut(&mut self, i: usize) -> &mut Self::Output { &mut self.coords[i] } } /* * * Neg. * */ impl Neg for Point where DefaultAllocator: Allocator { type Output = Self; #[inline] fn neg(self) -> Self::Output { Self::Output::from(-self.coords) } } impl<'a, N: Scalar + ClosedNeg, D: DimName> Neg for &'a Point where DefaultAllocator: Allocator { type Output = Point; #[inline] fn neg(self) -> Self::Output { Self::Output::from(-&self.coords) } } /* * * Subtraction & Addition. * */ // Point - Point add_sub_impl!(Sub, sub, ClosedSub; (D, U1), (D, U1) for D: DimName; self: &'a Point, right: &'b Point, Output = VectorSum; &self.coords - &right.coords; 'a, 'b); add_sub_impl!(Sub, sub, ClosedSub; (D, U1), (D, U1) for D: DimName; self: &'a Point, right: Point, Output = VectorSum; &self.coords - right.coords; 'a); add_sub_impl!(Sub, sub, ClosedSub; (D, U1), (D, U1) for D: DimName; self: Point, right: &'b Point, Output = VectorSum; self.coords - &right.coords; 'b); add_sub_impl!(Sub, sub, ClosedSub; (D, U1), (D, U1) for D: DimName; self: Point, right: Point, Output = VectorSum; self.coords - right.coords; ); // Point - Vector add_sub_impl!(Sub, sub, ClosedSub; (D1, U1), (D2, U1) -> (D1) for D1: DimName, 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; (D1, U1), (D2, U1) -> (D1) for D1: DimName, D2: Dim, SB: Storage; self: &'a Point, right: Vector, Output = Point; Self::Output::from(&self.coords - &right); 'a); // FIXME: should not be a ref to `right`. add_sub_impl!(Sub, sub, ClosedSub; (D1, U1), (D2, U1) -> (D1) for D1: DimName, D2: Dim, SB: Storage; self: Point, right: &'b Vector, Output = Point; Self::Output::from(self.coords - right); 'b); add_sub_impl!(Sub, sub, ClosedSub; (D1, U1), (D2, U1) -> (D1) for D1: DimName, D2: Dim, SB: Storage; self: Point, right: Vector, Output = Point; Self::Output::from(self.coords - right); ); // Point + Vector add_sub_impl!(Add, add, ClosedAdd; (D1, U1), (D2, U1) -> (D1) for D1: DimName, 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; (D1, U1), (D2, U1) -> (D1) for D1: DimName, D2: Dim, SB: Storage; self: &'a Point, right: Vector, Output = Point; Self::Output::from(&self.coords + &right); 'a); // FIXME: should not be a ref to `right`. add_sub_impl!(Add, add, ClosedAdd; (D1, U1), (D2, U1) -> (D1) for D1: DimName, D2: Dim, SB: Storage; self: Point, right: &'b Vector, Output = Point; Self::Output::from(self.coords + right); 'b); add_sub_impl!(Add, add, ClosedAdd; (D1, U1), (D2, U1) -> (D1) for D1: DimName, D2: Dim, SB: Storage; self: Point, right: Vector, Output = Point; Self::Output::from(self.coords + right); ); // XXX: replace by the shared macro: add_sub_assign_impl macro_rules! op_assign_impl( ($($TraitAssign: ident, $method_assign: ident, $bound: ident);* $(;)*) => {$( impl<'b, N, D1: DimName, D2: Dim, SB> $TraitAssign<&'b Vector> for Point where N: Scalar + $bound, SB: Storage, DefaultAllocator: Allocator, ShapeConstraint: SameNumberOfRows { #[inline] fn $method_assign(&mut self, right: &'b Vector) { self.coords.$method_assign(right) } } impl $TraitAssign> for Point where N: Scalar + $bound, SB: Storage, DefaultAllocator: Allocator, ShapeConstraint: SameNumberOfRows { #[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; (R1, C1), (D2, U1) for R1: DimName, C1: Dim, D2: DimName, SA: Storage where ShapeConstraint: AreMultipliable; self: Matrix, 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 where DefaultAllocator: Allocator { type Output = Point; #[inline] fn $method(self, right: N) -> Self::Output { Point::from(self.coords.$method(right)) } } impl<'a, N: Scalar + $bound, D: DimName> $Trait for &'a Point where DefaultAllocator: Allocator { type Output = Point; #[inline] fn $method(self, right: N) -> Self::Output { Point::from((&self.coords).$method(right)) } } impl $TraitAssign for Point where DefaultAllocator: Allocator { #[inline] fn $method_assign(&mut self, right: N) { 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 where DefaultAllocator: Allocator<$T, D> { type Output = Point<$T, D>; #[inline] fn mul(self, right: Point<$T, D>) -> Self::Output { Point::from(self * right.coords) } } impl<'b, D: DimName> Mul<&'b Point<$T, D>> for $T where DefaultAllocator: Allocator<$T, D> { 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);