Skip to content

Commit 34c81b7

Browse files
committed
FEATURE: sparse module with sparse array functions
1 parent 38a4393 commit 34c81b7

File tree

5 files changed

+328
-1
lines changed

5 files changed

+328
-1
lines changed

src/array.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,8 @@ extern {
9797

9898
fn af_is_owner(result: *mut c_int, arr: AfArray) -> c_int;
9999

100+
fn af_is_sparse(result: *mut c_int, arr: AfArray) -> c_int;
101+
100102
fn af_lock_array(arr: AfArray) -> c_int;
101103

102104
fn af_unlock_array(arr: AfArray) -> c_int;
@@ -335,6 +337,16 @@ impl Array {
335337
}
336338
}
337339

340+
/// Find if the current array is sparse
341+
pub fn is_sparse(&self) -> bool {
342+
unsafe {
343+
let mut temp: i32 = 0;
344+
let err_val = af_is_sparse(&mut temp as *mut c_int, self.handle as AfArray);
345+
HANDLE_ERROR(AfError::from(err_val));
346+
temp > 0
347+
}
348+
}
349+
338350
/// Lock the device buffer in the memory manager
339351
///
340352
/// Locked buffers are not freed by memory manager until unlock is called.

src/defines.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,3 +344,17 @@ pub enum MomentType {
344344
M11 = 8, // 1<<3
345345
FIRST_ORDER = 1<<0 | 1<<1 | 1<<2 | 1<<3
346346
}
347+
348+
/// Sparse storage format type
349+
#[repr(C)]
350+
#[derive(Clone, Copy, Debug, PartialEq)]
351+
pub enum SparseFormat {
352+
/// Dense format
353+
DENSE = 0,
354+
/// Compressed sparse row format
355+
CSR = 1,
356+
/// Compressed sparse coloumn format
357+
CSC = 2,
358+
/// Coordinate list (row, coloumn, value) tuples.
359+
COO = 3
360+
}

src/lib.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ mod device;
4747
pub use defines::{DType, AfError, Backend, ColorMap, YCCStd, HomographyType};
4848
pub use defines::{InterpType, BorderType, MatchType, NormType};
4949
pub use defines::{Connectivity, ConvMode, ConvDomain, ColorSpace, MatProp};
50-
pub use defines::{MarkerType, MomentType};
50+
pub use defines::{MarkerType, MomentType, SparseFormat};
5151
mod defines;
5252

5353
pub use dim4::Dim4;
@@ -93,6 +93,11 @@ pub use signal::{fft_convolve1, fft_convolve2, fft_convolve3};
9393
pub use signal::{fir, iir};
9494
mod signal;
9595

96+
pub use sparse::{sparse, sparse_from_host, sparse_from_dense, sparse_convert_to};
97+
pub use sparse::{sparse_to_dense, sparse_get_info, sparse_get_values, sparse_get_nnz};
98+
pub use sparse::{sparse_get_row_indices, sparse_get_col_indices, sparse_get_format};
99+
mod sparse;
100+
96101
pub use statistics::{mean, stdev, median, var, cov, corrcoef};
97102
pub use statistics::{mean_weighted, var_weighted};
98103
pub use statistics::{var_all, mean_all, stdev_all, median_all};

src/sparse/mod.rs

Lines changed: 288 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,288 @@
1+
extern crate libc;
2+
3+
use array::Array;
4+
use defines::{AfError, SparseFormat};
5+
use error::HANDLE_ERROR;
6+
use self::libc::{uint8_t, c_void, c_int};
7+
use util::HasAfEnum;
8+
9+
type MutAfArray = *mut self::libc::c_longlong;
10+
type AfArray = self::libc::c_longlong;
11+
type DimT = self::libc::c_longlong;
12+
type MutDimT = *mut self::libc::c_longlong;
13+
14+
#[allow(dead_code)]
15+
extern {
16+
fn af_create_sparse_array(out: MutAfArray, nRows: DimT, nCols: DimT, vals: AfArray,
17+
rowIdx: AfArray, colIdx: AfArray, stype: uint8_t) -> c_int;
18+
19+
fn af_create_sparse_array_from_ptr(out: MutAfArray, nRows: DimT, nCols: DimT, nNZ: DimT,
20+
values: *const c_void, rowIdx: *const c_int, colIdx: *const c_int,
21+
aftype: uint8_t, stype: uint8_t, src: uint8_t) -> c_int;
22+
23+
fn af_create_sparse_array_from_dense(out: MutAfArray, dense: AfArray, stype: uint8_t) -> c_int;
24+
25+
fn af_sparse_convert_to(out: MutAfArray, input: AfArray, dstStrge: uint8_t) -> c_int;
26+
27+
fn af_sparse_to_dense(out: MutAfArray, sparse: AfArray) -> c_int;
28+
29+
fn af_sparse_get_info(vals: MutAfArray, rIdx: MutAfArray, cIdx: MutAfArray, stype: *mut uint8_t,
30+
input: AfArray) -> c_int;
31+
32+
fn af_sparse_get_values(out: MutAfArray, input: AfArray) -> c_int;
33+
34+
fn af_sparse_get_row_idx(out: MutAfArray, input: AfArray) -> c_int;
35+
36+
fn af_sparse_get_col_idx(out: MutAfArray, input: AfArray) -> c_int;
37+
38+
fn af_sparse_get_nnz(out: MutDimT, input: AfArray) -> c_int;
39+
40+
fn af_sparse_get_storage(out: *mut uint8_t, input: AfArray) -> c_int;
41+
}
42+
43+
/// Create sprase matrix from arrays
44+
///
45+
/// This function converts [Array](./struct.Array.html) of `values` into sparse array
46+
/// of `format` sparse format using arrays `row_indices` and `col_indices`.
47+
///
48+
/// # Parameters
49+
///
50+
/// - `rows` is the number of rows in the dense matrix
51+
/// - `cols` is the number of columns in the dense matrix
52+
/// - `values` is the \ref af::array containing the non-zero elements
53+
/// `of the matrix
54+
/// - `row_indices` is the row indices for the sparse array
55+
/// - `col_indices` is the column indices for the sparse array
56+
/// - `format` is the storage format of the sparse array
57+
///
58+
/// # Return Values
59+
///
60+
/// Array with data in given sparse format
61+
///
62+
/// # Note
63+
///
64+
/// This function only uses references of the input arrays to create the
65+
/// sparse data structure and does not perform deep copies.
66+
pub fn sparse(rows: u64, cols: u64, values: &Array, row_indices: &Array, col_indices: &Array,
67+
format: SparseFormat) -> Array {
68+
unsafe {
69+
let mut temp: i64 = 0;
70+
let err_val = af_create_sparse_array(&mut temp as MutAfArray, rows as DimT, cols as DimT,
71+
values.get() as AfArray, row_indices.get() as AfArray,
72+
col_indices.get() as AfArray, format as uint8_t);
73+
HANDLE_ERROR(AfError::from(err_val));
74+
Array::from(temp)
75+
}
76+
}
77+
78+
/// Create sprase matrix from data on host memory
79+
///
80+
/// This function converts host array `values` into sparse array of `format` sparse
81+
/// format using host arrays `row_indices` and `col_indices`.
82+
///
83+
/// # Parameters
84+
///
85+
/// - `rows` is the number of rows in the dense matrix
86+
/// - `cols` is the number of columns in the dense matrix
87+
/// - `nzz` is the number of non zero elements in the dense matrix
88+
/// - `values` is the \ref af::array containing the non-zero elements
89+
/// `of the matrix
90+
/// - `row_indices` is the row indices for the sparse array
91+
/// - `col_indices` is the column indices for the sparse array
92+
/// - `format` is the storage format of the sparse array
93+
///
94+
/// # Return Values
95+
///
96+
/// Array with data in given sparse format
97+
///
98+
/// # Note
99+
///
100+
/// The rules for deep copy/shallow copy/reference are the same as for creating a
101+
/// regular [Array](./struct.Array.html).
102+
pub fn sparse_from_host<T: HasAfEnum>(rows: u64, cols: u64, nzz: u64,
103+
values: &[T], row_indices: &[i32], col_indices: &[i32],
104+
format: SparseFormat) -> Array {
105+
unsafe {
106+
let aftype = T::get_af_dtype();
107+
let mut temp: i64 = 0;
108+
let err_val = af_create_sparse_array_from_ptr(&mut temp as MutAfArray,
109+
rows as DimT, cols as DimT, nzz as DimT,
110+
values.as_ptr() as *const c_void,
111+
row_indices.as_ptr() as *const c_int,
112+
col_indices.as_ptr() as *const c_int,
113+
aftype as uint8_t, format as uint8_t, 1);
114+
HANDLE_ERROR(AfError::from(err_val));
115+
Array::from(temp)
116+
}
117+
}
118+
119+
/// Convert dense array to sparse array
120+
///
121+
/// # Parameters
122+
///
123+
/// - `dense` is the dense format array
124+
/// - `format` is the target sparse format
125+
///
126+
/// # Return Values
127+
///
128+
/// Sparse Array
129+
pub fn sparse_from_dense(dense: &Array, format: SparseFormat) -> Array {
130+
unsafe {
131+
let mut temp : i64 = 0;
132+
let err_val = af_create_sparse_array_from_dense(&mut temp as MutAfArray, dense.get() as AfArray,
133+
format as uint8_t);
134+
HANDLE_ERROR(AfError::from(err_val));
135+
Array::from(temp)
136+
}
137+
}
138+
139+
/// Convert between sparse formats
140+
///
141+
/// # Parameters
142+
///
143+
/// - `input` is the input sparse array
144+
/// - `format` is the target sparse format
145+
///
146+
/// # Return Values
147+
///
148+
/// Sparse Array in targe sparse format.
149+
pub fn sparse_convert_to(input: &Array, format: SparseFormat) -> Array {
150+
unsafe {
151+
let mut temp : i64 = 0;
152+
let err_val = af_sparse_convert_to(&mut temp as MutAfArray, input.get() as AfArray,
153+
format as uint8_t);
154+
HANDLE_ERROR(AfError::from(err_val));
155+
Array::from(temp)
156+
}
157+
}
158+
159+
/// Convert sparse array to dense array
160+
///
161+
/// # Parameters
162+
///
163+
/// - `input` is the sparse array
164+
///
165+
/// # Return Values
166+
///
167+
/// Dense Array
168+
pub fn sparse_to_dense(input: &Array) -> Array {
169+
unsafe {
170+
let mut temp : i64 = 0;
171+
let err_val = af_sparse_to_dense(&mut temp as MutAfArray, input.get() as AfArray);
172+
HANDLE_ERROR(AfError::from(err_val));
173+
Array::from(temp)
174+
}
175+
}
176+
177+
/// Get sparse Array information
178+
///
179+
/// # Parameters
180+
///
181+
/// - `input` is the sparse array
182+
///
183+
/// # Return Values
184+
///
185+
/// A tuple of values, row indices, coloumn indices Arrays and SparseFormat enum.
186+
pub fn sparse_get_info(input: &Array) -> (Array, Array, Array, SparseFormat) {
187+
unsafe {
188+
let mut val : i64 = 0;
189+
let mut row : i64 = 0;
190+
let mut col : i64 = 0;
191+
let mut stype : u8 = 0;
192+
let err_val = af_sparse_get_info(&mut val as MutAfArray, &mut row as MutAfArray,
193+
&mut col as MutAfArray, &mut stype as *mut uint8_t,
194+
input.get() as AfArray);
195+
HANDLE_ERROR(AfError::from(err_val));
196+
(Array::from(val), Array::from(row), Array::from(col), SparseFormat::from(stype as i32))
197+
}
198+
}
199+
200+
/// Get values of sparse Array
201+
///
202+
/// # Parameters
203+
///
204+
/// - `input` is the sparse array
205+
///
206+
/// # Return Values
207+
///
208+
/// Sparse array values
209+
pub fn sparse_get_values(input: &Array) -> Array {
210+
unsafe {
211+
let mut val : i64 = 0;
212+
let err_val = af_sparse_get_values(&mut val as MutAfArray, input.get() as AfArray);
213+
HANDLE_ERROR(AfError::from(err_val));
214+
Array::from(val)
215+
}
216+
}
217+
218+
/// Get row indices Array
219+
///
220+
/// # Parameters
221+
///
222+
/// - `input` is the sparse array
223+
///
224+
/// # Return Values
225+
///
226+
/// Array with row indices values of sparse Array
227+
pub fn sparse_get_row_indices(input: &Array) -> Array {
228+
unsafe {
229+
let mut val : i64 = 0;
230+
let err_val = af_sparse_get_row_idx(&mut val as MutAfArray, input.get() as AfArray);
231+
HANDLE_ERROR(AfError::from(err_val));
232+
Array::from(val)
233+
}
234+
}
235+
236+
/// Get cololumn indices Array
237+
///
238+
/// # Parameters
239+
///
240+
/// - `input` is the sparse array
241+
///
242+
/// # Return Values
243+
///
244+
/// Array with coloumn indices values of sparse Array
245+
pub fn sparse_get_col_indices(input: &Array) -> Array {
246+
unsafe {
247+
let mut val : i64 = 0;
248+
let err_val = af_sparse_get_col_idx(&mut val as MutAfArray, input.get() as AfArray);
249+
HANDLE_ERROR(AfError::from(err_val));
250+
Array::from(val)
251+
}
252+
}
253+
254+
/// Get number of non-zero elements in sparse array
255+
///
256+
/// # Parameters
257+
///
258+
/// - `input` is the sparse array
259+
///
260+
/// # Return Values
261+
///
262+
/// Number of non-zero elements of sparse Array
263+
pub fn sparse_get_nnz(input: &Array) -> i64 {
264+
unsafe {
265+
let mut count : i64 = 0;
266+
let err_val = af_sparse_get_nnz(&mut count as *mut DimT, input.get() as AfArray);
267+
HANDLE_ERROR(AfError::from(err_val));
268+
count
269+
}
270+
}
271+
272+
/// Get sparse format
273+
///
274+
/// # Parameters
275+
///
276+
/// - `input` is the sparse array
277+
///
278+
/// # Return Values
279+
///
280+
/// Sparse array format
281+
pub fn sparse_get_format(input: &Array) -> SparseFormat {
282+
unsafe {
283+
let mut stype : u8 = 0;
284+
let err_val = af_sparse_get_storage(&mut stype as *mut uint8_t, input.get() as AfArray);
285+
HANDLE_ERROR(AfError::from(err_val));
286+
SparseFormat::from(stype as i32)
287+
}
288+
}

src/util.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ extern crate libc;
22
extern crate num;
33

44
use defines::{AfError, ColorMap, ConvDomain, ConvMode, DType, InterpType, MatProp, MatchType};
5+
use defines::{SparseFormat};
56
use error::HANDLE_ERROR;
67
use std::mem;
78
use self::num::Complex;
@@ -135,3 +136,10 @@ impl_has_af_enum!(i64, DType::S64);
135136
impl_has_af_enum!(u64, DType::U64);
136137
impl_has_af_enum!(i16, DType::S16);
137138
impl_has_af_enum!(u16, DType::U16);
139+
140+
impl From<i32> for SparseFormat {
141+
fn from(t: i32) -> SparseFormat {
142+
assert!(SparseFormat::DENSE as i32 <= t && t <= SparseFormat::COO as i32);
143+
unsafe { mem::transmute(t) }
144+
}
145+
}

0 commit comments

Comments
 (0)