1#![allow(unused_unsafe)]
6use std::os::raw::c_void;
7use core::fmt::Debug;
8use core::ops::DerefMut;
9use std::slice::{
10 from_raw_parts,
11 from_raw_parts_mut
12};
13
14use ndarray::{
15 Array,
16 ArrayViewD,
17 ArrayViewMutD,
18 Dimension,
19};
20
21pub use rustmex_core::numeric::{
22 MatlabNumber,
23 NumericArray,
24 MutNumericArray,
25};
26
27
28use rustmex_core::{
29 mxArray,
30 pointers::{
31 MxArray,
32 MatlabPtr,
33 MutMatlabPtr,
34 },
35
36 num_struct,
37
38
39 data_or_dangling,
40 data_shape_ok,
41
42 mappable::*,
43
44 convert::{
45 ToMatlabResult,
46 FromVec,
47 VecLayout,
48 FromMatlabError,
49 },
50 shim::{
51 rustmex_create_uninit_numeric_array,
52 },
53
54 MatlabClass,
55 MutMatlabClass,
56 OwnedMatlabClass,
57 NewEmpty,
58 TakeData,
59 Complexity,
60 raw::{
61 mwSize,
62 mxClassID,
63 },
64};
65
66#[cfg(any(doc, all(feature = "complex", feature="matlab800")))]
69pub use rustmex_interleaved_complex::InterleavedComplexArray;
70
71#[cfg(any(doc, all(feature = "complex", any(feature="matlab700", feature="octave"))))]
74pub use rustmex_separated_complex::SeparatedComplexArray;
75
76#[cfg(any(doc, all(feature="complex", feature="matlab800")))]
78pub use InterleavedComplexArray as ComplexArray;
79
80#[cfg(all(feature="complex", any(feature="matlab700", feature="octave")))]
81pub use SeparatedComplexArray as ComplexArray;
82
83num_struct!(
84Numeric, Complexity::Real);
88
89
90pub type OwnedNumeric<T> = Numeric<T, MxArray>;
91
92extern "Rust" {
93 fn rustmex_set_real_data(mx: *mut mxArray, newdata: Real<*mut c_void>);
94 fn rustmex_get_real_data(mx: *const mxArray) -> Real<*mut c_void>;
95}
96
97macro_rules! data_access {
98 ($s:ident, $t1:ty, $accessor:ident, $builder:ident) => {{
99 let ptr = data_or_dangling!(unsafe { $accessor($s.array.deref()) }.0, $t1 );
100 let numel = $s.array.numel();
101 unsafe { $builder(ptr, numel) }
102 }}
103}
104
105impl<'p, T, P> NumericArray<'p> for Numeric<T, P> where
106 T: MatlabNumber + 'p,
107 P: MatlabPtr + 'p,
108{
109 type Data = &'p [T];
110 fn data(&self) -> Self::Data {
111 data_access!(self, *const T, rustmex_get_real_data, from_raw_parts)
112 }
113}
114
115impl<'p, T, P> MutNumericArray<'p> for Numeric<T, P> where
116 T: MatlabNumber + 'p,
117 P: MutMatlabPtr + 'p,
118{
119 type MutData = &'p mut [T];
120 fn mut_data(&mut self) -> Self::MutData {
121 data_access!(self, *mut T, rustmex_get_real_data, from_raw_parts_mut)
122 }
123}
124
125impl<T, P> TakeData<P> for Numeric<T, P> where
126 T: MatlabNumber,
127 P: MutMatlabPtr,
128{
129 type OwnedData = Box<[T]>;
130 fn take_data(&mut self) -> Self::OwnedData {
131
132 let data = self.mut_data();
135
136 let data = unsafe { Vec::from_raw_parts(data.as_mut_ptr(), data.len(), data.len()) }
146 .into_boxed_slice();
147
148 unsafe { rustmex_set_real_data(self.deref_mut(), Real(core::ptr::null_mut())) };
151
152 data
153 }
154}
155
156macro_rules! construct_set {
157 ($data:ident, $shape:ident, $complex:literal) => {{
158 data_shape_ok!($data, $shape);
159 let mx = rustmex_core::create_uninit_numeric_array!($shape, T, Complexity::Real);
160 unsafe { rustmex_set_real_data(mx, Real(Box::into_raw($data) as *mut core::ffi::c_void)); }
161 mx
162 }}
163}
164
165impl<T: MatlabNumber> Numeric<T, MxArray> {
166 pub fn new(data: Box<[T]>, shape: &[usize]) -> ToMatlabResult<Self, Box<[T]>> {
167 Ok(Self::construct(unsafe {MxArray::assume_responsibility_ptr(construct_set!(data, shape, false))}))
168 }
169}
170
171impl<'a, T> From<Numeric<T, &'a mxArray>> for ArrayViewD<'a, T> where
175 T: MatlabNumber
176{
177 fn from(num: Numeric<T, &'a mxArray>) -> Self {
178 (&num).into()
179 }
180}
181
182impl<'a, T> From<&Numeric<T, &'a mxArray>> for ArrayViewD<'a, T> where
183 T: MatlabNumber
184{
185 fn from(num: &Numeric<T, &'a mxArray>) -> Self {
186 let data = num.data();
187 let dims = num.dimensions();
188 rustmex_core::from_num_to_ndarray!(data, dims)
189 }
190}
191
192impl<'a, T> From<&Numeric<T, &'a mxArray>> for &'a [T] where
193 T: MatlabNumber
194{
195 fn from(num: &Numeric<T, &'a mxArray>) -> Self {
196 num.data()
197 }
198}
199
200impl<'a, T> From<Numeric<T, &'a mxArray>> for &'a [T] where
201 T: MatlabNumber
202{
203 fn from(num: Numeric<T, &'a mxArray>) -> Self {
204 num.into()
205 }
206}
207
208impl<'a, T> From<Numeric<T, &'a mut mxArray>> for ArrayViewMutD<'a, T> where
213 T: MatlabNumber
214{
215 fn from(mut num: Numeric<T, &'a mut mxArray>) -> Self {
216 (&mut num).into()
217 }
218}
219
220impl<'a, T> From<&mut Numeric<T, &'a mut mxArray>> for ArrayViewMutD<'a, T> where
221 T: MatlabNumber,
222{
223 fn from(num: &mut Numeric<T, &'a mut mxArray>) -> Self {
224 let data = num.mut_data();
225 let dims = num.dimensions();
226 rustmex_core::from_num_to_ndarray!(data, dims)
227 }
228}
229
230impl<'a, T, D> From<Array<T, D>> for Numeric<T, MxArray> where
231 T: MatlabNumber,
232 D: Dimension,
233{
234 fn from(mut arr: Array<T, D>) -> Self {
235 rustmex_core::from_ndarray_to_num!(arr)
236 }
237}
238
239impl<T> From<T> for Numeric<T, MxArray> where T: MatlabNumber {
241 fn from(t: T) -> Self {
242 Numeric::new(Box::new([t]), &[1, 1]).unwrap()
243 }
244}
245
246impl<T> From<[T;0]> for Numeric<T, MxArray> where T: MatlabNumber {
248 fn from(_empty: [T;0]) -> Self {
249 Self::new_empty()
250 }
251}
252
253impl From<()> for Numeric<f64, MxArray> {
255 fn from(_nothing: ()) -> Self {
256 Self::new_empty()
257 }
258}
259
260impl<T> FromVec<T> for Numeric<T, MxArray> where T: MatlabNumber {
261 fn from_boxed_slice<L: VecLayout>(b: Box<[T]>, l: L) -> Self {
262 let len = b.len();
263 Self::new(b, l.layout(len).as_ref()).expect("Conversion from Vec-ish type should be infallible")
264 }
265}