diff --git a/src/impl_methods.rs b/src/impl_methods.rs
index 09edbb15e..2a9de3278 100644
--- a/src/impl_methods.rs
+++ b/src/impl_methods.rs
@@ -6,6 +6,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use std::cell::Cell;
use std::ptr as std_ptr;
use std::slice;
@@ -151,6 +152,20 @@ where
unsafe { ArrayViewMut::new(self.ptr, self.dim.clone(), self.strides.clone()) }
}
+ /// Return a shared view of the array with elements as if they were embedded in cells.
+ ///
+ /// The cell view requires a mutable borrow of the array. Once borrowed the
+ /// cell view itself can be copied and accessed without exclusivity.
+ ///
+ /// The view acts "as if" the elements are temporarily in cells, and elements
+ /// can be changed through shared references using the regular cell methods.
+ pub fn cell_view(&mut self) -> ArrayView<'_, Cell, D>
+ where
+ S: DataMut,
+ {
+ self.view_mut().into_cell_view()
+ }
+
/// Return an uniquely owned copy of the array.
///
/// If the input array is contiguous and its strides are positive, then the
diff --git a/src/impl_views/conversions.rs b/src/impl_views/conversions.rs
index 863d26ddb..4265f7616 100644
--- a/src/impl_views/conversions.rs
+++ b/src/impl_views/conversions.rs
@@ -6,6 +6,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use std::cell::Cell;
use std::slice;
use crate::imp_prelude::*;
@@ -117,6 +118,21 @@ where
pub fn into_slice(self) -> Option<&'a mut [A]> {
self.try_into_slice().ok()
}
+
+ /// Return a shared view of the array with elements as if they were embedded in cells.
+ ///
+ /// The cell view itself can be copied and accessed without exclusivity.
+ ///
+ /// The view acts "as if" the elements are temporarily in cells, and elements
+ /// can be changed through shared references using the regular cell methods.
+ pub fn into_cell_view(self) -> ArrayView<'a, Cell, D> {
+ // safety: valid because
+ // A and Cell have the same representation
+ // &'a mut T is interchangeable with &'a Cell -- see method Cell::from_mut
+ unsafe {
+ self.into_raw_view_mut().cast::>().deref_into_view()
+ }
+ }
}
/// Private array view methods
diff --git a/tests/views.rs b/tests/views.rs
new file mode 100644
index 000000000..216e55402
--- /dev/null
+++ b/tests/views.rs
@@ -0,0 +1,16 @@
+use ndarray::prelude::*;
+use ndarray::Zip;
+
+#[test]
+fn cell_view() {
+ let mut a = Array::from_shape_fn((10, 5), |(i, j)| (i * j) as f32);
+ let answer = &a + 1.;
+
+ {
+ let cv1 = a.cell_view();
+ let cv2 = cv1;
+
+ Zip::from(cv1).and(cv2).apply(|a, b| a.set(b.get() + 1.));
+ }
+ assert_eq!(a, answer);
+}
|