scirs2_core/memory_efficient/
views.rs

1use super::validation;
2use crate::error::{CoreError, ErrorContext, ErrorLocation};
3use ::ndarray::{
4    Array, ArrayBase, ArrayView as NdArrayView, ArrayViewMut as NdArrayViewMut, Data, Dimension,
5    Ix1, Ix2,
6};
7
8/// A type alias for ndarray's ArrayView with additional functionality
9pub type ArrayView<'a, A, D> = NdArrayView<'a, A, D>;
10
11/// A type alias for ndarray's ArrayViewMut with additional functionality
12pub type ViewMut<'a, A, D> = NdArrayViewMut<'a, A, D>;
13
14/// Create a view of an array with a different element type
15///
16/// This function creates a view of the given array interpreting its elements
17/// as a different type. This is useful for viewing binary data as different
18/// types without copying.
19///
20/// # Safety
21///
22/// This function is unsafe because it does not check that the memory layout
23/// of the source type is compatible with the destination type.
24///
25/// # Arguments
26///
27/// * `array` - The array to view
28///
29/// # Returns
30///
31/// A view of the array with elements interpreted as the new type
32pub unsafe fn view_as<A, B, S, D>(array: &ArrayBase<S, D>) -> Result<ArrayView<'_, B, D>, CoreError>
33where
34    A: Clone,
35    S: Data<Elem = A>,
36    D: Dimension,
37{
38    validation::check_not_empty(array)?;
39
40    // Calculate new shape based on type sizes
41    let a_size = std::mem::size_of::<A>();
42    let b_size = std::mem::size_of::<B>();
43
44    if a_size == 0 || b_size == 0 {
45        return Err(CoreError::ValidationError(
46            ErrorContext::new("Cannot reinterpret view of zero-sized type".to_string())
47                .with_location(ErrorLocation::new(file!(), line!())),
48        ));
49    }
50
51    if a_size % b_size != 0 && b_size % a_size != 0 {
52        return Err(CoreError::ValidationError(
53            ErrorContext::new(format!(
54                "Type sizes are not compatible: {a_size} is not divisible by or a divisor of {b_size}"
55            ))
56            .with_location(ErrorLocation::new(file!(), line!())),
57        ));
58    }
59
60    // This is a placeholder - the actual implementation would need to create a view
61    // with the appropriate type conversion
62    Err(CoreError::ImplementationError(
63        ErrorContext::new("view_as is not yet implemented".to_string())
64            .with_location(ErrorLocation::new(file!(), line!())),
65    ))
66}
67
68/// Create a mutable view of an array with a different element type
69///
70/// # Safety
71///
72/// This function is unsafe because it does not check that the memory layout
73/// of the source type is compatible with the destination type.
74///
75/// # Arguments
76///
77/// * `array` - The array to view
78///
79/// # Returns
80///
81/// A mutable view of the array with elements interpreted as the new type
82pub unsafe fn view_mut_as<A, B, S, D>(
83    array: &mut ArrayBase<S, D>,
84) -> Result<ViewMut<'_, B, D>, CoreError>
85where
86    A: Clone,
87    S: Data<Elem = A>,
88    D: Dimension,
89{
90    validation::check_not_empty(array)?;
91
92    // Calculate new shape based on type sizes
93    let a_size = std::mem::size_of::<A>();
94    let b_size = std::mem::size_of::<B>();
95
96    if a_size == 0 || b_size == 0 {
97        return Err(CoreError::ValidationError(
98            ErrorContext::new("Cannot reinterpret view of zero-sized type".to_string())
99                .with_location(ErrorLocation::new(file!(), line!())),
100        ));
101    }
102
103    if a_size % b_size != 0 && b_size % a_size != 0 {
104        return Err(CoreError::ValidationError(
105            ErrorContext::new(format!(
106                "Type sizes are not compatible: {a_size} is not divisible by or a divisor of {b_size}"
107            ))
108            .with_location(ErrorLocation::new(file!(), line!())),
109        ));
110    }
111
112    // This is a placeholder - the actual implementation would need to create a mutable view
113    // with the appropriate type conversion
114    Err(CoreError::ImplementationError(
115        ErrorContext::new("view_mut_as is not yet implemented".to_string())
116            .with_location(ErrorLocation::new(file!(), line!())),
117    ))
118}
119
120/// Create a transposed copy of a 2D array
121///
122/// # Arguments
123///
124/// * `array` - The array to transpose
125///
126/// # Returns
127///
128/// A transposed copy of the array
129#[allow(dead_code)]
130pub fn transpose_view<A, S>(array: &ArrayBase<S, Ix2>) -> Result<Array<A, Ix2>, CoreError>
131where
132    A: Clone,
133    S: Data<Elem = A>,
134{
135    validation::check_not_empty(array)?;
136
137    // Create a transposed owned copy
138    Ok(array.to_owned().t().to_owned())
139}
140
141/// Create a copy of the diagonal of a 2D array
142///
143/// # Arguments
144///
145/// * `array` - The array to view
146///
147/// # Returns
148///
149/// A copy of the diagonal of the array
150#[allow(dead_code)]
151pub fn diagonal_view<A, S>(array: &ArrayBase<S, Ix2>) -> Result<Array<A, Ix1>, CoreError>
152where
153    A: Clone,
154    S: Data<Elem = A>,
155{
156    validation::check_not_empty(array)?;
157    validation::check_square(array)?;
158
159    // Create a diagonal copy
160    Ok(array.diag().to_owned())
161}