19
19
#include <binsparse/binsparse.h>
20
20
#include <string.h>
21
21
22
- /**
23
- * Convert bsp_array_t to MATLAB array
24
- */
25
- mxArray * bsp_array_to_matlab (const bsp_array_t * array ) {
26
- if (array -> data == NULL || array -> size == 0 ) {
27
- // Return empty array
28
- return mxCreateDoubleMatrix (0 , 1 , mxREAL );
29
- }
30
-
31
- mxArray * mx_array = NULL ;
32
-
33
- switch (array -> type ) {
34
- case BSP_FLOAT64 :
35
- mx_array = mxCreateNumericMatrix (array -> size , 1 , mxDOUBLE_CLASS , mxREAL );
36
- memcpy (mxGetPr (mx_array ), array -> data , array -> size * sizeof (double ));
37
- break ;
38
-
39
- case BSP_FLOAT32 :
40
- mx_array = mxCreateNumericMatrix (array -> size , 1 , mxSINGLE_CLASS , mxREAL );
41
- memcpy (mxGetData (mx_array ), array -> data , array -> size * sizeof (float ));
42
- break ;
43
-
44
- case BSP_UINT64 :
45
- mx_array = mxCreateNumericMatrix (array -> size , 1 , mxUINT64_CLASS , mxREAL );
46
- memcpy (mxGetData (mx_array ), array -> data , array -> size * sizeof (uint64_t ));
47
- break ;
48
-
49
- case BSP_UINT32 :
50
- mx_array = mxCreateNumericMatrix (array -> size , 1 , mxUINT32_CLASS , mxREAL );
51
- memcpy (mxGetData (mx_array ), array -> data , array -> size * sizeof (uint32_t ));
52
- break ;
22
+ static inline void * bsp_matlab_malloc (size_t size ) {
23
+ void * ptr = mxMalloc (size );
24
+ mexMakeMemoryPersistent (ptr );
25
+ return ptr ;
26
+ }
53
27
54
- case BSP_UINT16 :
55
- mx_array = mxCreateNumericMatrix (array -> size , 1 , mxUINT16_CLASS , mxREAL );
56
- memcpy (mxGetData (mx_array ), array -> data , array -> size * sizeof (uint16_t ));
57
- break ;
28
+ static const bsp_allocator_t bsp_matlab_allocator = {
29
+ .malloc = bsp_matlab_malloc , .free = mxFree };
58
30
31
+ static inline mxClassID get_mxClassID (bsp_type_t type ) {
32
+ switch (type ) {
59
33
case BSP_UINT8 :
60
- mx_array = mxCreateNumericMatrix (array -> size , 1 , mxUINT8_CLASS , mxREAL );
61
- memcpy (mxGetData (mx_array ), array -> data , array -> size * sizeof (uint8_t ));
62
- break ;
63
-
64
- case BSP_INT64 :
65
- mx_array = mxCreateNumericMatrix (array -> size , 1 , mxINT64_CLASS , mxREAL );
66
- memcpy (mxGetData (mx_array ), array -> data , array -> size * sizeof (int64_t ));
67
- break ;
68
-
69
- case BSP_INT32 :
70
- mx_array = mxCreateNumericMatrix (array -> size , 1 , mxINT32_CLASS , mxREAL );
71
- memcpy (mxGetData (mx_array ), array -> data , array -> size * sizeof (int32_t ));
72
- break ;
73
-
34
+ return mxUINT8_CLASS ;
35
+ case BSP_UINT16 :
36
+ return mxUINT16_CLASS ;
37
+ case BSP_UINT32 :
38
+ return mxUINT32_CLASS ;
39
+ case BSP_UINT64 :
40
+ return mxUINT64_CLASS ;
41
+ case BSP_INT8 :
42
+ return mxINT8_CLASS ;
74
43
case BSP_INT16 :
75
- mx_array = mxCreateNumericMatrix (array -> size , 1 , mxINT16_CLASS , mxREAL );
76
- memcpy (mxGetData (mx_array ), array -> data , array -> size * sizeof (int16_t ));
77
- break ;
44
+ return mxINT16_CLASS ;
45
+ case BSP_INT32 :
46
+ return mxINT32_CLASS ;
47
+ case BSP_INT64 :
48
+ return mxINT64_CLASS ;
49
+ case BSP_FLOAT32 :
50
+ return mxSINGLE_CLASS ;
51
+ case BSP_FLOAT64 :
52
+ return mxDOUBLE_CLASS ;
53
+ case BSP_BINT8 : // Treat BSP_BINT8 as UINT8
54
+ return mxUINT8_CLASS ;
55
+ case BSP_COMPLEX_FLOAT32 :
56
+ return mxSINGLE_CLASS ;
57
+ case BSP_COMPLEX_FLOAT64 :
58
+ return mxDOUBLE_CLASS ;
59
+ default :
60
+ return mxUNKNOWN_CLASS ;
61
+ }
62
+ }
78
63
79
- case BSP_INT8 :
80
- mx_array = mxCreateNumericMatrix (array -> size , 1 , mxINT8_CLASS , mxREAL );
81
- memcpy (mxGetData (mx_array ), array -> data , array -> size * sizeof (int8_t ));
82
- break ;
83
-
84
- case BSP_BINT8 :
85
- // Treat BSP_BINT8 as UINT8 as suggested
86
- mx_array = mxCreateNumericMatrix (array -> size , 1 , mxUINT8_CLASS , mxREAL );
87
- memcpy (mxGetData (mx_array ), array -> data , array -> size * sizeof (int8_t ));
88
- break ;
89
-
90
- case BSP_COMPLEX_FLOAT64 : {
91
- mx_array = mxCreateNumericMatrix (array -> size , 1 , mxDOUBLE_CLASS , mxCOMPLEX );
92
- double * in_data =
93
- (double * ) array -> data ; // Treat as array of adjacent real/imag pairs
94
- double * real_data = mxGetPr (mx_array );
95
- double * imag_data = mxGetPi (mx_array );
96
- for (size_t i = 0 ; i < array -> size ; i ++ ) {
97
- real_data [i ] = in_data [2 * i ]; // Real part
98
- imag_data [i ] = in_data [2 * i + 1 ]; // Imaginary part
99
- }
100
- break ;
64
+ static inline mxComplexity get_mxComplexity (bsp_type_t type ) {
65
+ if (type == BSP_COMPLEX_FLOAT32 || type == BSP_COMPLEX_FLOAT64 ) {
66
+ return mxCOMPLEX ;
67
+ } else {
68
+ return mxREAL ;
101
69
}
70
+ }
102
71
103
- case BSP_COMPLEX_FLOAT32 : {
104
- mx_array = mxCreateNumericMatrix (array -> size , 1 , mxSINGLE_CLASS , mxCOMPLEX );
105
- float * in_data =
106
- (float * ) array -> data ; // Treat as array of adjacent real/imag pairs
107
- float * real_data = (float * ) mxGetData (mx_array );
108
- float * imag_data = (float * ) mxGetImagData (mx_array );
109
- for (size_t i = 0 ; i < array -> size ; i ++ ) {
110
- real_data [i ] = in_data [2 * i ]; // Real part
111
- imag_data [i ] = in_data [2 * i + 1 ]; // Imaginary part
112
- }
113
- break ;
72
+ mxArray * bsp_array_to_matlab (bsp_array_t * array ) {
73
+ if (array -> data == NULL || array -> size == 0 ) {
74
+ // Return empty array
75
+ return mxCreateDoubleMatrix (1 , 1 , mxREAL );
114
76
}
115
77
116
- default :
117
- // Fallback: create empty array
118
- mx_array = mxCreateDoubleMatrix (0 , 1 , mxREAL );
78
+ if (get_mxClassID (array -> type ) == mxUNKNOWN_CLASS ) {
119
79
mexWarnMsgIdAndTxt ("BinSparse:UnsupportedType" ,
120
80
"Unsupported array type %d, returning empty array" ,
121
81
(int ) array -> type );
122
- break ;
82
+ return mxCreateDoubleMatrix (1 , 1 , mxREAL );
83
+ }
84
+
85
+ mxArray * mx_array = NULL ;
86
+
87
+ if ((array -> allocator .malloc == bsp_matlab_allocator .malloc &&
88
+ array -> allocator .free == bsp_matlab_allocator .free ) &&
89
+ get_mxComplexity (array -> type ) == mxREAL ) {
90
+ // Create mx_array in a zero-copy fashion.
91
+
92
+ mx_array = mxCreateNumericMatrix (0 , 1 , get_mxClassID (array -> type ),
93
+ get_mxComplexity (array -> type ));
94
+
95
+ mxSetData (mx_array , array -> data );
96
+ mxSetM (mx_array , array -> size );
97
+
98
+ array -> data = NULL ;
99
+ array -> size = 0 ;
100
+ } else {
101
+ mx_array = mxCreateNumericMatrix (array -> size , 1 , get_mxClassID (array -> type ),
102
+ get_mxComplexity (array -> type ));
103
+
104
+ if (get_mxComplexity (array -> type ) == mxREAL ) {
105
+ memcpy (mxGetData (mx_array ), array -> data ,
106
+ array -> size * bsp_type_size (array -> type ));
107
+ } else {
108
+ if (array -> type == BSP_COMPLEX_FLOAT32 ) {
109
+ float * in_data =
110
+ (float * ) array -> data ; // Treat as array of adjacent real/imag pairs
111
+ float * real_data = (float * ) mxGetData (mx_array );
112
+ float * imag_data = (float * ) mxGetImagData (mx_array );
113
+ for (size_t i = 0 ; i < array -> size ; i ++ ) {
114
+ real_data [i ] = in_data [2 * i ]; // Real part
115
+ imag_data [i ] = in_data [2 * i + 1 ]; // Imaginary part
116
+ }
117
+ } else {
118
+ double * in_data =
119
+ (double * ) array -> data ; // Treat as array of adjacent real/imag pairs
120
+ double * real_data = mxGetPr (mx_array );
121
+ double * imag_data = mxGetPi (mx_array );
122
+ for (size_t i = 0 ; i < array -> size ; i ++ ) {
123
+ real_data [i ] = in_data [2 * i ]; // Real part
124
+ imag_data [i ] = in_data [2 * i + 1 ]; // Imaginary part
125
+ }
126
+ }
127
+ }
123
128
}
124
129
125
130
return mx_array ;
@@ -128,7 +133,7 @@ mxArray* bsp_array_to_matlab(const bsp_array_t* array) {
128
133
/**
129
134
* Convert bsp_matrix_t to MATLAB struct
130
135
*/
131
- mxArray * bsp_matrix_to_matlab_struct (const bsp_matrix_t * matrix ) {
136
+ mxArray * bsp_matrix_to_matlab_struct (bsp_matrix_t * matrix ) {
132
137
const char * field_names [] = {
133
138
"values" , "indices_0" , "indices_1" , "pointers_to_1" , "nrows" ,
134
139
"ncols" , "nnz" , "is_iso" , "format" , "structure" };
@@ -210,7 +215,8 @@ void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) {
210
215
}
211
216
212
217
// Read the matrix using Binsparse
213
- error = bsp_read_matrix (& matrix , filename , group );
218
+ error =
219
+ bsp_read_matrix_allocator (& matrix , filename , group , bsp_matlab_allocator );
214
220
215
221
if (error != BSP_SUCCESS ) {
216
222
// Clean up
@@ -228,6 +234,7 @@ void mexFunction(int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[]) {
228
234
229
235
// Clean up
230
236
bsp_destroy_matrix_t (& matrix );
237
+
231
238
if (filename )
232
239
mxFree (filename );
233
240
if (group )
0 commit comments