diff --git a/src/matrix/mat.rs b/src/matrix/mat.rs index 3cb0484..f9db3d9 100644 --- a/src/matrix/mat.rs +++ b/src/matrix/mat.rs @@ -520,40 +520,72 @@ impl_elementwise_op_scalar_all!(Mul, mul, *); impl_elementwise_op_scalar_all!(Div, div, /); /// Generates element-wise bitwise operations for boolean matrices. -macro_rules! impl_bitwise_op { +macro_rules! impl_bitwise_op_all { ($OpTrait:ident, $method:ident, $op:tt) => { - impl<'a, 'b> std::ops::$OpTrait<&'b Matrix> for &'a Matrix { + // &Matrix OP &Matrix + impl<'a, 'b> $OpTrait<&'b Matrix> for &'a Matrix { type Output = Matrix; - fn $method(self, rhs: &'b Matrix) -> Matrix { - // Ensure both matrices have identical dimensions - assert_eq!(self.rows, rhs.rows, "row count mismatch"); - assert_eq!(self.cols, rhs.cols, "col count mismatch"); - // Apply the bitwise operation element-wise - let data = self - .data - .iter() - .cloned() - .zip(rhs.data.iter().cloned()) - .map(|(a, b)| a $op b) - .collect(); + assert_eq!(self.rows, rhs.rows); assert_eq!(self.cols, rhs.cols); + let data = self.data.iter().cloned().zip(rhs.data.iter().cloned()).map(|(a, b)| a $op b).collect(); Matrix { rows: self.rows, cols: self.cols, data } } } + // Matrix OP &Matrix + impl<'b> $OpTrait<&'b Matrix> for Matrix { + type Output = Matrix; + fn $method(mut self, rhs: &'b Matrix) -> Matrix { + assert_eq!(self.rows, rhs.rows); assert_eq!(self.cols, rhs.cols); + for (a, b) in self.data.iter_mut().zip(rhs.data.iter()) { *a = *a $op *b; } // bool is Copy + self + } + } + // &Matrix OP Matrix + impl<'a> $OpTrait> for &'a Matrix { + type Output = Matrix; + fn $method(self, mut rhs: Matrix) -> Matrix { + assert_eq!(self.rows, rhs.rows); assert_eq!(self.cols, rhs.cols); + for (a, b) in self.data.iter().zip(rhs.data.iter_mut()) { *b = *a $op *b; } // bool is Copy + rhs + } + } + // Matrix OP Matrix + impl $OpTrait> for Matrix { + type Output = Matrix; + fn $method(mut self, rhs: Matrix) -> Matrix { + assert_eq!(self.rows, rhs.rows); assert_eq!(self.cols, rhs.cols); + for (a, b) in self.data.iter_mut().zip(rhs.data.iter()) { *a = *a $op *b; } // bool is Copy + self + } + } }; } -// Instantiate bitwise AND, OR, and XOR for boolean matrices -impl_bitwise_op!(BitAnd, bitand, &); -impl_bitwise_op!(BitOr, bitor, |); -impl_bitwise_op!(BitXor, bitxor, ^); +// Instantiate ALL combinations for bitwise ops +impl_bitwise_op_all!(BitAnd, bitand, &); +impl_bitwise_op_all!(BitOr, bitor, |); +impl_bitwise_op_all!(BitXor, bitxor, ^); +// --- Logical Not --- + +// `!Matrix` (consumes matrix) impl Not for Matrix { type Output = Matrix; + fn not(mut self) -> Matrix { + // Take by value, make mutable + for val in self.data.iter_mut() { + *val = !*val; // Invert in place + } + self // Return the modified matrix + } +} +// `!&Matrix` (borrows matrix, returns new matrix) +impl Not for &Matrix { + type Output = Matrix; fn not(self) -> Matrix { - // Invert each boolean element in the matrix - let data = self.data.iter().map(|&v| !v).collect(); + // Take by reference + let data = self.data.iter().map(|&v| !v).collect(); // Create new data vec Matrix { rows: self.rows, cols: self.cols,