diff --git a/src/array.rs b/src/array.rs index ea1a2d2..8c275e0 100644 --- a/src/array.rs +++ b/src/array.rs @@ -42,6 +42,9 @@ pub trait Array1 { fn replace_i(&mut self, i: uint, src: Element) -> Element { mem::replace(self.mut_i(i), src) } + + /// Apply a function to each element. + fn map(&mut self, op: |Element| -> Element) -> Self; } /// A column-major array @@ -93,4 +96,7 @@ pub trait Array2, Row: Array1, Element: Copy> { let (bc, br) = b; unsafe { ptr::swap(self.mut_cr(ac, ar), self.mut_cr(bc, br)) }; } + + /// Apply a function to each column. + fn map(&mut self, op: |Column| -> Column) -> Self; } diff --git a/src/matrix.rs b/src/matrix.rs index ee2b240..a0963ca 100644 --- a/src/matrix.rs +++ b/src/matrix.rs @@ -416,6 +416,13 @@ impl Array2, Vector2, S> for Matrix2 { self.mut_c(0).swap_i(a, b); self.mut_c(1).swap_i(a, b); } + + #[inline] + fn map(&mut self, op: |Vector2| -> Vector2) -> Matrix2 { + self.x = op(self.x); + self.y = op(self.y); + *self + } } impl Array2, Vector3, S> for Matrix3 { @@ -450,6 +457,14 @@ impl Array2, Vector3, S> for Matrix3 { self.mut_c(1).swap_i(a, b); self.mut_c(2).swap_i(a, b); } + + #[inline] + fn map(&mut self, op: |Vector3| -> Vector3) -> Matrix3 { + self.x = op(self.x); + self.y = op(self.y); + self.z = op(self.z); + *self + } } impl Array2, Vector4, S> for Matrix4 { @@ -486,6 +501,15 @@ impl Array2, Vector4, S> for Matrix4 { self.mut_c(2).swap_i(a, b); self.mut_c(3).swap_i(a, b); } + + #[inline] + fn map(&mut self, op: |Vector4| -> Vector4) -> Matrix4 { + self.x = op(self.x); + self.y = op(self.y); + self.z = op(self.z); + self.w = op(self.w); + *self + } } impl Matrix> for Matrix2 { diff --git a/src/point.rs b/src/point.rs index 3a1c769..09dd083 100644 --- a/src/point.rs +++ b/src/point.rs @@ -120,6 +120,13 @@ impl Array1 for Point2 { let slice: &'a mut [S, ..2] = unsafe { mem::transmute(self) }; &'a mut slice[i] } + + #[inline] + fn map(&mut self, op: |S| -> S) -> Point2 { + self.x = op(self.x); + self.y = op(self.y); + *self + } } impl Point> for Point2 { @@ -238,6 +245,14 @@ impl Array1 for Point3 { let slice: &'a mut [S, ..3] = unsafe { mem::transmute(self) }; &'a mut slice[i] } + + #[inline] + fn map(&mut self, op: |S| -> S) -> Point3 { + self.x = op(self.x); + self.y = op(self.y); + self.z = op(self.z); + *self + } } impl Point> for Point3 { diff --git a/src/quaternion.rs b/src/quaternion.rs index 06e4b27..b9dd625 100644 --- a/src/quaternion.rs +++ b/src/quaternion.rs @@ -55,6 +55,15 @@ impl Array1 for Quaternion { let slice: &'a mut [S, ..4] = unsafe { mem::transmute(self) }; &'a mut slice[i] } + + #[inline] + fn map(&mut self, op: |S| -> S) -> Quaternion { + self.s = op(self.s); + self.v.x = op(self.v.x); + self.v.y = op(self.v.y); + self.v.z = op(self.v.z); + *self + } } impl Quaternion { diff --git a/src/test/vector.rs b/src/test/vector.rs index 9f1a5d2..ffc5c60 100644 --- a/src/test/vector.rs +++ b/src/test/vector.rs @@ -14,6 +14,7 @@ // limitations under the License. use cgmath::angle::*; +use cgmath::array::*; use cgmath::vector::*; use cgmath::approx::ApproxEq; @@ -157,3 +158,9 @@ fn test_normalize() { assert!(Vector3::new(2.0f64, 3.0f64, 6.0f64).normalize().approx_eq( &Vector3::new(2.0/7.0, 3.0/7.0, 6.0/7.0) )); assert!(Vector4::new(1.0f64, 2.0f64, 4.0f64, 10.0f64).normalize().approx_eq( &Vector4::new(1.0/11.0, 2.0/11.0, 4.0/11.0, 10.0/11.0) )); } + +#[test] +fn test_map() { + assert_eq!(Vector3::new(7.12f64, 3.8f64, -6.98f64).map(|x| x.floor()), Vector3::new(7.0f64, 3.0f64, -7.0f64)); + assert_eq!(Vector3::new(7.12f64, 3.8f64, -6.98f64).map(|x| x.max(0.0f64)), Vector3::new(7.12f64, 3.8f64, 0.0f64)); +} diff --git a/src/vector.rs b/src/vector.rs index f8e342c..711dcbe 100644 --- a/src/vector.rs +++ b/src/vector.rs @@ -144,6 +144,9 @@ macro_rules! vec( let slice: &'a mut [S, ..$n] = unsafe { mem::transmute(self) }; &'a mut slice[i] } + + #[inline] + fn map(&mut self, op: |S| -> S) -> $Self { $(self.$field = op(self.$field);)+ *self } } impl Vector for $Self {