diff --git a/Cargo.lock b/Cargo.lock index 3b81b6769..ecda39e8c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,6 +3,7 @@ name = "arrayfire" version = "3.0.0" dependencies = [ "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -11,6 +12,23 @@ name = "libc" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "num" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustc-serialize" version = "0.3.15" diff --git a/Cargo.toml b/Cargo.toml index 3d6653afc..e244addf3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ build = "build.rs" [dependencies] libc = "*" +num = "*" [build-dependencies.rustc-serialize] rustc-serialize = "*" @@ -14,6 +15,6 @@ rustc-serialize = "*" name = "arrayfire" path = "src/lib.rs" -[[test]] +[[example]] name = "helloworld" -path = "tests/hello_world.rs" +path = "examples/helloworld.rs" diff --git a/README.md b/README.md index 986be35a3..3f76c373e 100644 --- a/README.md +++ b/README.md @@ -10,17 +10,17 @@ Edit [build.conf](build.conf) to modify the build flags. The structure is a simp Currently Rust does not allow key:value pairs to be passed from the CLI. To use an existing arrayfire installation modify the first three JSON values. -To build: +To build arrayfire: ```bash git submodule update --init --recursive cargo build ``` -To test: +To run hello world example: ```bash -~/p/arrayfire_rust> cargo test +~/p/arrayfire_rust> cargo run --example helloworld ... running 1 test ArrayFire v3.0.0 (CUDA, 64-bit Mac OSX, build d8d4b38) @@ -35,12 +35,75 @@ Create a 5-by-3 matrix of random floats on the GPU 0.9251 0.5132 0.6814 Element-wise arithmetic +sin(a) + 1.5 => [5 3 1 1] - 0.6744 0.4317 0.7006 - 0.7962 0.6189 0.2905 - 0.0390 0.1097 0.6549 - 0.8243 0.4531 0.3509 - 0.7987 0.4910 0.6299 + 2.1744 1.9317 2.2006 + 2.2962 2.1189 1.7905 + 1.5390 1.6097 2.1549 + 2.3243 1.9531 1.8509 + 2.2987 1.9910 2.1299 + +sin(a) + cos(a) => +[5 3 1 1] + 1.4128 1.3337 1.4142 + 1.4012 1.4044 1.2474 + 1.0382 1.1037 1.4106 + 1.3905 1.3446 1.2873 + 1.4004 1.3621 1.4066 + +!a => +[5 3 1 1] + 1 1 1 + 1 1 1 + 1 1 1 + 1 1 1 + 1 1 1 + +a + b +[5 3 1 1] + 2.9147 2.3780 2.9767 + 3.2172 2.7862 2.0853 + 1.5780 1.7196 2.8689 + 3.2933 2.4233 2.2094 + 3.2238 2.5042 2.8113 + +Fourier transform the result +[5 3 1 1] + (10.6327,0.0000) (9.6043,0.0000) (10.1267,0.0000) + (0.4689,0.4640) (0.3193,0.0802) (0.1713,0.1441) + (-0.3491,-0.7454) (-0.2923,-0.4018) (0.2667,0.4886) + (-0.3491,0.7454) (-0.2923,0.4018) (0.2667,-0.4886) + (0.4689,-0.4640) (0.3193,-0.0802) (0.1713,-0.1441) + +Create 2-by-3 matrix from host data +[2 3 1 1] + 1 3 5 + 2 4 6 + +Sort A and print sorted array and corresponding indices +[5 3 1 1] + 0.0390 0.1099 0.2948 + 0.7402 0.4464 0.3585 + 0.9210 0.4702 0.6814 + 0.9251 0.5132 0.7140 + 0.9690 0.6673 0.7762 + +[5 3 1 1] + 2 2 1 + 0 0 3 + 1 3 4 + 4 4 2 + 3 1 0 + +u8 constant array +[5 3 1 1] + 1 1 1 + 1 1 1 + 1 1 1 + 1 1 1 + 1 1 1 + +Is u8_cnst array float precision type ? false ``` ## Issues diff --git a/tests/hello_world.rs b/examples/helloworld.rs similarity index 70% rename from tests/hello_world.rs rename to examples/helloworld.rs index 7c71be940..486853870 100644 --- a/tests/hello_world.rs +++ b/examples/helloworld.rs @@ -4,7 +4,6 @@ extern crate arrayfire as af; use af::Dim4; use af::Array; -#[test] fn main() { af::set_device(0); af::info(); @@ -16,8 +15,15 @@ fn main() { af::print(&a); println!("Element-wise arithmetic"); - let b: Array = af::sin(&a) + 1.5; - af::print(&b); + let b: Array = &af::sin(&a) + 1.5; + let b2: Array = &af::sin(&a) + &af::cos(&a); + let b3: Array = ! &a; + println!("sin(a) + 1.5 => "); af::print(&b); + println!("sin(a) + cos(a) => "); af::print(&b2); + println!("!a => "); af::print(&b3); + + let test = &a + &b; + println!("a + b"); af::print(&test); // printf("Negate the first three elements of second column\n"); // B(seq(0, 2), 1) = B(seq(0, 2), 1) * -1; @@ -46,4 +52,9 @@ fn main() { let (vals, inds) = af::sort_index(&a, 0, true); af::print(&vals); af::print(&inds); + + println!("u8 constant array"); + let u8_cnst = af::constant(1 as u8, dims); + af::print(&u8_cnst); + println!("Is u8_cnst array float precision type ? {}", u8_cnst.is_single()); } diff --git a/src/algorithm/mod.rs b/src/algorithm/mod.rs index 84793b0f5..8f4071b55 100644 --- a/src/algorithm/mod.rs +++ b/src/algorithm/mod.rs @@ -1,79 +1,49 @@ extern crate libc; -use super::Array as Array; -use libc::{c_int, c_uint, c_double}; +use array::Array; +use self::libc::{c_int, c_uint}; -type MutAfArray = *mut ::libc::c_longlong; -type MutDouble = *mut ::libc::c_double; -type MutUint = *mut ::libc::c_uint; -type AfArray = ::libc::c_longlong; +type MutAfArray = *mut self::libc::c_longlong; +type MutDouble = *mut self::libc::c_double; +type MutUint = *mut self::libc::c_uint; +type AfArray = self::libc::c_longlong; #[allow(dead_code)] extern { fn af_sum(out: MutAfArray, input: AfArray, dim: c_int) -> c_int; - //fn af_sum_nan(out: MutAfArray, input: AfArray, dim: c_int, nanval: c_double) -> c_int; - fn af_product(out: MutAfArray, input: AfArray, dim: c_int) -> c_int; - //fn af_product_nan(out: MutAfArray, input: AfArray, dim: c_int, val: c_double) -> c_int; - fn af_min(out: MutAfArray, input: AfArray, dim: c_int) -> c_int; - fn af_max(out: MutAfArray, input: AfArray, dim: c_int) -> c_int; - fn af_all_true(out: MutAfArray, input: AfArray, dim: c_int) -> c_int; - fn af_any_true(out: MutAfArray, input: AfArray, dim: c_int) -> c_int; - fn af_count(out: MutAfArray, input: AfArray, dim: c_int) -> c_int; - fn af_sum_all(r: MutDouble, i: MutDouble, input: AfArray) -> c_int; - //fn af_sum_nan_all(r: MutDouble, i: MutDouble, input: AfArray, val: c_double) -> c_int; - fn af_product_all(r: MutDouble, i: MutDouble, input: AfArray) -> c_int; - //fn af_product_nan_all(r: MutDouble, i: MutDouble, input: AfArray, val: c_double) -> c_int; - fn af_min_all(r: MutDouble, i: MutDouble, input: AfArray) -> c_int; - fn af_max_all(r: MutDouble, i: MutDouble, input: AfArray) -> c_int; - fn af_all_true_all(r: MutDouble, i: MutDouble, input: AfArray) -> c_int; - fn af_any_true_all(r: MutDouble, i: MutDouble, input: AfArray) -> c_int; - fn af_count_all(r: MutDouble, i: MutDouble, input: AfArray) -> c_int; - fn af_imin(out: MutAfArray, idx: MutAfArray, input: AfArray, dim: c_int) -> c_int; - fn af_imax(out: MutAfArray, idx: MutAfArray, input: AfArray, dim: c_int) -> c_int; - fn af_imin_all(r: MutDouble, i: MutDouble, idx: MutUint, input: AfArray) -> c_int; - fn af_imax_all(r: MutDouble, i: MutDouble, idx: MutUint, input: AfArray) -> c_int; - fn af_accum(out: MutAfArray, input: AfArray, dim: c_int) -> c_int; - fn af_where(out: MutAfArray, input: AfArray) -> c_int; - fn af_diff1(out: MutAfArray, input: AfArray, dim: c_int) -> c_int; - fn af_diff2(out: MutAfArray, input: AfArray, dim: c_int) -> c_int; - fn af_sort(out: MutAfArray, input: AfArray, dim: c_uint, ascend: c_int) -> c_int; - fn af_sort_index(o: MutAfArray, i: MutAfArray, inp: AfArray, d: c_uint, a: c_int) -> c_int; - - fn af_sort_by_key(out_keys: MutAfArray, out_vals: MutAfArray, - in_keys: AfArray, in_vals: AfArray, dim: c_uint, ascend: c_int) -> c_int; - fn af_set_unique(out: MutAfArray, input: AfArray, is_sorted: c_int) -> c_int; - fn af_set_union(out: MutAfArray, first: AfArray, second: AfArray, is_unq: c_int) -> c_int; - fn af_set_intersect(out: MutAfArray, one: AfArray, two: AfArray, is_unq: c_int) -> c_int; + + fn af_sort_by_key(out_keys: MutAfArray, out_vals: MutAfArray, + in_keys: AfArray, in_vals: AfArray, dim: c_uint, ascend: c_int) -> c_int; } #[allow(unused_mut)] @@ -81,7 +51,7 @@ pub fn sum(input: &Array, dim: i32) -> Array { unsafe { let mut temp: i64 = 0; af_sum(&mut temp as MutAfArray, input.get() as AfArray, dim as c_int); - Array {handle: temp} + Array::from(temp) } } @@ -94,11 +64,12 @@ pub fn sum(input: &Array, dim: i32) -> Array { // } //} +#[allow(unused_mut)] pub fn product(input: &Array, dim: i32) -> Array { unsafe { let mut temp: i64 = 0; af_product(&mut temp as MutAfArray, input.get() as AfArray, dim as c_int); - Array {handle: temp} + Array::from(temp) } } @@ -111,46 +82,52 @@ pub fn product(input: &Array, dim: i32) -> Array { // } //} +#[allow(unused_mut)] pub fn min(input: &Array, dim: i32) -> Array { unsafe { let mut temp: i64 = 0; af_min(&mut temp as MutAfArray, input.get() as AfArray, dim as c_int); - Array {handle: temp} + Array::from(temp) } } +#[allow(unused_mut)] pub fn max(input: &Array, dim: i32) -> Array { unsafe { let mut temp: i64 = 0; af_max(&mut temp as MutAfArray, input.get() as AfArray, dim as c_int); - Array {handle: temp} + Array::from(temp) } } +#[allow(unused_mut)] pub fn all_true(input: &Array, dim: i32) -> Array { unsafe { let mut temp: i64 = 0; af_all_true(&mut temp as MutAfArray, input.get() as AfArray, dim as c_int); - Array {handle: temp} + Array::from(temp) } } +#[allow(unused_mut)] pub fn any_true(input: &Array, dim: i32) -> Array { unsafe { let mut temp: i64 = 0; af_any_true(&mut temp as MutAfArray, input.get() as AfArray, dim as c_int); - Array {handle: temp} + Array::from(temp) } } +#[allow(unused_mut)] pub fn count(input: &Array, dim: i32) -> Array { unsafe { let mut temp: i64 = 0; af_count(&mut temp as MutAfArray, input.get() as AfArray, dim as c_int); - Array {handle: temp} + Array::from(temp) } } +#[allow(unused_mut)] pub fn sum_all(input: &Array) -> (f64, f64) { unsafe { let mut real: f64 = 0.0; @@ -191,6 +168,7 @@ pub fn product_all(input: &Array) -> (f64, f64) { // } //} +#[allow(unused_mut)] pub fn min_all(input: &Array) -> (f64, f64) { unsafe { let mut real: f64 = 0.0; @@ -201,6 +179,7 @@ pub fn min_all(input: &Array) -> (f64, f64) { } } +#[allow(unused_mut)] pub fn max_all(input: &Array) -> (f64, f64) { unsafe { let mut real: f64 = 0.0; @@ -211,6 +190,7 @@ pub fn max_all(input: &Array) -> (f64, f64) { } } +#[allow(unused_mut)] pub fn all_true_all(input: &Array) -> (f64, f64) { unsafe { let mut real: f64 = 0.0; @@ -221,6 +201,7 @@ pub fn all_true_all(input: &Array) -> (f64, f64) { } } +#[allow(unused_mut)] pub fn any_true_all(input: &Array) -> (f64, f64) { unsafe { let mut real: f64 = 0.0; @@ -231,6 +212,7 @@ pub fn any_true_all(input: &Array) -> (f64, f64) { } } +#[allow(unused_mut)] pub fn count_all(input: &Array) -> (f64, f64) { unsafe { let mut real: f64 = 0.0; @@ -241,26 +223,29 @@ pub fn count_all(input: &Array) -> (f64, f64) { } } +#[allow(unused_mut)] pub fn imin(input: &Array, dim: i32) -> (Array, Array) { unsafe { let mut temp: i64 = 0; let mut idx: i64 = 0; af_imin(&mut temp as MutAfArray, &mut idx as MutAfArray, input.get() as AfArray, dim as c_int); - (Array{handle: temp}, Array{handle: idx}) + (Array::from(temp), Array::from(idx)) } } +#[allow(unused_mut)] pub fn imax(input: &Array, dim: i32) -> (Array, Array) { unsafe { let mut temp: i64 = 0; let mut idx: i64 = 0; af_imax(&mut temp as MutAfArray, &mut idx as MutAfArray, input.get() as AfArray, dim as c_int); - (Array{handle: temp}, Array{handle: idx}) + (Array::from(temp), Array::from(idx)) } } +#[allow(unused_mut)] pub fn imin_all(input: &Array) -> (f64, f64, u32) { unsafe { let mut real: f64 = 0.0; @@ -272,6 +257,7 @@ pub fn imin_all(input: &Array) -> (f64, f64, u32) { } } +#[allow(unused_mut)] pub fn imax_all(input: &Array) -> (f64, f64, u32) { unsafe { let mut real: f64 = 0.0; @@ -283,47 +269,53 @@ pub fn imax_all(input: &Array) -> (f64, f64, u32) { } } +#[allow(unused_mut)] pub fn accum(input: &Array, dim: i32) -> Array { unsafe { let mut temp: i64 = 0; af_accum(&mut temp as MutAfArray, input.get() as AfArray, dim as c_int); - Array {handle: temp} + Array::from(temp) } } +#[allow(unused_mut)] pub fn locate(input: &Array) -> Array { unsafe { let mut temp: i64 = 0; af_where(&mut temp as MutAfArray, input.get() as AfArray); - Array {handle: temp} + Array::from(temp) } } +#[allow(unused_mut)] pub fn diff1(input: &Array, dim: i32) -> Array { unsafe { let mut temp: i64 = 0; af_diff1(&mut temp as MutAfArray, input.get() as AfArray, dim as c_int); - Array {handle: temp} + Array::from(temp) } } +#[allow(unused_mut)] pub fn diff2(input: &Array, dim: i32) -> Array { unsafe { let mut temp: i64 = 0; af_diff2(&mut temp as MutAfArray, input.get() as AfArray, dim as c_int); - Array {handle: temp} + Array::from(temp) } } +#[allow(unused_mut)] pub fn sort(input: &Array, dim: u32, ascending: bool) -> Array { unsafe { let mut temp: i64 = 0; af_sort(&mut temp as MutAfArray, input.get() as AfArray, dim as c_uint, ascending as c_int); - Array{handle: temp} + Array::from(temp) } } +#[allow(unused_mut)] pub fn sort_index(input: &Array, dim: u32, ascending: bool) -> (Array, Array) { unsafe { let mut temp: i64 = 0; @@ -331,10 +323,11 @@ pub fn sort_index(input: &Array, dim: u32, ascending: bool) -> (Array, Array) { af_sort_index(&mut temp as MutAfArray, &mut idx as MutAfArray, input.get() as AfArray, dim as c_uint, ascending as c_int); - (Array {handle: temp}, Array {handle: idx}) + (Array::from(temp), Array::from(idx)) } } +#[allow(unused_mut)] pub fn sort_by_key(keys: &Array, vals: &Array, dim: u32, ascending: bool) -> (Array, Array) { unsafe { let mut temp: i64 = 0; @@ -342,32 +335,35 @@ pub fn sort_by_key(keys: &Array, vals: &Array, dim: u32, ascending: bool) -> (Ar af_sort_by_key(&mut temp as MutAfArray, &mut temp2 as MutAfArray, keys.get() as AfArray, vals.get() as AfArray, dim as c_uint, ascending as c_int); - (Array {handle: temp}, Array {handle: temp2}) + (Array::from(temp), Array::from(temp2)) } } +#[allow(unused_mut)] pub fn set_unique(input: &Array, is_sorted: bool) -> Array { unsafe { let mut temp: i64 = 0; af_set_unique(&mut temp as MutAfArray, input.get() as AfArray, is_sorted as c_int); - Array{handle: temp} + Array::from(temp) } } +#[allow(unused_mut)] pub fn set_union(first: &Array, second: &Array, is_unique: bool) -> Array { unsafe { let mut temp: i64 = 0; af_set_union(&mut temp as MutAfArray, first.get() as AfArray, second.get() as AfArray, is_unique as c_int); - Array{handle: temp} + Array::from(temp) } } +#[allow(unused_mut)] pub fn set_intersect(first: &Array, second: &Array, is_unique: bool) -> Array { unsafe { let mut temp: i64 = 0; af_set_intersect(&mut temp as MutAfArray, first.get() as AfArray, second.get() as AfArray, is_unique as c_int); - Array{handle: temp} + Array::from(temp) } } diff --git a/src/arith/mod.rs b/src/arith/mod.rs new file mode 100644 index 000000000..750594694 --- /dev/null +++ b/src/arith/mod.rs @@ -0,0 +1,256 @@ +extern crate libc; +extern crate num; + +use array::Array; +use self::libc::{c_int}; +use data::constant; +use self::num::Complex; + +type MutAfArray = *mut self::libc::c_longlong; +type MutDouble = *mut self::libc::c_double; +type MutUint = *mut self::libc::c_uint; +type AfArray = self::libc::c_longlong; + +use std::ops::{Add, Sub, Div, Mul, BitAnd, BitOr, BitXor, Not, Rem, Shl, Shr}; + +#[allow(dead_code)] +extern { + fn af_add(out: MutAfArray, lhs: AfArray, rhs: AfArray, batch: c_int) -> c_int; + fn af_sub(out: MutAfArray, lhs: AfArray, rhs: AfArray, batch: c_int) -> c_int; + fn af_mul(out: MutAfArray, lhs: AfArray, rhs: AfArray, batch: c_int) -> c_int; + fn af_div(out: MutAfArray, lhs: AfArray, rhs: AfArray, batch: c_int) -> c_int; + + fn af_lt(out: MutAfArray, lhs: AfArray, rhs: AfArray, batch: c_int) -> c_int; + fn af_gt(out: MutAfArray, lhs: AfArray, rhs: AfArray, batch: c_int) -> c_int; + fn af_le(out: MutAfArray, lhs: AfArray, rhs: AfArray, batch: c_int) -> c_int; + fn af_ge(out: MutAfArray, lhs: AfArray, rhs: AfArray, batch: c_int) -> c_int; + fn af_eq(out: MutAfArray, lhs: AfArray, rhs: AfArray, batch: c_int) -> c_int; + fn af_or(out: MutAfArray, lhs: AfArray, rhs: AfArray, batch: c_int) -> c_int; + + fn af_neq(out: MutAfArray, lhs: AfArray, rhs: AfArray, batch: c_int) -> c_int; + fn af_and(out: MutAfArray, lhs: AfArray, rhs: AfArray, batch: c_int) -> c_int; + fn af_rem(out: MutAfArray, lhs: AfArray, rhs: AfArray, batch: c_int) -> c_int; + fn af_mod(out: MutAfArray, lhs: AfArray, rhs: AfArray, batch: c_int) -> c_int; + + fn af_bitand(out: MutAfArray, lhs: AfArray, rhs: AfArray, batch: c_int) -> c_int; + fn af_bitor(out: MutAfArray, lhs: AfArray, rhs: AfArray, batch: c_int) -> c_int; + fn af_bitxor(out: MutAfArray, lhs: AfArray, rhs: AfArray, batch: c_int) -> c_int; + fn af_bitshiftl(out: MutAfArray, lhs: AfArray, rhs: AfArray, batch: c_int) -> c_int; + fn af_bitshiftr(out: MutAfArray, lhs: AfArray, rhs: AfArray, batch: c_int) -> c_int; + fn af_minof(out: MutAfArray, lhs: AfArray, rhs: AfArray, batch: c_int) -> c_int; + fn af_maxof(out: MutAfArray, lhs: AfArray, rhs: AfArray, batch: c_int) -> c_int; + + fn af_not(out: MutAfArray, arr: AfArray) -> c_int; + fn af_abs(out: MutAfArray, arr: AfArray) -> c_int; + fn af_arg(out: MutAfArray, arr: AfArray) -> c_int; + fn af_sign(out: MutAfArray, arr: AfArray) -> c_int; + fn af_ceil(out: MutAfArray, arr: AfArray) -> c_int; + fn af_round(out: MutAfArray, arr: AfArray) -> c_int; + fn af_trunc(out: MutAfArray, arr: AfArray) -> c_int; + fn af_floor(out: MutAfArray, arr: AfArray) -> c_int; + + fn af_hypot(out: MutAfArray, lhs: AfArray, rhs: AfArray, batch: c_int) -> c_int; + + fn af_sin(out: MutAfArray, arr: AfArray) -> c_int; + fn af_cos(out: MutAfArray, arr: AfArray) -> c_int; + fn af_tan(out: MutAfArray, arr: AfArray) -> c_int; + fn af_asin(out: MutAfArray, arr: AfArray) -> c_int; + fn af_acos(out: MutAfArray, arr: AfArray) -> c_int; + fn af_atan(out: MutAfArray, arr: AfArray) -> c_int; + + fn af_atan2(out: MutAfArray, lhs: AfArray, rhs: AfArray, batch: c_int) -> c_int; + fn af_cplx2(out: MutAfArray, lhs: AfArray, rhs: AfArray, batch: c_int) -> c_int; + fn af_root(out: MutAfArray, lhs: AfArray, rhs: AfArray, batch: c_int) -> c_int; + fn af_pow(out: MutAfArray, lhs: AfArray, rhs: AfArray, batch: c_int) -> c_int; + + fn af_cplx(out: MutAfArray, arr: AfArray) -> c_int; + fn af_real(out: MutAfArray, arr: AfArray) -> c_int; + fn af_imag(out: MutAfArray, arr: AfArray) -> c_int; + fn af_conjg(out: MutAfArray, arr: AfArray) -> c_int; + fn af_sinh(out: MutAfArray, arr: AfArray) -> c_int; + fn af_cosh(out: MutAfArray, arr: AfArray) -> c_int; + fn af_tanh(out: MutAfArray, arr: AfArray) -> c_int; + fn af_asinh(out: MutAfArray, arr: AfArray) -> c_int; + fn af_acosh(out: MutAfArray, arr: AfArray) -> c_int; + fn af_atanh(out: MutAfArray, arr: AfArray) -> c_int; + fn af_pow2(out: MutAfArray, arr: AfArray) -> c_int; + fn af_exp(out: MutAfArray, arr: AfArray) -> c_int; + fn af_expm1(out: MutAfArray, arr: AfArray) -> c_int; + fn af_erf(out: MutAfArray, arr: AfArray) -> c_int; + fn af_erfc(out: MutAfArray, arr: AfArray) -> c_int; + fn af_log(out: MutAfArray, arr: AfArray) -> c_int; + fn af_log1p(out: MutAfArray, arr: AfArray) -> c_int; + fn af_log10(out: MutAfArray, arr: AfArray) -> c_int; + fn af_log2(out: MutAfArray, arr: AfArray) -> c_int; + fn af_sqrt(out: MutAfArray, arr: AfArray) -> c_int; + fn af_cbrt(out: MutAfArray, arr: AfArray) -> c_int; + fn af_factorial(out: MutAfArray, arr: AfArray) -> c_int; + fn af_tgamma(out: MutAfArray, arr: AfArray) -> c_int; + fn af_lgamma(out: MutAfArray, arr: AfArray) -> c_int; + fn af_iszero(out: MutAfArray, arr: AfArray) -> c_int; + fn af_isinf(out: MutAfArray, arr: AfArray) -> c_int; + fn af_isnan(out: MutAfArray, arr: AfArray) -> c_int; +} + +impl<'f> Not for &'f Array { + type Output = Array; + + fn not(self) -> Array { + unsafe { + let mut temp: i64 = 0; + af_not(&mut temp as MutAfArray, self.get() as AfArray); + Array::from(temp) + } + } +} + +macro_rules! unary_func { + ($fn_name: ident, $ffi_fn: ident) => ( + #[allow(unused_mut)] + pub fn $fn_name(input: &Array) -> Array { + unsafe { + let mut temp: i64 = 0; + $ffi_fn(&mut temp as MutAfArray, input.get() as AfArray); + Array::from(temp) + } + } + ) +} + +unary_func!(abs, af_abs); +unary_func!(arg, af_arg); +unary_func!(sign, af_sign); +unary_func!(round, af_round); +unary_func!(trunc, af_trunc); +unary_func!(floor, af_floor); +unary_func!(ceil, af_ceil); +unary_func!(sin, af_sin); +unary_func!(cos, af_cos); +unary_func!(tan, af_tan); +unary_func!(asin, af_asin); +unary_func!(acos, af_acos); +unary_func!(atan, af_atan); +unary_func!(cplx, af_cplx); +unary_func!(real, af_real); +unary_func!(imag, af_imag); +unary_func!(conjg, af_conjg); +unary_func!(sinh, af_sinh); +unary_func!(cosh, af_cosh); +unary_func!(tanh, af_tanh); +unary_func!(asinh, af_asinh); +unary_func!(acosh, af_acosh); +unary_func!(atanh, af_atanh); +unary_func!(pow2, af_pow2); +unary_func!(exp, af_exp); +unary_func!(expm1, af_expm1); +unary_func!(erf, af_erf); +unary_func!(erfc, af_erfc); +unary_func!(log, af_log); +unary_func!(log1p, af_log1p); +unary_func!(log10, af_log10); +unary_func!(log2, af_log2); +unary_func!(sqrt, af_sqrt); +unary_func!(cbrt, af_cbrt); +unary_func!(factorial, af_factorial); +unary_func!(tgamma, af_tgamma); +unary_func!(lgamma, af_lgamma); +unary_func!(iszero, af_iszero); +unary_func!(isinf, af_isinf); +unary_func!(isnan, af_isnan); + +macro_rules! binary_func { + ($fn_name: ident, $ffi_fn: ident) => ( + #[allow(unused_mut)] + pub fn $fn_name(lhs: &Array, rhs: &Array) -> Array { + unsafe { + let mut temp: i64 = 0; + $ffi_fn(&mut temp as MutAfArray, lhs.get() as AfArray, rhs.get() as AfArray, 0); + Array::from(temp) + } + } + ) +} + +binary_func!(lt, af_lt); +binary_func!(gt, af_gt); +binary_func!(le, af_le); +binary_func!(ge, af_ge); +binary_func!(eq, af_eq); +binary_func!(neq, af_neq); +binary_func!(and, af_and); +binary_func!(or, af_or); +binary_func!(minof, af_minof); +binary_func!(maxof, af_maxof); +binary_func!(modulo, af_mod); +binary_func!(hypot, af_hypot); +binary_func!(atan2, af_atan2); +binary_func!(cplx2, af_cplx2); +binary_func!(root, af_root); +binary_func!(pow, af_pow); + +macro_rules! arith_scalar_func { + ($rust_type: ty, $op_name:ident, $fn_name: ident, $ffi_fn: ident) => ( + impl<'f> $op_name<$rust_type> for &'f Array { + type Output = Array; + + fn $fn_name(self, rhs: $rust_type) -> Array { + let cnst_arr = constant(rhs, self.dims()); + unsafe { + let mut temp: i64 = 0; + $ffi_fn(&mut temp as MutAfArray, + self.get() as AfArray, cnst_arr.get() as AfArray, + 0); + Array::from(temp) + } + } + } + ) +} + +macro_rules! arith_scalar_spec { + ($ty_name:ty) => ( + arith_scalar_func!($ty_name, Add, add, af_add); + arith_scalar_func!($ty_name, Sub, sub, af_sub); + arith_scalar_func!($ty_name, Mul, mul, af_mul); + arith_scalar_func!($ty_name, Div, div, af_div); + ) +} + +arith_scalar_spec!(Complex); +arith_scalar_spec!(Complex); +arith_scalar_spec!(f64); +arith_scalar_spec!(f32); +arith_scalar_spec!(u64); +arith_scalar_spec!(i64); +arith_scalar_spec!(u32); +arith_scalar_spec!(i32); +arith_scalar_spec!(u8); + +macro_rules! arith_func { + ($op_name:ident, $fn_name:ident, $ffi_fn: ident) => ( + impl<'f> $op_name<&'f Array> for &'f Array { + type Output = Array; + + fn $fn_name(self, rhs:&'f Array) -> Array { + unsafe { + let mut temp: i64 = 0; + $ffi_fn(&mut temp as MutAfArray, + self.get() as AfArray, rhs.get() as AfArray, + 0); + Array::from(temp) + } + } + } + ) +} + +arith_func!(Add, add, af_add); +arith_func!(Sub, sub, af_sub); +arith_func!(Mul, mul, af_mul); +arith_func!(Div, div, af_div); +arith_func!(Rem, rem, af_rem); +arith_func!(BitAnd, bitand, af_bitand); +arith_func!(BitOr, bitor, af_bitor); +arith_func!(BitXor, bitxor, af_bitxor); +arith_func!(Shl, shl, af_bitshiftl); +arith_func!(Shr, shr, af_bitshiftr); diff --git a/src/array.rs b/src/array.rs new file mode 100644 index 000000000..0f266df36 --- /dev/null +++ b/src/array.rs @@ -0,0 +1,187 @@ +extern crate libc; + +use dim4::Dim4; +use defines::Aftype; +use self::libc::{uint8_t, c_void, c_int, c_uint, c_longlong}; + +type MutAfArray = *mut self::libc::c_longlong; +type MutDouble = *mut self::libc::c_double; +type MutUint = *mut self::libc::c_uint; +type AfArray = self::libc::c_longlong; +type DimT = self::libc::c_longlong; + +#[allow(dead_code)] +extern { + fn af_create_array(out: MutAfArray, data: *const c_void, + ndims: c_uint, dims: *const DimT, aftype: uint8_t) -> c_int; + + fn af_get_elements(out: MutAfArray, arr: AfArray) -> c_int; + + fn af_get_type(out: *mut uint8_t, arr: AfArray) -> c_int; + + fn af_get_dims(dim0: *mut c_longlong, dim1: *mut c_longlong, dim2: *mut c_longlong, + dim3: *mut c_longlong, arr: AfArray) -> c_int; + + fn af_get_numdims(result: *mut c_uint, arr: AfArray) -> c_int; + + fn af_is_empty(result: *mut c_int, arr: AfArray) -> c_int; + + fn af_is_scalar(result: *mut c_int, arr: AfArray) -> c_int; + + fn af_is_row(result: *mut c_int, arr: AfArray) -> c_int; + + fn af_is_column(result: *mut c_int, arr: AfArray) -> c_int; + + fn af_is_vector(result: *mut c_int, arr: AfArray) -> c_int; + + fn af_is_complex(result: *mut c_int, arr: AfArray) -> c_int; + + fn af_is_real(result: *mut c_int, arr: AfArray) -> c_int; + + fn af_is_double(result: *mut c_int, arr: AfArray) -> c_int; + + fn af_is_single(result: *mut c_int, arr: AfArray) -> c_int; + + fn af_is_realfloating(result: *mut c_int, arr: AfArray) -> c_int; + + fn af_is_floating(result: *mut c_int, arr: AfArray) -> c_int; + + fn af_is_integer(result: *mut c_int, arr: AfArray) -> c_int; + + fn af_is_bool(result: *mut c_int, arr: AfArray) -> c_int; + + fn af_get_data_ptr(data: *mut c_void, arr: AfArray) -> c_int; + + fn af_eval(arr: AfArray) -> c_int; + + fn af_retain_array(out: MutAfArray, arr: AfArray) -> c_int; + + fn af_release_array(arr: AfArray) -> c_int; + + fn af_print_array(arr: AfArray) -> c_int; +} + +pub struct Array { + handle: i64, +} + +macro_rules! is_func { + ($fn_name: ident, $ffi_fn: ident) => ( + pub fn $fn_name(&self) -> bool { + unsafe { + let mut ret_val: i32 = 0; + $ffi_fn(&mut ret_val as *mut c_int, self.handle as AfArray); + ret_val > 0 + } + } + ) +} + +impl Array { + #[allow(unused_mut)] + pub fn new(dims: Dim4, slice: &[T], aftype: Aftype) -> Array { + unsafe { + let mut temp: i64 = 0; + af_create_array(&mut temp as MutAfArray, slice.as_ptr() as *const c_void, + dims.ndims() as c_uint, dims.get().as_ptr() as * const c_longlong, + aftype as uint8_t); + Array {handle: temp} + } + } + + pub fn elements(&self) -> i64 { + unsafe { + let mut ret_val: i64 = 0; + af_get_elements(&mut ret_val as MutAfArray, self.handle as AfArray); + ret_val + } + } + + pub fn get_type(&self) -> Aftype { + unsafe { + let mut ret_val: u8 = 0; + af_get_type(&mut ret_val as *mut uint8_t, self.handle as AfArray); + Aftype::from(ret_val) + } + } + + pub fn dims(&self) -> Dim4 { + unsafe { + let mut ret0: i64 = 0; + let mut ret1: i64 = 0; + let mut ret2: i64 = 0; + let mut ret3: i64 = 0; + af_get_dims(&mut ret0 as *mut c_longlong, &mut ret1 as *mut c_longlong, + &mut ret2 as *mut c_longlong, &mut ret3 as *mut c_longlong, + self.handle as AfArray); + Dim4::new(&[ret0 as u64, ret1 as u64, ret2 as u64, ret3 as u64]) + } + } + + pub fn numdims(&self) -> u32 { + unsafe { + let mut ret_val: u32 = 0; + af_get_numdims(&mut ret_val as *mut c_uint, self.handle as AfArray); + ret_val + } + } + + pub fn get(&self) -> i64 { + self.handle + } + + pub fn host(&self, data:&mut [f64]) { + unsafe { + af_get_data_ptr(data.as_mut_ptr() as *mut c_void, self.handle as AfArray); + } + } + + pub fn eval(&self) { + unsafe { + af_eval(self.handle as AfArray); + } + } + + is_func!(is_empty, af_is_empty); + is_func!(is_scalar, af_is_scalar); + is_func!(is_row, af_is_row); + is_func!(is_column, af_is_column); + is_func!(is_vector, af_is_vector); + is_func!(is_complex, af_is_complex); + is_func!(is_double, af_is_double); + is_func!(is_single, af_is_single); + is_func!(is_real, af_is_real); + is_func!(is_floating, af_is_floating); + is_func!(is_integer, af_is_integer); + is_func!(is_bool, af_is_bool); +} + +impl From for Array { + fn from(t: i64) -> Array { + Array {handle: t} + } +} + +impl Clone for Array { + fn clone(&self) -> Array { + unsafe { + let mut temp: i64 = 0; + af_retain_array(&mut temp as MutAfArray, self.handle as AfArray); + Array {handle: temp} + } + } +} + +impl Drop for Array { + fn drop(&mut self) { + unsafe { + af_release_array(self.handle); + } + } +} + +pub fn print(input: &Array) { + unsafe { + af_print_array(input.get() as AfArray); + } +} diff --git a/src/blas/mod.rs b/src/blas/mod.rs new file mode 100644 index 000000000..4706015cd --- /dev/null +++ b/src/blas/mod.rs @@ -0,0 +1,57 @@ +extern crate libc; + +use array::Array; +use defines::MatProp; +use self::libc::{c_uint, c_int}; +use util::to_u32; + +type MutAfArray = *mut self::libc::c_longlong; +type AfArray = self::libc::c_longlong; + +#[allow(dead_code)] +extern { + fn af_matmul(out: MutAfArray, lhs: AfArray, rhs: AfArray, + optlhs: c_uint, optrhs: c_uint) -> c_int; + + fn af_dot(out: MutAfArray, lhs: AfArray, rhs: AfArray, + optlhs: c_uint, optrhs: c_uint) -> c_int; + + fn af_transpose(out: MutAfArray, arr: AfArray, conjugate: c_int) -> c_int; + fn af_transpose_inplace(arr: AfArray, conjugate: c_int) -> c_int; +} + +#[allow(unused_mut)] +pub fn matmul(lhs: &Array, rhs: &Array, optlhs: MatProp, optrhs: MatProp) -> Array { + unsafe { + let mut temp: i64 = 0; + af_matmul(&mut temp as MutAfArray, lhs.get() as AfArray, rhs.get() as AfArray, + to_u32(optlhs) as c_uint, to_u32(optrhs) as c_uint); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn dot(lhs: &Array, rhs: &Array, optlhs: MatProp, optrhs: MatProp) -> Array { + unsafe { + let mut temp: i64 = 0; + af_dot(&mut temp as MutAfArray, lhs.get() as AfArray, rhs.get() as AfArray, + to_u32(optlhs) as c_uint, to_u32(optrhs) as c_uint); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn transpose(arr: &Array, conjugate: bool) -> Array { + unsafe { + let mut temp: i64 = 0; + af_transpose(&mut temp as MutAfArray, arr.get() as AfArray, conjugate as c_int); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn transpose_inplace(arr: &Array, conjugate: bool) { + unsafe { + af_transpose_inplace(arr.get() as AfArray, conjugate as c_int); + } +} diff --git a/src/data/mod.rs b/src/data/mod.rs new file mode 100644 index 000000000..b0ee8e4de --- /dev/null +++ b/src/data/mod.rs @@ -0,0 +1,322 @@ +extern crate libc; +extern crate num; + +use array::Array; +use dim4::Dim4; +use defines::Aftype; +use self::libc::{uint8_t, c_int, c_uint, c_double}; +use self::num::Complex; + +use std::vec::Vec; + +type MutAfArray = *mut self::libc::c_longlong; +type MutDouble = *mut self::libc::c_double; +type MutUint = *mut self::libc::c_uint; +type AfArray = self::libc::c_longlong; +type DimT = self::libc::c_longlong; +type Intl = self::libc::c_longlong; +type Uintl = self::libc::c_ulonglong; + +#[allow(dead_code)] +extern { + fn af_constant(out: MutAfArray, val: c_double, + ndims: c_uint, dims: *const DimT, afdtype: c_int) -> c_int; + + fn af_constant_complex(out: MutAfArray, real: c_double, imag: c_double, + ndims: c_uint, dims: *const DimT, afdtype: c_int) -> c_int; + + fn af_constant_long(out: MutAfArray, val: Intl, + ndims: c_uint, dims: *const DimT) -> c_int; + + fn af_constant_ulong(out: MutAfArray, val: Uintl, + ndims: c_uint, dims: *const DimT) -> c_int; + + fn af_range(out: MutAfArray, ndims: c_uint, dims: *const DimT, + seq_dims: c_int, afdtype: uint8_t) -> c_int; + + fn af_iota(out: MutAfArray, ndims: c_uint, dims: *const DimT, + t_ndims: c_uint, tdims: *const DimT, afdtype: uint8_t) -> c_int; + + fn af_randu(out: MutAfArray, ndims: c_uint, dims: *const DimT, afdtype: uint8_t) -> c_int; + fn af_randn(out: MutAfArray, ndims: c_uint, dims: *const DimT, afdtype: uint8_t) -> c_int; + + fn af_set_seed(seed: Uintl); + fn af_get_seed(seed: *mut Uintl); + + fn af_identity(out: MutAfArray, ndims: c_uint, dims: *const DimT, afdtype: uint8_t) -> c_int; + fn af_diag_create(out: MutAfArray, arr: AfArray, num: c_int) -> c_int; + fn af_diag_extract(out: MutAfArray, arr: AfArray, num: c_int) -> c_int; + fn af_join(out: MutAfArray, dim: c_int, first: AfArray, second: AfArray) -> c_int; + fn af_join_many(out: MutAfArray, dim: c_int, n_arrays: c_uint, inpts: *const AfArray) -> c_int; + + fn af_tile(out: MutAfArray, arr: AfArray, x: c_uint, y: c_uint, z: c_uint, w: c_uint) -> c_int; + fn af_reorder(o: MutAfArray, a: AfArray, x: c_uint, y: c_uint, z: c_uint, w: c_uint) -> c_int; + fn af_shift(o: MutAfArray, a: AfArray, x: c_uint, y: c_uint, z: c_uint, w: c_uint) -> c_int; + fn af_moddims(out: MutAfArray, arr: AfArray, ndims: c_uint, dims: *const DimT) -> c_int; + + fn af_flat(out: MutAfArray, arr: AfArray) -> c_int; + fn af_flip(out: MutAfArray, arr: AfArray, dim: c_uint) -> c_int; + fn af_lower(out: MutAfArray, arr: AfArray, is_unit_diag: c_int) -> c_int; + fn af_upper(out: MutAfArray, arr: AfArray, is_unit_diag: c_int) -> c_int; +} + +pub trait ConstGenerator { + fn generate(&self, dims: Dim4) -> Array; +} + +#[allow(unused_mut)] +impl ConstGenerator for i64 { + fn generate(&self, dims: Dim4) -> Array { + unsafe { + let mut temp: i64 = 0; + af_constant_long(&mut temp as MutAfArray, *self as Intl, + dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT); + Array::from(temp) + } + } +} + +#[allow(unused_mut)] +impl ConstGenerator for u64 { + fn generate(&self, dims: Dim4) -> Array { + unsafe { + let mut temp: i64 = 0; + af_constant_ulong(&mut temp as MutAfArray, *self as Uintl, + dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT); + Array::from(temp) + } + } +} + +#[allow(unused_mut)] +impl ConstGenerator for Complex { + fn generate(&self, dims: Dim4) -> Array { + unsafe { + let mut temp: i64 = 0; + af_constant_complex(&mut temp as MutAfArray, + (*self).re as c_double, (*self).im as c_double, + dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT, 1); + Array::from(temp) + } + } +} + +#[allow(unused_mut)] +impl ConstGenerator for Complex { + fn generate(&self, dims: Dim4) -> Array { + unsafe { + let mut temp: i64 = 0; + af_constant_complex(&mut temp as MutAfArray, + (*self).re as c_double, (*self).im as c_double, + dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT, 3); + Array::from(temp) + } + } +} + +macro_rules! cnst { + ($rust_type:ty, $ffi_type:expr) => ( + #[allow(unused_mut)] + impl ConstGenerator for $rust_type { + fn generate(&self, dims: Dim4) -> Array { + unsafe { + let mut temp: i64 = 0; + af_constant(&mut temp as MutAfArray, *self as c_double, + dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT, + $ffi_type); + Array::from(temp) + } + } + } + ) +} + +cnst!(f32 , 0); +cnst!(f64 , 2); +cnst!(bool, 4); +cnst!(i32 , 5); +cnst!(u32 , 6); +cnst!(u8 , 7); + + +pub fn constant(cnst: T, dims: Dim4) -> Array { + cnst.generate(dims) +} + +#[allow(unused_mut)] +pub fn range(dims: Dim4, seq_dim: i32, aftype: Aftype) -> Array { + unsafe { + let mut temp: i64 = 0; + af_range(&mut temp as MutAfArray, + dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT, + seq_dim as c_int, aftype as uint8_t); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn iota(dims: Dim4, tdims: Dim4, aftype: Aftype) -> Array { + unsafe { + let mut temp: i64 = 0; + af_iota(&mut temp as MutAfArray, + dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT, + tdims.ndims() as c_uint, tdims.get().as_ptr() as *const DimT, + aftype as uint8_t); + Array::from(temp) + } +} + +pub fn set_seed(seed: u64) { + unsafe { af_set_seed(seed as Uintl); } +} + +#[allow(unused_mut)] +pub fn get_seed() -> u64 { + unsafe { + let mut temp: u64 = 0; + af_get_seed(&mut temp as *mut Uintl); + temp + } +} + +macro_rules! data_gen_def { + ($fn_name:ident, $ffi_name: ident) => ( + #[allow(unused_mut)] + pub fn $fn_name(dims: Dim4, aftype: Aftype) -> Array { + unsafe { + let mut temp: i64 = 0; + $ffi_name(&mut temp as MutAfArray, + dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT, + aftype as uint8_t); + Array::from(temp) + } + } + ) +} + +data_gen_def!(randu, af_randu); +data_gen_def!(randn, af_randn); +data_gen_def!(identity, af_identity); + +#[allow(unused_mut)] +pub fn diag_create(input: &Array, dim: i32) -> Array { + unsafe { + let mut temp: i64 = 0; + af_diag_create(&mut temp as MutAfArray, input.get() as AfArray, dim as c_int); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn diag_extract(input: &Array, dim: i32) -> Array { + unsafe { + let mut temp: i64 = 0; + af_diag_extract(&mut temp as MutAfArray, input.get() as AfArray, dim as c_int); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn join(dim: i32, first: &Array, second: &Array) -> Array { + unsafe { + let mut temp: i64 = 0; + af_join(&mut temp as MutAfArray, dim as c_int, + first.get() as AfArray, second.get() as AfArray); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn join_many(dim: i32, inputs: Vec<&Array>) -> Array { + unsafe { + let mut temp: i64 = 0; + af_join_many(&mut temp as MutAfArray, dim as c_int, + inputs.len() as c_uint, inputs.as_ptr() as *const AfArray); + Array::from(temp) + } +} + +// Using macro to implement join many wrapper +#[macro_export] +macro_rules! join_many { + [$dim: expr; $($x:ident),+] => { + { + let mut temp_vec = Vec::new(); + $( + temp_vec.push($x); + )* + let mut temp: i64 = 0; + unsafe { + let mut temp: i64 = 0; + af_join_many(&mut temp as MutAfArray, $dim as c_int, + temp_vec.len() as c_uint, temp_vec.as_ptr() as *const AfArray); + Array::from(temp) + } + } + }; +} + +macro_rules! data_func_def { + ($fn_name:ident, $ffi_name: ident) => ( + #[allow(unused_mut)] + pub fn $fn_name(input: &Array, dims: Dim4) -> Array { + unsafe { + let mut temp: i64 = 0; + $ffi_name(&mut temp as MutAfArray, input.get() as AfArray, + dims[0] as c_uint, dims[1] as c_uint, + dims[2] as c_uint, dims[3] as c_uint); + Array::from(temp) + } + } + ) +} + +data_func_def!(tile, af_tile); +data_func_def!(reorder, af_reorder); +data_func_def!(shift, af_shift); + +#[allow(unused_mut)] +pub fn moddims(input: &Array, dims: Dim4) -> Array { + unsafe { + let mut temp: i64 = 0; + af_moddims(&mut temp as MutAfArray, input.get() as AfArray, + dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn flat(input: &Array) -> Array { + unsafe { + let mut temp: i64 = 0; + af_flat(&mut temp as MutAfArray, input.get() as AfArray); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn flip(input: &Array, dim: u32) -> Array { + unsafe { + let mut temp: i64 = 0; + af_flip(&mut temp as MutAfArray, input.get() as AfArray, dim as c_uint); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn lower(input: &Array, is_unit_diag: bool) -> Array { + unsafe { + let mut temp: i64 = 0; + af_lower(&mut temp as MutAfArray, input.get() as AfArray, is_unit_diag as c_int); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn upper(input: &Array, is_unit_diag: bool) -> Array { + unsafe { + let mut temp: i64 = 0; + af_upper(&mut temp as MutAfArray, input.get() as AfArray, is_unit_diag as c_int); + Array::from(temp) + } +} diff --git a/src/defines.rs b/src/defines.rs new file mode 100644 index 000000000..957eb8eae --- /dev/null +++ b/src/defines.rs @@ -0,0 +1,94 @@ +#[derive(Copy, Clone)] +pub enum Aftype { + F32 = 0, + C32 = 1, + F64 = 2, + C64 = 3, + B8 = 4, + S32 = 5, + U32 = 6, + U8 = 7, + S64 = 8, + U64 = 9, +} + +#[derive(Copy, Clone)] +pub enum InterpType { + NEAREST = 0, + LINEAR = 1, + BILINEAR= 2, + CUBIC = 3, +} + +#[derive(Copy, Clone)] +pub enum BorderType { + ZERO = 0, + SYMMETRIC = 1, +} + +#[derive(Copy, Clone)] +pub enum Connectivity { + FOUR = 4, + EIGHT = 8 +} + +#[derive(Copy, Clone)] +pub enum ConvMode { + DEFAULT = 0, + EXPAND = 1, +} + +#[derive(Copy, Clone)] +pub enum ConvDomain { + AUTO = 0, + SPATIAL = 1, + FREQUENCY= 2, +} + +#[derive(Copy, Clone)] +pub enum MatchType { + SAD = 0, + ZSAD= 1, + LSAD= 2, + SSD = 3, + ZSSD= 4, + LSSD= 5, + NCC = 6, + ZNCC= 7, + SHD = 8, +} + +#[derive(Copy, Clone)] +pub enum ColorSpace { + GRAY = 0, + RGB = 1, + HSV = 2, +} + +#[derive(Copy, Clone)] +pub enum MatProp { + NONE, + TRANS, + CTRANS, + UPPER, + LOWER, + DIAGUNIT, + SYM, + POSDEF, + ORTHOG, + TRIDIAG, + BLOCKDIAG, +} + +#[allow(non_camel_case_types)] +#[derive(Copy, Clone)] +pub enum NormType { + VECTOR_1 = 0, + VECTOR_INF = 1, + VECTOR_2 = 2, + VECTOR_P = 3, + MATRIX_1 = 4, + MATRIX_INF = 5, + MATRIX_2 = 6, + MATRIX_L_PQ = 7, +} diff --git a/src/device/mod.rs b/src/device/mod.rs new file mode 100644 index 000000000..ad75a35c6 --- /dev/null +++ b/src/device/mod.rs @@ -0,0 +1,29 @@ +extern crate libc; + +use self::libc::c_int; + +extern { + fn af_get_version(major: *mut c_int, minor: *mut c_int, patch: *mut c_int) -> c_int; + + fn af_info() -> c_int; + + fn af_set_device(device: c_int) -> c_int; +} + +pub fn get_version() -> (i32, i32, i32) { + unsafe { + let mut maj: i32 = 0; + let mut min: i32 = 0; + let mut pat: i32 = 0; + af_get_version(&mut maj as *mut c_int, &mut min as *mut c_int, &mut pat as *mut c_int); + (maj, min, pat) + } +} + +pub fn info() { + unsafe { af_info(); } +} + +pub fn set_device(device: i32) { + unsafe { af_set_device(device as c_int); } +} diff --git a/src/dim4.rs b/src/dim4.rs new file mode 100644 index 000000000..5abe3c848 --- /dev/null +++ b/src/dim4.rs @@ -0,0 +1,55 @@ +use std::fmt; +use std::ops::Index; + +#[derive(Copy, Clone)] +pub struct Dim4 { + dims: [u64; 4], +} + +impl Default for Dim4 { + fn default() -> Dim4 { + Dim4 { dims:[1, 1, 1, 1] } + } +} + +impl Index for Dim4 { + type Output = u64; + + fn index<'a>(&'a self, _index: usize) ->&'a u64 { + &self.dims[_index] + } +} + +impl fmt::Display for Dim4 { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "[{} {} {} {}]", self.dims[0], self.dims[1], self.dims[2], self.dims[3]) + } +} + +impl Dim4 { + pub fn new(dims: &[u64; 4]) -> Dim4 { + Dim4 { dims: dims.clone(), } + } + + pub fn elements(&self) -> u64 { + self.dims[0]*self.dims[1]*self.dims[2]*self.dims[3] + } + + pub fn ndims(&self) -> usize { + let nelems = self.elements(); + match nelems { + 0 => 0, + 1 => 0, + _ => { + if self.dims[3] != 1 { 4 } + else if self.dims[2] != 1 { 3 } + else if self.dims[1] != 1 { 2 } + else { 1 } + }, + } + } + + pub fn get(&self) -> &[u64; 4] { + &self.dims + } +} diff --git a/src/image/mod.rs b/src/image/mod.rs new file mode 100644 index 000000000..80fc4e265 --- /dev/null +++ b/src/image/mod.rs @@ -0,0 +1,318 @@ +extern crate libc; + +use array::Array; +use defines::Aftype; +use defines::BorderType; +use defines::ColorSpace; +use defines::Connectivity; +use defines::InterpType; +use self::libc::{uint8_t, c_uint, c_int, c_float, c_double}; + +type MutAfArray = *mut self::libc::c_longlong; +type AfArray = self::libc::c_longlong; +type DimT = self::libc::c_longlong; + +#[allow(dead_code)] +extern { + fn af_gradient(dx: MutAfArray, dy: MutAfArray, arr: AfArray) -> c_int; + fn af_load_image(out: MutAfArray, filename: *const u8, iscolor: c_int) -> c_int; + fn af_save_image(filename: *const u8, input: AfArray) -> c_int; + + fn af_resize(out: MutAfArray, input: AfArray, + odim0: DimT, odim1: DimT, method: uint8_t) -> c_int; + + fn af_transform(out: MutAfArray, input: AfArray, trans: AfArray, + odim0: DimT, odim1: DimT, method: uint8_t, is_inverse: c_int) -> c_int; + + fn af_rotate(out: MutAfArray, input: AfArray, theta: c_float, crop: c_int, + method: uint8_t) -> c_int; + + fn af_translate(out: MutAfArray, input: AfArray, trans0: c_float, trans1: c_float, + odim0: DimT, odim1: DimT, method: uint8_t) -> c_int; + + fn af_scale(out: MutAfArray, input: AfArray, scale0: c_float, scale1: c_float, + odim0: DimT, odim1: DimT, method: uint8_t) -> c_int; + + fn af_skew(out: MutAfArray, input: AfArray, skew0: c_float, skew1: c_float, + odim0: DimT, odim1: DimT, method: uint8_t, is_inverse: c_int) -> c_int; + + fn af_histogram(out: MutAfArray, input: AfArray, nbins: c_uint, + minval: c_double, maxval: c_double) -> c_int; + + fn af_dilate(out: MutAfArray, input: AfArray, mask: AfArray) -> c_int; + fn af_dilate3(out: MutAfArray, input: AfArray, mask: AfArray) -> c_int; + fn af_erode(out: MutAfArray, input: AfArray, mask: AfArray) -> c_int; + fn af_erode3(out: MutAfArray, input: AfArray, mask: AfArray) -> c_int; + fn af_regions(out: MutAfArray, input: AfArray, conn: uint8_t, aftype: uint8_t) -> c_int; + fn af_sobel_operator(dx: MutAfArray, dy: MutAfArray, i: AfArray, ksize: c_uint) -> c_int; + fn af_rgb2gray(out: MutAfArray, input: AfArray, r: c_float, g: c_float, b: c_float) -> c_int; + fn af_gray2rgb(out: MutAfArray, input: AfArray, r: c_float, g: c_float, b: c_float) -> c_int; + fn af_hist_equal(out: MutAfArray, input: AfArray, hist: AfArray) -> c_int; + fn af_hsv2rgb(out: MutAfArray, input: AfArray) -> c_int; + fn af_rgb2hsv(out: MutAfArray, input: AfArray) -> c_int; + + fn af_bilateral(out: MutAfArray, input: AfArray, + sp_sig: c_float, ch_sig: c_float, iscolor: c_int) -> c_int; + + fn af_mean_shift(out: MutAfArray, input: AfArray, sp_sig: c_float, + ch_sig: c_float, iter: c_uint, iscolor: c_int) -> c_int; + + fn af_medfilt(out: MutAfArray, input: AfArray, + wlen: DimT, wwid: DimT, etype: uint8_t) -> c_int; + + fn af_minfilt(out: MutAfArray, input: AfArray, + wlen: DimT, wwid: DimT, etype: uint8_t) -> c_int; + + fn af_maxfilt(out: MutAfArray, input: AfArray, + wlen: DimT, wwid: DimT, etype: uint8_t) -> c_int; + + fn af_gaussian_kernel(out: MutAfArray, rows: c_int, cols: c_int, + sigma_r: c_double, sigma_c: c_double) -> c_int; + + fn af_color_space(out: MutAfArray, input: AfArray, + tospace: uint8_t, fromspace: uint8_t) -> c_int; +} + +#[allow(unused_mut)] +pub fn gradient(input: &Array) -> (Array, Array) { + unsafe { + let mut dx: i64 = 0; + let mut dy: i64 = 0; + af_gradient(&mut dx as MutAfArray, &mut dy as MutAfArray, input.get() as AfArray); + (Array::from(dx), Array::from(dy)) + } +} + +#[allow(unused_mut)] +pub fn load_image(filename: &[u8], is_color: bool) -> Array { + unsafe { + let mut temp: i64 = 0; + af_load_image(&mut temp as MutAfArray, + filename.as_ptr() as *const u8, is_color as c_int); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn save_image(filename: &[u8], input: &Array) { + unsafe { + af_save_image(filename.as_ptr() as *const u8, input.get() as AfArray); + } +} + +#[allow(unused_mut)] +pub fn resize(input: &Array, odim0: i64, odim1: i64, method: InterpType) -> Array { + unsafe { + let mut temp: i64 = 0; + af_resize(&mut temp as MutAfArray, input.get() as AfArray, odim0 as DimT, + odim1 as DimT, method as uint8_t); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn transform(input: &Array, trans: &Array, odim0: i64, odim1: i64, + method: InterpType, is_inverse: bool) -> Array { + unsafe { + let mut temp: i64 = 0; + af_transform(&mut temp as MutAfArray, input.get() as AfArray, trans.get() as AfArray, + odim0 as DimT, odim1 as DimT, method as uint8_t, is_inverse as c_int); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn rotate(input: &Array, theta: f64, crop: bool, method: InterpType) -> Array { + unsafe { + let mut temp: i64 = 0; + af_rotate(&mut temp as MutAfArray, input.get() as AfArray, theta as c_float, + crop as c_int, method as uint8_t); + Array::from(temp) + } +} + +macro_rules! trans_func_def { + ($fn_name: ident, $ffi_name: ident) => ( + #[allow(unused_mut)] + pub fn $fn_name(input: &Array, p0: f32, p1: f32, + odim0: i64, odim1: i64, method: InterpType) -> Array { + unsafe { + let mut temp: i64 = 0; + $ffi_name(&mut temp as MutAfArray, + input.get() as AfArray, + p0 as c_float, p1 as c_float, + odim0 as DimT, odim1 as DimT, + method as uint8_t); + Array::from(temp) + } + } + ) +} + +trans_func_def!(translate, af_translate); +trans_func_def!(scale, af_scale); + +#[allow(unused_mut)] +pub fn skew(input: &Array, skew0: f32, skew1: f32, odim0: i64, odim1: i64, + method: InterpType, is_inverse: bool) -> Array { + unsafe { + let mut temp: i64 = 0; + af_skew(&mut temp as MutAfArray, input.get() as AfArray, + skew0 as c_float, skew1 as c_float, odim0 as DimT, odim1 as DimT, + method as uint8_t, is_inverse as c_int); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn histogram(input: &Array, nbins: u32, minval: f64, maxval: f64) -> Array { + unsafe { + let mut temp: i64 = 0; + af_histogram(&mut temp as MutAfArray, input.get() as AfArray, + nbins as c_uint, minval as c_double, maxval as c_double); + Array::from(temp) + } +} + +macro_rules! morph_func_def { + ($fn_name: ident, $ffi_name: ident) => ( + #[allow(unused_mut)] + pub fn $fn_name(input: &Array, mask: &Array) -> Array { + unsafe { + let mut temp: i64 = 0; + $ffi_name(&mut temp as MutAfArray, input.get() as AfArray, mask.get() as AfArray); + Array::from(temp) + } + } + ) +} + +morph_func_def!(dilate, af_dilate); +morph_func_def!(erode, af_erode); +morph_func_def!(dilate3, af_dilate3); +morph_func_def!(erode3, af_erode3); + +#[allow(unused_mut)] +pub fn bilateral(input: &Array, spatial_sigma: f32, chromatic_sigma: f32, + iscolor: bool) -> Array { + unsafe { + let mut temp: i64 = 0; + af_bilateral(&mut temp as MutAfArray, input.get() as AfArray, + spatial_sigma as c_float, chromatic_sigma as c_float, + iscolor as c_int); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn mean_shift(input: &Array, spatial_sigma: f32, chromatic_sigma: f32, + iter: u32, iscolor: bool) -> Array { + unsafe { + let mut temp: i64 = 0; + af_mean_shift(&mut temp as MutAfArray, input.get() as AfArray, + spatial_sigma as c_float, chromatic_sigma as c_float, + iter as c_uint, iscolor as c_int); + Array::from(temp) + } +} + +macro_rules! filt_func_def { + ($fn_name: ident, $ffi_name: ident) => ( + #[allow(unused_mut)] + pub fn $fn_name(input: &Array, wlen: i64, wwid: i64, etype: BorderType) -> Array { + unsafe { + let mut temp: i64 = 0; + $ffi_name(&mut temp as MutAfArray, input.get() as AfArray, + wlen as DimT, wwid as DimT, etype as uint8_t); + Array::from(temp) + } + } + ) +} + +filt_func_def!(medfilt, af_medfilt); +filt_func_def!(minfilt, af_minfilt); +filt_func_def!(maxfilt, af_maxfilt); + +#[allow(unused_mut)] +pub fn gaussian_kernel(rows: i32, cols: i32, sigma_r: f64, sigma_c: f64) -> Array { + unsafe { + let mut temp: i64 = 0; + af_gaussian_kernel(&mut temp as MutAfArray, rows as c_int, cols as c_int, + sigma_r as c_double, sigma_c as c_double); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn color_space(input: &Array, tospace: ColorSpace, fromspace: ColorSpace) -> Array { + unsafe { + let mut temp: i64 = 0; + af_color_space(&mut temp as MutAfArray, input.get() as AfArray, + tospace as uint8_t, fromspace as uint8_t); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn regions(input: &Array, conn: Connectivity, aftype: Aftype) -> Array { + unsafe { + let mut temp: i64 = 0; + af_regions(&mut temp as MutAfArray, input.get() as AfArray, + conn as uint8_t, aftype as uint8_t); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn sobel(input: &Array, ker_size: u32) -> (Array, Array) { + unsafe { + let mut dx: i64 = 0; + let mut dy: i64 = 0; + af_sobel_operator(&mut dx as MutAfArray, &mut dy as MutAfArray, + input.get() as AfArray, ker_size as c_uint); + (Array::from(dx), Array::from(dy)) + } +} + +#[allow(unused_mut)] +pub fn hist_equal(input: &Array, hist: &Array) -> Array { + unsafe { + let mut temp: i64 = 0; + af_hist_equal(&mut temp as MutAfArray, input.get() as AfArray, hist.get() as AfArray); + Array::from(temp) + } +} + +macro_rules! grayrgb_func_def { + ($fn_name: ident, $ffi_name: ident) => ( + #[allow(unused_mut)] + pub fn $fn_name(input: &Array, r: f32, g: f32, b: f32) -> Array { + unsafe { + let mut temp: i64 = 0; + $ffi_name(&mut temp as MutAfArray, input.get() as AfArray, + r as c_float, g as c_float, b as c_float); + Array::from(temp) + } + } + ) +} + +grayrgb_func_def!(rgb2gray, af_rgb2gray); +grayrgb_func_def!(gray2rgb, af_gray2rgb); + +macro_rules! hsvrgb_func_def { + ($fn_name: ident, $ffi_name: ident) => ( + #[allow(unused_mut)] + pub fn $fn_name(input: &Array) -> Array { + unsafe { + let mut temp: i64 = 0; + $ffi_name(&mut temp as MutAfArray, input.get() as AfArray); + Array::from(temp) + } + } + ) +} + +hsvrgb_func_def!(hsv2rgb, af_hsv2rgb); +hsvrgb_func_def!(rgb2hsv, af_rgb2hsv); diff --git a/src/lapack/mod.rs b/src/lapack/mod.rs new file mode 100644 index 000000000..9a1d1be56 --- /dev/null +++ b/src/lapack/mod.rs @@ -0,0 +1,148 @@ +extern crate libc; + +use array::Array; +use defines::NormType; +use util::to_u32; +use self::libc::{uint8_t, c_int, c_uint, c_double}; + +type MutAfArray = *mut self::libc::c_longlong; +type MutDouble = *mut self::libc::c_double; +type AfArray = self::libc::c_longlong; + +#[allow(dead_code)] +extern { + fn af_lu(lower: MutAfArray, upper: MutAfArray, pivot: MutAfArray, input: AfArray) -> c_int; + fn af_lu_inplace(pivot: MutAfArray, input: AfArray, is_lapack_piv: c_int) -> c_int; + fn af_qr(q: MutAfArray, r: MutAfArray, tau: MutAfArray, input: AfArray) -> c_int; + fn af_qr_inplace(tau: MutAfArray, input: AfArray) -> c_int; + fn af_cholesky(out: MutAfArray, info: *mut c_int, input: AfArray, is_upper: c_int) -> c_int; + fn af_cholesky_inplace(info: *mut c_int, input: AfArray, is_upper: c_int) -> c_int; + fn af_solve(x: MutAfArray, a: AfArray, b: AfArray, options: c_uint) -> c_int; + fn af_solve_lu(x: MutAfArray, a: AfArray, piv: AfArray, b: AfArray, options: c_uint) -> c_int; + fn af_inverse(out: MutAfArray, input: AfArray, options: c_uint) -> c_int; + fn af_rank(rank: *mut c_uint, input: AfArray, tol: c_double) -> c_int; + fn af_det(det_real: MutDouble, det_imag: MutDouble, input: AfArray) -> c_int; + fn af_norm(out: MutDouble, input: AfArray, ntype: uint8_t, p: c_double, q: c_double) -> c_int; +} + +#[allow(unused_mut)] +pub fn lu(input: &Array) -> (Array, Array, Array) { + unsafe { + let mut lower: i64 = 0; + let mut upper: i64 = 0; + let mut pivot: i64 = 0; + af_lu(&mut lower as MutAfArray, &mut upper as MutAfArray, + &mut pivot as MutAfArray, input.get() as AfArray); + (Array::from(lower), Array::from(upper), Array::from(pivot)) + } +} + +#[allow(unused_mut)] +pub fn lu_inplace(input: &mut Array, is_lapack_piv: bool) -> Array { + unsafe { + let mut pivot: i64 = 0; + af_lu_inplace(&mut pivot as MutAfArray, input.get() as AfArray, + is_lapack_piv as c_int); + Array::from(pivot) + } +} + +#[allow(unused_mut)] +pub fn qr(input: &Array) -> (Array, Array, Array) { + unsafe { + let mut q: i64 = 0; + let mut r: i64 = 0; + let mut tau: i64 = 0; + af_qr(&mut q as MutAfArray, &mut r as MutAfArray, + &mut tau as MutAfArray, input.get() as AfArray); + (Array::from(q), Array::from(r), Array::from(tau)) + } +} + +#[allow(unused_mut)] +pub fn qr_inplace(input: &mut Array) -> Array { + unsafe { + let mut tau: i64 = 0; + af_lu_inplace(&mut tau as MutAfArray, input.get() as AfArray); + Array::from(tau) + } +} + +#[allow(unused_mut)] +pub fn cholesky(input: &Array, is_upper: bool) -> (Array, i32) { + unsafe { + let mut temp: i64 = 0; + let mut info: i32 = 0; + af_cholesky(&mut temp as MutAfArray, &mut info as *mut c_int, + input.get() as AfArray, is_upper as c_int); + (Array::from(temp), info) + } +} + +#[allow(unused_mut)] +pub fn cholesky_inplace(input: &mut Array, is_upper: bool) -> i32 { + unsafe { + let mut info: i32 = 0; + af_cholesky_inplace(&mut info as *mut c_int, input.get() as AfArray, + is_upper as c_int); + info + } +} + +#[allow(unused_mut)] +pub fn solve(a: &Array, b: &Array, options: MatProp) -> Array { + unsafe { + let mut temp: i64 = 0; + af_solve(&mut temp as MutAfArray, a.get() as AfArray, + b.get() as AfArray, to_u32(options) as c_uint); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn solve_lu(a: &Array, piv: &Array, b: &Array, options: MatProp) -> Array { + unsafe { + let mut temp: i64 = 0; + af_solve_lu(&mut temp as MutAfArray, a.get() as AfArray, piv.get() as AfArray, + b.get() as AfArray, to_u32(options) as c_uint); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn inverse(input: &Array, options: MatProp) -> Array { + unsafe { + let mut temp: i64 = 0; + af_solve(&mut temp as MutAfArray, input.get() as AfArray, to_u32(options) as c_uint); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn rank(input: &Array, tol: f64) -> u32 { + unsafe { + let mut temp: u32 = 0; + af_rank(&mut temp as *mut c_uint, input.get() as AfArray, tol as c_double); + temp + } +} + +#[allow(unused_mut)] +pub fn det(input: &Array) -> (f64, f64) { + unsafe { + let mut real: f64 = 0.0; + let mut imag: f64 = 0.0; + af_det(&mut real as MutDouble, &mut imag as MutDouble, input.get() as AfArray); + (real, imag) + } +} + +#[allow(unused_mut)] +pub fn norm(input: &Array, ntype: NormType, p: f64, q: f64) -> f64 { + unsafe { + let mut out: f64 = 0.0; + af_norm(&mut out as MutDouble, input.get() as AfArray, ntype as uint8_t, + p as c_double, q as c_double); + out + } +} diff --git a/src/lib.rs b/src/lib.rs index 54f322d83..bb7571083 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,374 +1,6 @@ -extern crate libc; - -use libc::{c_void, c_int, c_uint, c_double, c_longlong}; - -use std::fmt; -use std::ops::Index; -use std::ops::Add; - -extern { - fn af_set_device(device: c_int) -> c_int; - - fn af_info() -> c_int; - - fn af_create_array(out: *mut c_longlong, - data: *const c_void, - ndims: c_uint, - dims: *const c_longlong, - af_type: c_int) -> c_int; - - fn af_get_elements(out: *mut c_longlong, - arr: c_longlong) -> c_int; - - fn af_get_type(out: *mut c_int, - arr: c_longlong) -> c_int; - - fn af_get_dims(dim0: *mut c_longlong, - dim1: *mut c_longlong, - dim2: *mut c_longlong, - dim3: *mut c_longlong, - arr: c_longlong) -> c_int; - - fn af_get_numdims(result: *mut c_uint, - arr: c_longlong) -> c_int; - - fn af_get_data_ptr(data: *mut c_void, - arr: c_longlong) -> c_int; - - fn af_eval(arr: c_longlong) -> c_int; - - fn af_release_array(arr: c_longlong) -> c_int; - - fn af_print_array(arr: c_longlong) -> c_int; - - fn af_constant(out: *mut c_longlong, - cnst: c_double, - ndims: c_uint, - dims: *const c_longlong, - af_type: c_int) -> c_int; - - fn af_randu(out: *mut c_longlong, - ndims: c_uint, - dims: *const c_longlong, - af_type: c_int) -> c_int; - - fn af_add(out: *mut c_longlong, - lhs: c_longlong, - rhs: c_longlong, - batch: c_int) -> c_int; - - fn af_sin(out: *mut c_longlong, - arr: c_longlong) -> c_int; - - fn af_fft(out: *mut c_longlong, - arr: c_longlong, - nfac: c_double, - odim0: c_longlong) -> c_int; - - fn af_fft2(out: *mut c_longlong, - arr: c_longlong, - nfac: c_double, - odim0: c_longlong, - odim1: c_longlong) -> c_int; - - fn af_fft3(out: *mut c_longlong, - arr: c_longlong, - nfac: c_double, - odim0: c_longlong, - odim1: c_longlong, - odim2: c_longlong) -> c_int; -} - -#[derive(Clone)] -pub enum Aftype { - F32, - C32, - F64, - C64, - B8, - S32, - U32, - U8, - S64, - U64, -} - -fn get_ffi_type(t: Aftype) -> i32 { - match t { - Aftype::F32 => 0, - Aftype::C32 => 1, - Aftype::F64 => 2, - Aftype::C64 => 3, - Aftype::B8 => 4, - Aftype::S32 => 5, - Aftype::U32 => 6, - Aftype::U8 => 7, - Aftype::S64 => 8, - Aftype::U64 => 9, - } -} - -fn get_af_type(t: i32) -> Aftype { - match t { - 0 => Aftype::F32, - 1 => Aftype::C32, - 2 => Aftype::F64, - 3 => Aftype::C64, - 4 => Aftype::B8 , - 5 => Aftype::S32, - 6 => Aftype::U32, - 7 => Aftype::U8 , - 8 => Aftype::S64, - 9 => Aftype::U64, - _ => Aftype::F32, - } -} - -#[derive(Clone)] -pub struct Dim4 { - dims: [u64; 4], -} - -impl Default for Dim4 { - fn default() -> Dim4 { - Dim4 { dims:[1, 1, 1, 1] } - } -} - -impl Index for Dim4 { - type Output = u64; - - fn index<'a>(&'a self, _index: usize) ->&'a u64 { - &self.dims[_index] - } -} - -impl fmt::Display for Dim4 { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "[{} {} {} {}]", self.dims[0], self.dims[1], self.dims[2], self.dims[3]) - } -} - -impl Dim4 { - pub fn new(dims: &[u64; 4]) -> Dim4 { - Dim4 { dims: dims.clone(), } - } - - pub fn elements(&self) -> u64 { - self.dims[0]*self.dims[1]*self.dims[2]*self.dims[3] - } - - pub fn ndims(&self) -> usize { - let nelems = self.elements(); - match nelems { - 0 => 0, - 1 => 0, - _ => { - if self.dims[3] != 1 { 4 } - else if self.dims[2] != 1 { 3 } - else if self.dims[1] != 1 { 2 } - else { 1 } - }, - } - } - - pub fn get(&self) -> &[u64; 4] { - &self.dims - } -} - -pub struct Array { - handle: i64, -} - -impl Array { - #[allow(unused_mut)] - pub fn new(dims: Dim4, slice: &[T], aftype: Aftype) -> Array { - unsafe { - let mut temp: i64 = 0; - af_create_array(&mut temp as *mut c_longlong, - slice.as_ptr() as *const c_void, - dims.ndims() as c_uint, - dims.get().as_ptr() as * const c_longlong, - get_ffi_type(aftype.clone()) as c_int); - Array { handle: temp } - } - } - - pub fn elements(&self) -> i64 { - unsafe { - let mut ret_val: i64 = 0; - af_get_elements(&mut ret_val as *mut c_longlong, - self.handle as c_longlong); - ret_val - } - } - - pub fn get_type(&self) -> Aftype { - unsafe { - let mut ret_val: i32 = 0; - af_get_type(&mut ret_val as *mut c_int, - self.handle as c_longlong); - get_af_type(ret_val) - } - } - - pub fn dims(&self) -> Dim4 { - unsafe { - let mut ret0: i64 = 0; - let mut ret1: i64 = 0; - let mut ret2: i64 = 0; - let mut ret3: i64 = 0; - af_get_dims(&mut ret0 as *mut c_longlong, - &mut ret1 as *mut c_longlong, - &mut ret2 as *mut c_longlong, - &mut ret3 as *mut c_longlong, - self.handle as c_longlong); - Dim4 { dims: [ret0 as u64, ret1 as u64, ret2 as u64, ret3 as u64] } - } - } - - pub fn numdims(&self) -> u32 { - unsafe { - let mut ret_val: u32 = 0; - af_get_numdims(&mut ret_val as *mut c_uint, - self.handle as c_longlong); - ret_val - } - } - - pub fn get(&self) -> i64 { - self.handle - } - - pub fn host(&self, data:&mut [f64]) { - unsafe { - af_get_data_ptr(data.as_mut_ptr() as *mut c_void, - self.handle as c_longlong); - } - } - - pub fn eval(&self) { - unsafe { - af_eval(self.handle as c_longlong); - } - } -} - -impl Drop for Array { - fn drop(&mut self) { - unsafe { - af_release_array(self.handle); - } - } -} - -impl Add for Array { - type Output = Array; - - fn add(self, rhs: f64) -> Array { - let cnst_arr = constant(rhs, self.dims(), self.get_type().clone()); - unsafe { - let mut temp: i64 = 0; - af_add(&mut temp as *mut c_longlong, - self.get() as c_longlong, - cnst_arr.get() as c_longlong, - 0); - Array { handle: temp } - } - } -} - -pub fn set_device(device: i32) { - unsafe { - af_set_device(device as c_int); - } -} - -pub fn info() { - unsafe { - af_info(); - } -} - -pub fn print(input: &Array) { - unsafe { - af_print_array(input.get() as c_longlong); - } -} - -#[allow(unused_mut)] -pub fn randu(dims: Dim4, aftype: Aftype) -> Array { - unsafe { - let mut temp: i64 = 0; - af_randu(&mut temp as *mut c_longlong, - dims.ndims() as c_uint, - dims.get().as_ptr() as * const c_longlong, - get_ffi_type(aftype.clone()) as c_int); - Array { handle: temp } - } -} - -#[allow(unused_mut)] -pub fn constant(cnst: f64, dims: Dim4, aftype: Aftype) -> Array { - unsafe { - let mut temp: i64 = 0; - af_constant(&mut temp as *mut c_longlong, - cnst as c_double, - dims.ndims() as c_uint, - dims.get().as_ptr() as * const c_longlong, - get_ffi_type(aftype.clone()) as c_int); - Array { handle: temp } - } -} - -#[allow(unused_mut)] -pub fn sin(input: &Array) -> Array { - unsafe { - let mut temp: i64 = 0; - af_sin(&mut temp as *mut c_longlong, input.get() as c_longlong); - Array { handle: temp } - } -} - -#[allow(unused_mut)] -pub fn fft(input: &Array, norm_factor: f64, odim0: i64) -> Array { - unsafe { - let mut temp: i64 = 0; - af_fft(&mut temp as *mut c_longlong, - input.get() as c_longlong, - norm_factor as c_double, - odim0 as c_longlong); - Array { handle: temp } - } -} - -#[allow(unused_mut)] -pub fn fft2(input: &Array, norm_factor: f64, odim0: i64, odim1: i64) -> Array { - unsafe { - let mut temp: i64 = 0; - af_fft2(&mut temp as *mut c_longlong, - input.get() as c_longlong, - norm_factor as c_double, - odim0 as c_longlong, - odim1 as c_longlong); - Array { handle: temp } - } -} - -#[allow(unused_mut)] -pub fn fft3(input: &Array, norm_factor: f64, odim0: i64, odim1: i64, odim2: i64) -> Array { - unsafe { - let mut temp: i64 = 0; - af_fft3(&mut temp as *mut c_longlong, - input.get() as c_longlong, - norm_factor as c_double, - odim0 as c_longlong, - odim1 as c_longlong, - odim2 as c_longlong); - Array { handle: temp } - } -} +pub use array::Array; +pub use array::{print}; +mod array; //pub use algorithm::{sum_nan, product_nan, sum_nan_all, product_nan_all}; pub use algorithm::{sum, product, min, max, all_true, any_true, count}; @@ -377,3 +9,59 @@ pub use algorithm::{all_true_all, any_true_all, count_all, imin, imax, imin_all, pub use algorithm::{accum, locate, diff1, diff2, sort, sort_index, sort_by_key}; pub use algorithm::{set_unique, set_union, set_intersect}; mod algorithm; + +pub use arith::{lt, gt, le, ge, eq, neq, and, or, minof, maxof}; +pub use arith::{abs, sign, round, trunc, floor, ceil, modulo}; +pub use arith::{sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh}; +pub use arith::{atan2, cplx2, arg, cplx, real, imag, conjg, hypot}; +pub use arith::{sqrt, log, log1p, log10, log2, pow2, exp, expm1, erf, erfc, root, pow}; +pub use arith::{cbrt, factorial, tgamma, lgamma, iszero, isinf, isnan}; +mod arith; + +pub use blas::{matmul, dot, transpose, transpose_inplace}; +mod blas; + +pub use data::{constant, range, iota}; +pub use data::{set_seed, get_seed, randu, randn}; +pub use data::{identity, diag_create, diag_extract, lower, upper}; +pub use data::{join, join_many, tile}; +pub use data::{reorder, shift, moddims, flat, flip}; +mod data; + +pub use device::{get_version, info, set_device}; +mod device; + +pub use defines::Aftype; +pub use defines::{InterpType, BorderType, MatchType, NormType}; +pub use defines::{Connectivity, ConvMode, ConvDomain, ColorSpace, MatProp}; +mod defines; + +pub use dim4::Dim4; +mod dim4; + +pub use image::{gaussian_kernel, load_image, save_image}; +pub use image::{resize, transform, rotate, translate, scale, skew}; +pub use image::{dilate, dilate3, erode, erode3, minfilt, maxfilt}; +pub use image::{gradient, histogram, hist_equal, regions}; +pub use image::{gray2rgb, rgb2gray, hsv2rgb, rgb2hsv, color_space}; +pub use image::{bilateral, mean_shift, medfilt, sobel}; +mod image; + +pub use signal::{approx1, approx2}; +pub use signal::{fft, fft2, fft3, ifft, ifft2, ifft3}; +pub use signal::{convolve1, convolve2, convolve3, convolve2_sep}; +pub use signal::{fft_convolve1, fft_convolve2, fft_convolve3}; +pub use signal::{fir, iir}; +mod signal; + +pub use statistics::{mean, stdev, median, var, cov, corrcoef}; +pub use statistics::{mean_weighted, var_weighted}; +pub use statistics::{var_all, mean_all, stdev_all, median_all}; +pub use statistics::{mean_all_weighted, var_all_weighted}; +mod statistics; + +mod util; + +pub use vision::Features; +pub use vision::{fast, orb, hamming_matcher, match_template}; +mod vision; diff --git a/src/signal/mod.rs b/src/signal/mod.rs new file mode 100644 index 000000000..26bdf2647 --- /dev/null +++ b/src/signal/mod.rs @@ -0,0 +1,197 @@ +extern crate libc; + +use array::Array; +use defines::InterpType; +use defines::ConvMode; +use defines::ConvDomain; +use self::libc::{uint8_t, c_int, c_float, c_double, c_longlong}; + +type MutAfArray = *mut self::libc::c_longlong; +type AfArray = self::libc::c_longlong; + +#[allow(dead_code)] +extern { + fn af_approx1(out: MutAfArray, inp: AfArray, pos: AfArray, + method: c_int, off_grid: c_float); + + fn af_approx2(out: MutAfArray, inp: AfArray, pos0: AfArray, pos1: AfArray, + method: c_int, off_grid: c_float); + + fn af_fft(out: MutAfArray, arr: AfArray, + nfac: c_double, odim0: c_longlong) -> c_int; + + fn af_fft2(out: MutAfArray, arr: AfArray, nfac: c_double, + odim0: c_longlong, odim1: c_longlong) -> c_int; + + fn af_fft3(out: MutAfArray, arr: AfArray, nfac: c_double, + odim0: c_longlong, odim1: c_longlong, odim2: c_longlong) -> c_int; + + fn af_ifft(out: MutAfArray, arr: AfArray, + nfac: c_double, odim0: c_longlong) -> c_int; + + fn af_ifft2(out: MutAfArray, arr: AfArray, nfac: c_double, + odim0: c_longlong, odim1: c_longlong) -> c_int; + + fn af_ifft3(out: MutAfArray, arr: AfArray, nfac: c_double, + odim0: c_longlong, odim1: c_longlong, odim2: c_longlong) -> c_int; + + fn af_convolve1(out: MutAfArray, s: AfArray, f: AfArray, m: uint8_t, d: uint8_t) -> c_int; + fn af_convolve2(out: MutAfArray, s: AfArray, f: AfArray, m: uint8_t, d: uint8_t) -> c_int; + fn af_convolve3(out: MutAfArray, s: AfArray, f: AfArray, m: uint8_t, d: uint8_t) -> c_int; + fn af_convolve2_sep(o: MutAfArray, c: AfArray, r: AfArray, s: AfArray, m: uint8_t) -> c_int; + fn af_fft_convolve1(out: MutAfArray, s: AfArray, f: AfArray, m: uint8_t) -> c_int; + fn af_fft_convolve2(out: MutAfArray, s: AfArray, f: AfArray, m: uint8_t) -> c_int; + fn af_fft_convolve3(out: MutAfArray, s: AfArray, f: AfArray, m: uint8_t) -> c_int; + fn af_fir(out: MutAfArray, b: AfArray, x: AfArray) -> c_int; + fn af_iir(out: MutAfArray, b: AfArray, a: AfArray, x: AfArray) -> c_int; +} + +#[allow(unused_mut)] +pub fn approx1(input: &Array, pos: &Array, method: InterpType, off_grid: f32) -> Array { + unsafe { + let mut temp: i64 = 0; + af_approx1(&mut temp as MutAfArray, + input.get() as AfArray, pos.get() as AfArray, + method as c_int, off_grid as c_float); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn approx2(input: &Array, pos0: &Array, pos1: &Array, + method: InterpType, off_grid: f32) -> Array { + unsafe { + let mut temp: i64 = 0; + af_approx2(&mut temp as MutAfArray, + input.get() as AfArray, pos0.get() as AfArray, pos1.get() as AfArray, + method as c_int, off_grid as c_float); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn fft(input: &Array, norm_factor: f64, odim0: i64) -> Array { + unsafe { + let mut temp: i64 = 0; + af_fft(&mut temp as MutAfArray, input.get() as AfArray, + norm_factor as c_double, odim0 as c_longlong); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn fft2(input: &Array, norm_factor: f64, odim0: i64, odim1: i64) -> Array { + unsafe { + let mut temp: i64 = 0; + af_fft2(&mut temp as MutAfArray, input.get() as AfArray, + norm_factor as c_double, odim0 as c_longlong, odim1 as c_longlong); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn fft3(input: &Array, norm_factor: f64, odim0: i64, odim1: i64, odim2: i64) -> Array { + unsafe { + let mut temp: i64 = 0; + af_fft3(&mut temp as MutAfArray, input.get() as AfArray, norm_factor as c_double, + odim0 as c_longlong, odim1 as c_longlong, odim2 as c_longlong); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn ifft(input: &Array, norm_factor: f64, odim0: i64) -> Array { + unsafe { + let mut temp: i64 = 0; + af_ifft(&mut temp as MutAfArray, input.get() as AfArray, + norm_factor as c_double, odim0 as c_longlong); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn ifft2(input: &Array, norm_factor: f64, odim0: i64, odim1: i64) -> Array { + unsafe { + let mut temp: i64 = 0; + af_ifft2(&mut temp as MutAfArray, input.get() as AfArray, + norm_factor as c_double, odim0 as c_longlong, odim1 as c_longlong); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn ifft3(input: &Array, norm_factor: f64, odim0: i64, odim1: i64, odim2: i64) -> Array { + unsafe { + let mut temp: i64 = 0; + af_ifft3(&mut temp as MutAfArray, input.get() as AfArray, norm_factor as c_double, + odim0 as c_longlong, odim1 as c_longlong, odim2 as c_longlong); + Array::from(temp) + } +} + +macro_rules! conv_func_def { + ($fn_name:ident, $ffi_name: ident) => ( + #[allow(unused_mut)] + pub fn $fn_name(signal: &Array, filter: &Array, + mode: ConvMode, domain: ConvDomain) -> Array { + unsafe { + let mut temp: i64 = 0; + $ffi_name(&mut temp as MutAfArray, + signal.get() as AfArray, filter.get() as AfArray, + mode as uint8_t, domain as uint8_t); + Array::from(temp) + } + } + ) +} + +conv_func_def!(convolve1, af_convolve1); +conv_func_def!(convolve2, af_convolve2); +conv_func_def!(convolve3, af_convolve3); + +#[allow(unused_mut)] +pub fn convolve2_sep(cfilt: &Array, rfilt: &Array, signal: &Array, mode: ConvMode) -> Array { + unsafe { + let mut temp: i64 = 0; + af_convolve2_sep(&mut temp as MutAfArray, + cfilt.get() as AfArray, rfilt.get() as AfArray, + signal.get() as AfArray, mode as uint8_t); + Array::from(temp) + } +} + +macro_rules! fft_conv_func_def { + ($fn_name:ident, $ffi_name: ident) => ( + #[allow(unused_mut)] + pub fn $fn_name(signal: &Array, filter: &Array, mode: ConvMode) -> Array { + unsafe { + let mut temp: i64 = 0; + $ffi_name(&mut temp as MutAfArray, signal.get() as AfArray, + filter.get() as AfArray, mode as uint8_t); + Array::from(temp) + } + } + ) +} + +fft_conv_func_def!(fft_convolve1, af_fft_convolve1); +fft_conv_func_def!(fft_convolve2, af_fft_convolve2); +fft_conv_func_def!(fft_convolve3, af_fft_convolve3); + +#[allow(unused_mut)] +pub fn fir(b: &Array, x: &Array) -> Array { + unsafe { + let mut temp: i64 = 0; + af_fir(&mut temp as MutAfArray, b.get() as AfArray, x.get() as AfArray); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn iir(b: &Array, a: &Array, x: &Array) -> Array { + unsafe { + let mut temp: i64 = 0; + af_iir(&mut temp as MutAfArray, b.get() as AfArray, a.get() as AfArray, x.get() as AfArray); + Array::from(temp) + } +} diff --git a/src/statistics/mod.rs b/src/statistics/mod.rs new file mode 100644 index 000000000..2d68bdf97 --- /dev/null +++ b/src/statistics/mod.rs @@ -0,0 +1,143 @@ +extern crate libc; + +use array::Array; +use self::libc::{c_int}; + +type MutAfArray = *mut self::libc::c_longlong; +type MutDouble = *mut self::libc::c_double; +type AfArray = self::libc::c_longlong; +type DimT = self::libc::c_longlong; + +#[allow(dead_code)] +extern { + fn af_mean(out: MutAfArray, arr: AfArray, dim: DimT) -> c_int; + fn af_stdev(out: MutAfArray, arr: AfArray, dim: DimT) -> c_int; + fn af_median(out: MutAfArray, arr: AfArray, dim: DimT) -> c_int; + + fn af_mean_weighted(out: MutAfArray, arr: AfArray, wts: AfArray, dim: DimT) -> c_int; + fn af_var_weighted(out: MutAfArray, arr: AfArray, wts: AfArray, dim: DimT) -> c_int; + + fn af_var(out: MutAfArray, arr: AfArray, isbiased: c_int, dim: DimT) -> c_int; + fn af_cov(out: MutAfArray, X: AfArray, Y: AfArray, isbiased: c_int) -> c_int; + fn af_var_all(real: MutDouble, imag: MutDouble, arr: AfArray, isbiased: c_int) -> c_int; + + fn af_mean_all(real: MutDouble, imag: MutDouble, arr: AfArray) -> c_int; + fn af_stdev_all(real: MutDouble, imag: MutDouble, arr: AfArray) -> c_int; + fn af_median_all(real: MutDouble, imag: MutDouble, arr: AfArray) -> c_int; + + fn af_mean_all_weighted(real: MutDouble, imag: MutDouble, arr: AfArray, wts: AfArray) -> c_int; + fn af_var_all_weighted(real: MutDouble, imag: MutDouble, arr: AfArray, wts: AfArray) -> c_int; + + fn af_corrcoef(real: MutDouble, imag: MutDouble, X: AfArray, Y: AfArray) -> c_int; +} + +macro_rules! stat_func_def { + ($fn_name: ident, $ffi_fn: ident) => ( + #[allow(unused_mut)] + pub fn $fn_name(input: &Array, dim: i64) -> Array { + unsafe { + let mut temp: i64 = 0; + $ffi_fn(&mut temp as MutAfArray, input.get() as AfArray, dim as DimT); + Array::from(temp) + } + } + ) +} + +stat_func_def!(mean, af_mean); +stat_func_def!(stdev, af_stdev); +stat_func_def!(median, af_median); + +macro_rules! stat_wtd_func_def { + ($fn_name: ident, $ffi_fn: ident) => ( + #[allow(unused_mut)] + pub fn $fn_name(input: &Array, weights: &Array, dim: i64) -> Array { + unsafe { + let mut temp: i64 = 0; + $ffi_fn(&mut temp as MutAfArray, input.get() as AfArray, + weights.get() as AfArray, dim as DimT); + Array::from(temp) + } + } + ) +} + +stat_wtd_func_def!(mean_weighted, af_mean_weighted); +stat_wtd_func_def!(var_weighted, af_var_weighted); + +#[allow(unused_mut)] +pub fn var(arr: &Array, isbiased: bool, dim: i64) -> Array { + unsafe { + let mut temp: i64 = 0; + af_var(&mut temp as MutAfArray, arr.get() as AfArray, + isbiased as c_int, dim as DimT); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn cov(x: &Array, y: &Array, isbiased: bool) -> Array { + unsafe { + let mut temp: i64 = 0; + af_cov(&mut temp as MutAfArray, x.get() as AfArray, y.get() as AfArray, isbiased as c_int); + Array::from(temp) + } +} + +#[allow(unused_mut)] +pub fn var_all(input: &Array, isbiased: bool) -> (f64, f64) { + unsafe { + let mut real: f64 = 0.0; + let mut imag: f64 = 0.0; + af_var_all(&mut real as MutDouble, &mut imag as MutDouble, + input.get() as AfArray, isbiased as c_int); + (real, imag) + } +} + +macro_rules! stat_all_func_def { + ($fn_name: ident, $ffi_fn: ident) => ( + #[allow(unused_mut)] + pub fn $fn_name(input: &Array) -> (f64, f64) { + unsafe { + let mut real: f64 = 0.0; + let mut imag: f64 = 0.0; + $ffi_fn(&mut real as MutDouble, &mut imag as MutDouble, input.get() as AfArray); + (real, imag) + } + } + ) +} + +stat_all_func_def!(mean_all, af_mean_all); +stat_all_func_def!(stdev_all, af_stdev_all); +stat_all_func_def!(median_all, af_median_all); + +macro_rules! stat_wtd_all_func_def { + ($fn_name: ident, $ffi_fn: ident) => ( + #[allow(unused_mut)] + pub fn $fn_name(input: &Array, weights: &Array) -> (f64, f64) { + unsafe { + let mut real: f64 = 0.0; + let mut imag: f64 = 0.0; + $ffi_fn(&mut real as MutDouble, &mut imag as MutDouble, + input.get() as AfArray, weights.get() as AfArray); + (real, imag) + } + } + ) +} + +stat_wtd_all_func_def!(mean_all_weighted, af_mean_all_weighted); +stat_wtd_all_func_def!(var_all_weighted, af_var_all_weighted); + +#[allow(unused_mut)] +pub fn corrcoef(x: &Array, y: &Array) -> (f64, f64) { + unsafe { + let mut real: f64 = 0.0; + let mut imag: f64 = 0.0; + af_corrcoef(&mut real as MutDouble, &mut imag as MutDouble, + x.get() as AfArray, y.get() as AfArray); + (real, imag) + } +} diff --git a/src/util.rs b/src/util.rs new file mode 100644 index 000000000..3ac30d6a9 --- /dev/null +++ b/src/util.rs @@ -0,0 +1,58 @@ +use defines::Aftype; +use defines::InterpType; +use defines::ConvMode; +use defines::ConvDomain; +use defines::MatProp; +use defines::MatchType; +use std::mem; + +impl From for Aftype { + fn from(t: u8) -> Aftype { + assert!(Aftype::F32 as u8 <= t && t <= Aftype::U64 as u8); + unsafe { mem::transmute(t) } + } +} + +impl From for InterpType { + fn from(t: u8) -> InterpType { + assert!(InterpType::NEAREST as u8 <= t && t <= InterpType::CUBIC as u8); + unsafe { mem::transmute(t) } + } +} + +impl From for ConvMode { + fn from(t: u8) -> ConvMode { + assert!(ConvMode::DEFAULT as u8 <= t && t <= ConvMode::EXPAND as u8); + unsafe { mem::transmute(t) } + } +} + +impl From for ConvDomain { + fn from(t: u8) -> ConvDomain { + assert!(ConvDomain::AUTO as u8 <= t && t <= ConvDomain::FREQUENCY as u8); + unsafe { mem::transmute(t) } + } +} + +impl From for MatchType { + fn from(t: u8) -> MatchType { + assert!(MatchType::SAD as u8 <= t && t <= MatchType::SHD as u8); + unsafe { mem::transmute(t) } + } +} + +pub fn to_u32(t: MatProp) -> u32 { + match t { + MatProp::NONE => 0, + MatProp::TRANS => 1, + MatProp::CTRANS => 2, + MatProp::UPPER => 32, + MatProp::LOWER => 64, + MatProp::DIAGUNIT => 128, + MatProp::SYM => 512, + MatProp::POSDEF => 1024, + MatProp::ORTHOG => 2048, + MatProp::TRIDIAG => 4096, + MatProp::BLOCKDIAG => 8192, + } +} diff --git a/src/vision/mod.rs b/src/vision/mod.rs new file mode 100644 index 000000000..dc2bb6205 --- /dev/null +++ b/src/vision/mod.rs @@ -0,0 +1,152 @@ +extern crate libc; + +use array::Array; +use defines::MatchType; +use self::libc::{c_void, uint8_t, c_uint, c_int, c_float, c_longlong}; + +type MutAfArray = *mut self::libc::c_longlong; +type AfArray = self::libc::c_longlong; +type DimT = self::libc::c_longlong; +type MutFeat = *mut *mut self::libc::c_void; +type Feat = *const self::libc::c_void; + +#[allow(dead_code)] +extern { + fn af_create_features(feat: MutFeat, num: DimT); + fn af_retain_features(feat: MutFeat, feat: Feat); + fn af_get_features_num(num: *mut DimT, feat: Feat); + fn af_get_features_xpos(out: MutAfArray, feat: Feat); + fn af_get_features_ypos(out: MutAfArray, feat: Feat); + fn af_get_features_score(out: MutAfArray, feat: Feat); + fn af_get_features_orientation(out: MutAfArray, feat: Feat); + fn af_get_features_size(out: MutAfArray, feat: Feat); + fn af_release_features(feat: *mut c_void); + + fn af_fast(out: MutFeat, input: AfArray, thr: c_float, arc_len: c_uint, non_max: c_int, + feature_ratio: c_float, edge: c_uint); + + fn af_orb(out: MutFeat, desc: MutAfArray, arr: AfArray, fast_thr: c_float, max_feat: c_uint, + scl_fctr: c_float, levels: c_uint, blur_img: c_int); + + fn af_hamming_matcher(idx: MutAfArray, dist: MutAfArray, + query: AfArray, train: AfArray, + dist_dim: DimT, n_dist: c_uint); + + fn af_match_template(out: MutAfArray, search_img: AfArray, template_img: AfArray, + mtype: uint8_t); +} + +pub struct Features { + feat: i64, +} + +macro_rules! feat_func_def { + ($fn_name: ident, $ffi_name: ident) => ( + pub fn $fn_name(&self) -> Array { + unsafe { + let mut temp: i64 = 0; + $ffi_name(&mut temp as MutAfArray, self.feat as Feat); + Array::from(temp) + } + } + ) +} + +impl Features { + #[allow(unused_mut)] + pub fn new(n: u64) -> Features { + unsafe { + let mut temp: i64 = 0; + af_create_features(&mut temp as *mut c_longlong as MutFeat, + n as DimT); + Features {feat: temp} + } + } + + pub fn num_features(&self) -> i64 { + unsafe { + let mut temp: i64 = 0; + af_get_features_num(&mut temp as *mut DimT, + self.feat as *const c_longlong as Feat); + temp + } + } + + feat_func_def!(xpos, af_get_features_xpos); + feat_func_def!(ypos, af_get_features_ypos); + feat_func_def!(score, af_get_features_score); + feat_func_def!(orientation, af_get_features_orientation); + feat_func_def!(size, af_get_features_size); + + pub fn get(&self) -> i64 { + self.feat + } +} + +impl Clone for Features { + fn clone(&self) -> Features { + unsafe { + let mut temp: i64 = 0; + af_retain_features(&mut temp as *mut c_longlong as MutFeat, + self.feat as *const c_longlong as Feat); + Features {feat: temp} + } + } +} + +impl Drop for Features { + fn drop(&mut self) { + unsafe { + af_release_features(self.feat as *mut c_longlong as *mut c_void); + } + } +} + +#[allow(unused_mut)] +pub fn fast(input: &Array, thr: f32, arc_len: u32, + non_max: bool, feat_ratio: f32, edge: u32) -> Features { + unsafe { + let mut temp: i64 = 0; + af_fast(&mut temp as *mut c_longlong as MutFeat, + input.get() as AfArray, thr as c_float, arc_len as c_uint, + non_max as c_int, feat_ratio as c_float, edge as c_uint); + Features {feat: temp} + } +} + +#[allow(unused_mut)] +pub fn orb(input: &Array, fast_thr: f32, max_feat: u32, + scl_fctr: f32, levels: u32, blur_img: bool) -> (Features, Array) { + unsafe { + let mut f: i64 = 0; + let mut d: i64 = 0; + af_orb(&mut f as *mut c_longlong as MutFeat, &mut d as MutAfArray, + input.get() as AfArray, fast_thr as c_float, + max_feat as c_uint, scl_fctr as c_float, levels as c_uint, blur_img as c_int); + (Features {feat: f}, Array::from(d)) + } +} + +#[allow(unused_mut)] +pub fn hamming_matcher(query: &Array, train: &Array, + dist_dims: i64, n_dist: u32) -> (Array, Array) { + unsafe { + let mut idx: i64 = 0; + let mut dist:i64 = 0; + af_hamming_matcher(&mut idx as MutAfArray, &mut dist as MutAfArray, + query.get() as AfArray, train.get() as AfArray, + dist_dims as DimT, n_dist as c_uint); + (Array::from(idx), Array::from(dist)) + } +} + +#[allow(unused_mut)] +pub fn match_template(search_img: &Array, template_img: &Array, mtype: MatchType) -> Array { + unsafe { + let mut temp: i64 = 0; + af_match_template(&mut temp as MutAfArray, + search_img.get() as AfArray, template_img.get() as AfArray, + mtype as uint8_t); + Array::from(temp) + } +}