From 5f9e5da9e955d40f9d6f9d726b407181b450b4b8 Mon Sep 17 00:00:00 2001 From: pradeep Date: Mon, 14 Dec 2015 21:06:14 -0500 Subject: [PATCH 01/37] Removed obselete sections from README --- README.md | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/README.md b/README.md index 381f883e4..8ed419db1 100644 --- a/README.md +++ b/README.md @@ -80,20 +80,6 @@ Create a 5-by-3 matrix of random floats on the GPU ... ``` -## Issues - -You might see something along the lines of : - -```bash -dyld: Library not loaded: @rpath/libafopencl.3.dylib -``` - -You need to add the location of libaf.{dylib, so, dll} to your LD_LIBRARY_PATH. - -## Note - -This is a work in progress and is not intended for production use. - ## Acknowledgements The ArrayFire library is written by developers at [ArrayFire](http://arrayfire.com) LLC From 86fc951323997e69785734199a2bdd269a95ea1c Mon Sep 17 00:00:00 2001 From: Pradeep Garigipati Date: Mon, 28 Dec 2015 15:09:01 -0500 Subject: [PATCH 02/37] added gitter chat badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8ed419db1..fa0bdf883 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Arrayfire Rust Bindings +# Arrayfire Rust Bindings [![Join the chat at https://gitter.im/arrayfire/arrayfire-rust](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/arrayfire/arrayfire-rust?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [ArrayFire](https://github.com/arrayfire/arrayfire) is a high performance library for parallel computing with an easy-to-use API. It enables users to write scientific computing code that is portable across CUDA, OpenCL and CPU devices. This project provides Rust bindings for the ArrayFire library. The wrapper is currently compliant with ArrayFire 3.2 API. If you find any bugs, please report them [here](https://github.com/arrayfire/arrayfire-rust/issues). From 80651c9ae2c5b442ae5fc8b0a56e44c14c48a7bf Mon Sep 17 00:00:00 2001 From: Theodore DeRego Date: Wed, 24 Feb 2016 11:05:20 -1000 Subject: [PATCH 03/37] Make Seq generic and make use of generic Seq in helloworld example --- examples/helloworld.rs | 4 ++-- src/index.rs | 52 +++++++++++++++++++++++++++++++----------- src/lib.rs | 2 ++ src/seq.rs | 34 +++++++++++++-------------- 4 files changed, 60 insertions(+), 32 deletions(-) diff --git a/examples/helloworld.rs b/examples/helloworld.rs index 6ed726019..356d3986c 100644 --- a/examples/helloworld.rs +++ b/examples/helloworld.rs @@ -42,12 +42,12 @@ fn main() { println!("a + b"); print(&test); // Index array using sequences - let seqs = &[Seq::new(1.0, 3.0, 1.0), Seq::default()]; + let seqs = &[Seq::new(1u32, 3, 1), Seq::default()]; let sub = index(&a, seqs).unwrap(); println!("a(seq(1,3,1), span)"); print(&sub); //Index array using array and sequence - let seq4gen = Seq::new(0.0, 2.0, 1.0); + let seq4gen = Seq::new(0u32, 2, 1); let mut idxrs = match Indexer::new() { Ok(v) => v, diff --git a/src/index.rs b/src/index.rs index c782b32a2..2aca11327 100644 --- a/src/index.rs +++ b/src/index.rs @@ -3,7 +3,7 @@ extern crate libc; use array::Array; use defines::AfError; use seq::Seq; -use self::libc::{c_int, c_uint, c_longlong}; +use self::libc::{c_double, c_int, c_uint}; type MutAfIndex = *mut self::libc::c_longlong; type MutAfArray = *mut self::libc::c_longlong; @@ -15,12 +15,12 @@ type IndexT = self::libc::c_longlong; extern { fn af_create_indexers(indexers: MutAfIndex) -> c_int; fn af_set_array_indexer(indexer: MutAfIndex, idx: AfArray, dim: DimT) -> c_int; - fn af_set_seq_indexer(indexer: MutAfIndex, idx: *const Seq, dim: DimT, is_batch: c_int) -> c_int; + fn af_set_seq_indexer(indexer: MutAfIndex, idx: *const SeqInternal, dim: DimT, is_batch: c_int) -> c_int; fn af_release_indexers(indexers: MutAfIndex) -> c_int; - fn af_index(out: MutAfArray, input: AfArray, ndims: c_uint, index: *const Seq) -> c_int; + fn af_index(out: MutAfArray, input: AfArray, ndims: c_uint, index: *const SeqInternal) -> c_int; fn af_lookup(out: MutAfArray, arr: AfArray, indices: AfArray, dim: c_uint) -> c_int; - fn af_assign_seq(out: MutAfArray, lhs: AfArray, ndims: c_uint, indices: *const Seq, rhs: AfArray) -> c_int; + fn af_assign_seq(out: MutAfArray, lhs: AfArray, ndims: c_uint, indices: *const SeqInternal, rhs: AfArray) -> c_int; fn af_index_gen(out: MutAfArray, input: AfArray, ndims: DimT, indices: *const IndexT) -> c_int; fn af_assign_gen(out: MutAfArray, lhs: AfArray, ndims: DimT, indices: *const IndexT, rhs: AfArray) -> c_int; } @@ -62,11 +62,12 @@ impl Indexable for Array { /// /// This is used in functions [index_gen](./fn.index_gen.html) and /// [assign_gen](./fn.assign_gen.html) -impl Indexable for Seq { +impl Indexable for Seq where c_double: From { fn set(&self, idxr: &Indexer, dim: u32, is_batch: Option) -> Result<(), AfError> { unsafe { - let err_val = af_set_seq_indexer(idxr.clone().get() as MutAfIndex, self as *const Seq, - dim as DimT, is_batch.unwrap() as c_int); + let err_val = af_set_seq_indexer(idxr.clone().get() as MutAfIndex, + &SeqInternal::from_seq(self) as *const SeqInternal, + dim as DimT, is_batch.unwrap() as c_int); match err_val { 0 => Ok(()), _ => Err(AfError::from(err_val)), @@ -130,12 +131,16 @@ impl Drop for Indexer { /// println!("a(seq(1, 3, 1), span)"); /// print(&sub); /// ``` -pub fn index(input: &Array, seqs: &[Seq]) -> Result { +pub fn index(input: &Array, seqs: &[Seq]) -> Result + where c_double: From +{ unsafe { let mut temp: i64 = 0; + // TODO: allocating a whole new array on the heap just for this is BAD + let seqs: Vec = seqs.iter().map(|s| SeqInternal::from_seq(s)).collect(); let err_val = af_index(&mut temp as MutAfArray , input.get() as AfArray, seqs.len() as u32 - , seqs.as_ptr() as *const Seq); + , seqs.as_ptr() as *const SeqInternal); match err_val { 0 => Ok(Array::from(temp)), _ => Err(AfError::from(err_val)), @@ -155,8 +160,8 @@ pub fn index(input: &Array, seqs: &[Seq]) -> Result { /// ``` #[allow(dead_code)] pub fn row(input: &Array, row_num: u64) -> Result { - index(input, &[Seq::new(row_num as f64, row_num as f64, 1.0) - , Seq::default()]) + index(input, &[Seq::new(row_num as f64, row_num as f64, 1.0), + Seq::default()]) } #[allow(dead_code)] @@ -300,11 +305,15 @@ pub fn lookup(input: &Array, indices: &Array, seq_dim: i32) -> Result Result { +pub fn assign_seq(lhs: &Array, seqs: &[Seq], rhs: &Array) -> Result + where c_double: From +{ unsafe{ let mut temp: i64 = 0; + // TODO: allocating a whole new array on the heap just for this is BAD + let seqs: Vec = seqs.iter().map(|s| SeqInternal::from_seq(s)).collect(); let err_val = af_assign_seq(&mut temp as MutAfArray, lhs.get() as AfArray, - seqs.len() as c_uint, seqs.as_ptr() as *const Seq, + seqs.len() as c_uint, seqs.as_ptr() as *const SeqInternal, rhs.get() as AfArray); match err_val { 0 => Ok(Array::from(temp)), @@ -402,3 +411,20 @@ pub fn assign_gen(lhs: &Array, indices: &Indexer, rhs: &Array) -> Result(s: &Seq) -> Self where c_double: From { + SeqInternal { + begin: From::from(s.begin()), + end: From::from(s.end()), + step: From::from(s.step()), + } + } +} diff --git a/src/lib.rs b/src/lib.rs index a09af0e1c..4a87d996f 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,5 @@ +#![feature(zero_one)] + #![doc(html_logo_url = "http://www.arrayfire.com/logos/arrayfire_logo_symbol.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://arrayfire.com/docs/rust")] diff --git a/src/seq.rs b/src/seq.rs index ae0a43b96..c09aa0245 100644 --- a/src/seq.rs +++ b/src/seq.rs @@ -2,49 +2,49 @@ extern crate libc; use std::fmt; use std::default::Default; -use self::libc::{c_double}; +use std::num::{One, Zero}; /// Sequences are used for indexing Arrays #[derive(Copy, Clone)] #[repr(C)] -pub struct Seq { - begin: c_double, - end: c_double, - step: c_double, +pub struct Seq { + begin: T, + end: T, + step: T, } /// Default `Seq` spans all the elements along a dimension -impl Default for Seq { - fn default() -> Seq { - Seq { begin: 1.0, end: 1.0, step: 0.0, } +impl Default for Seq { + fn default() -> Self { + Seq { begin: One::one(), end: One::one(), step: Zero::zero() } } } /// Enables use of `Seq` with `{}` format in print statements -impl fmt::Display for Seq { +impl fmt::Display for Seq { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "[begin: {}, end: {}, step: {}]", self.begin, self.end, self.step) } } -impl Seq { +impl Seq { /// Create a `Seq` that goes from `begin` to `end` at a step size of `step` - pub fn new(begin: f64, end: f64, step: f64) -> Seq { + pub fn new(begin: T, end: T, step: T) -> Self { Seq { begin: begin, end: end, step: step, } } /// Get begin index of Seq - pub fn begin(&self) -> f64 { - self.begin as f64 + pub fn begin(&self) -> T { + self.begin } /// Get begin index of Seq - pub fn end(&self) -> f64 { - self.end as f64 + pub fn end(&self) -> T { + self.end } /// Get step size of Seq - pub fn step(&self) -> f64 { - self.step as f64 + pub fn step(&self) -> T { + self.step } } From ab618ad20f4ee9bbb21865891cbe497a0f312eed Mon Sep 17 00:00:00 2001 From: Theodore DeRego Date: Thu, 25 Feb 2016 10:13:25 -1000 Subject: [PATCH 04/37] Made our own One+Zero traits so we can use stable rust --- src/lib.rs | 3 +-- src/num.rs | 33 +++++++++++++++++++++++++++++++++ src/seq.rs | 3 ++- 3 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 src/num.rs diff --git a/src/lib.rs b/src/lib.rs index 4a87d996f..09d7a5b1e 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,3 @@ -#![feature(zero_one)] - #![doc(html_logo_url = "http://www.arrayfire.com/logos/arrayfire_logo_symbol.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://arrayfire.com/docs/rust")] @@ -73,6 +71,7 @@ mod image; pub use lapack::{svd, lu, qr, cholesky, solve, solve_lu, inverse, det, rank, norm}; pub use lapack::{svd_inplace, lu_inplace, qr_inplace, cholesky_inplace}; mod lapack; +mod num; pub use signal::{approx1, approx2}; pub use signal::{fft, fft2, fft3, ifft, ifft2, ifft3}; diff --git a/src/num.rs b/src/num.rs new file mode 100644 index 000000000..4214d9d5e --- /dev/null +++ b/src/num.rs @@ -0,0 +1,33 @@ +pub trait Zero { + fn zero() -> Self; +} + +pub trait One { + fn one() -> Self; +} + +impl Zero for u8 { fn zero() -> Self { 0 } } +impl Zero for u16 { fn zero() -> Self { 0 } } +impl Zero for u32 { fn zero() -> Self { 0 } } +impl Zero for u64 { fn zero() -> Self { 0 } } +impl Zero for usize { fn zero() -> Self { 0 } } +impl Zero for i8 { fn zero() -> Self { 0 } } +impl Zero for i16 { fn zero() -> Self { 0 } } +impl Zero for i32 { fn zero() -> Self { 0 } } +impl Zero for i64 { fn zero() -> Self { 0 } } +impl Zero for isize { fn zero() -> Self { 0 } } +impl Zero for f32 { fn zero() -> Self { 0.0 } } +impl Zero for f64 { fn zero() -> Self { 0.0 } } + +impl One for u8 { fn one() -> Self { 1 } } +impl One for u16 { fn one() -> Self { 1 } } +impl One for u32 { fn one() -> Self { 1 } } +impl One for u64 { fn one() -> Self { 1 } } +impl One for usize { fn one() -> Self { 1 } } +impl One for i8 { fn one() -> Self { 1 } } +impl One for i16 { fn one() -> Self { 1 } } +impl One for i32 { fn one() -> Self { 1 } } +impl One for i64 { fn one() -> Self { 1 } } +impl One for isize { fn one() -> Self { 1 } } +impl One for f32 { fn one() -> Self { 1.0 } } +impl One for f64 { fn one() -> Self { 1.0 } } diff --git a/src/seq.rs b/src/seq.rs index c09aa0245..a56410362 100644 --- a/src/seq.rs +++ b/src/seq.rs @@ -2,7 +2,8 @@ extern crate libc; use std::fmt; use std::default::Default; -use std::num::{One, Zero}; + +use num::{One, Zero}; /// Sequences are used for indexing Arrays #[derive(Copy, Clone)] From 70fcd0f752afe03149a8980adc88a3b834d70df5 Mon Sep 17 00:00:00 2001 From: Theodore DeRego Date: Thu, 25 Feb 2016 14:44:36 -1000 Subject: [PATCH 05/37] Macro-ify Zero and One trait impls --- src/num.rs | 61 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/src/num.rs b/src/num.rs index 4214d9d5e..d5858d486 100644 --- a/src/num.rs +++ b/src/num.rs @@ -6,28 +6,41 @@ pub trait One { fn one() -> Self; } -impl Zero for u8 { fn zero() -> Self { 0 } } -impl Zero for u16 { fn zero() -> Self { 0 } } -impl Zero for u32 { fn zero() -> Self { 0 } } -impl Zero for u64 { fn zero() -> Self { 0 } } -impl Zero for usize { fn zero() -> Self { 0 } } -impl Zero for i8 { fn zero() -> Self { 0 } } -impl Zero for i16 { fn zero() -> Self { 0 } } -impl Zero for i32 { fn zero() -> Self { 0 } } -impl Zero for i64 { fn zero() -> Self { 0 } } -impl Zero for isize { fn zero() -> Self { 0 } } -impl Zero for f32 { fn zero() -> Self { 0.0 } } -impl Zero for f64 { fn zero() -> Self { 0.0 } } +macro_rules! zero_impl { + ( $t:ident, $z:expr ) => ( + impl Zero for $t { fn zero() -> Self { $z } } + ) +} + +zero_impl!(u8, 0); +zero_impl!(u16, 0); +zero_impl!(u32, 0); +zero_impl!(u64, 0); +zero_impl!(usize, 0); +zero_impl!(i8, 0); +zero_impl!(i16, 0); +zero_impl!(i32, 0); +zero_impl!(i64, 0); +zero_impl!(isize, 0); +zero_impl!(f32, 0.0); +zero_impl!(f64, 0.0); + + +macro_rules! one_impl { + ( $t:ident, $o:expr ) => ( + impl One for $t { fn one() -> Self { $o } } + ) +} -impl One for u8 { fn one() -> Self { 1 } } -impl One for u16 { fn one() -> Self { 1 } } -impl One for u32 { fn one() -> Self { 1 } } -impl One for u64 { fn one() -> Self { 1 } } -impl One for usize { fn one() -> Self { 1 } } -impl One for i8 { fn one() -> Self { 1 } } -impl One for i16 { fn one() -> Self { 1 } } -impl One for i32 { fn one() -> Self { 1 } } -impl One for i64 { fn one() -> Self { 1 } } -impl One for isize { fn one() -> Self { 1 } } -impl One for f32 { fn one() -> Self { 1.0 } } -impl One for f64 { fn one() -> Self { 1.0 } } +one_impl!(u8, 1); +one_impl!(u16, 1); +one_impl!(u32, 1); +one_impl!(u64, 1); +one_impl!(usize, 1); +one_impl!(i8, 1); +one_impl!(i16, 1); +one_impl!(i32, 1); +one_impl!(i64, 1); +one_impl!(isize, 1); +one_impl!(f32, 1.0); +one_impl!(f64, 1.0); From b088f07725fdfa86b962cacdf25c9da425f094a4 Mon Sep 17 00:00:00 2001 From: pradeep Date: Fri, 11 Mar 2016 15:49:47 +0530 Subject: [PATCH 06/37] API Catchup to 3.3.0 version More detailed information on the new release can be found at the following URL https://github.com/arrayfire/arrayfire/releases/tag/v3.3.0 --- Cargo.toml | 2 +- arrayfire | 2 +- examples/unified.rs | 12 ++-- src/array.rs | 111 +++++++++++++++++++++++++++++++++--- src/backend.rs | 23 +++++++- src/defines.rs | 33 ++++++++--- src/device/mod.rs | 134 +++++++++++++++++++++++++++++++++++++++++++- src/graphics.rs | 63 ++++++++++++++++++++- src/image/mod.rs | 49 ++++++++++++++++ src/lapack/mod.rs | 18 ++++++ src/lib.rs | 10 ++-- 11 files changed, 423 insertions(+), 34 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 93fd8e562..bbd9a1a14 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "arrayfire" description = "ArrayFire is a high performance software library for parallel computing with an easy-to-use API. Its array based function set makes parallel programming simple. ArrayFire's multiple backends (CUDA, OpenCL and native CPU) make it platform independent and highly portable. A few lines of code in ArrayFire can replace dozens of lines of parallel computing code, saving you valuable time and lowering development costs. This crate provides Rust bindings for ArrayFire library." -version = "3.2.0" +version = "3.3.0" documentation = "http://arrayfire.github.io/arrayfire-rust/arrayfire/index.html" homepage = "https://github.com/arrayfire/arrayfire" repository = "https://github.com/arrayfire/arrayfire-rust" diff --git a/arrayfire b/arrayfire index f263db079..5842ed251 160000 --- a/arrayfire +++ b/arrayfire @@ -1 +1 @@ -Subproject commit f263db079443f7818a73ee94e237dd53ef017d01 +Subproject commit 5842ed25195848653148fa9b3a8270255d83f5b8 diff --git a/examples/unified.rs b/examples/unified.rs index 713a6f068..d865e3401 100644 --- a/examples/unified.rs +++ b/examples/unified.rs @@ -24,9 +24,9 @@ fn main() { println!("There are {:?} available backends", get_backend_count().unwrap()); let available = get_available_backends().unwrap(); - if available.contains(&Backend::AF_BACKEND_CPU){ + if available.contains(&Backend::CPU){ println!("Evaluating CPU Backend..."); - let err = set_backend(Backend::AF_BACKEND_CPU); + let err = set_backend(Backend::CPU); println!("There are {} CPU compute devices", device_count().unwrap()); match err { Ok(_) => test_backend(), @@ -34,9 +34,9 @@ fn main() { }; } - if available.contains(&Backend::AF_BACKEND_CUDA){ + if available.contains(&Backend::CUDA){ println!("Evaluating CUDA Backend..."); - let err = set_backend(Backend::AF_BACKEND_CUDA); + let err = set_backend(Backend::CUDA); println!("There are {} CUDA compute devices", device_count().unwrap()); match err { Ok(_) => test_backend(), @@ -44,9 +44,9 @@ fn main() { }; } - if available.contains(&Backend::AF_BACKEND_OPENCL){ + if available.contains(&Backend::OPENCL){ println!("Evaluating OpenCL Backend..."); - let err = set_backend(Backend::AF_BACKEND_OPENCL); + let err = set_backend(Backend::OPENCL); println!("There are {} OpenCL compute devices", device_count().unwrap()); match err { Ok(_) => test_backend(), diff --git a/src/array.rs b/src/array.rs index 77d1a1294..45914b1bf 100644 --- a/src/array.rs +++ b/src/array.rs @@ -72,6 +72,21 @@ extern { fn af_cast(out: MutAfArray, arr: AfArray, aftype: uint8_t) -> c_int; fn af_get_backend_id(backend: *mut c_int, input: AfArray) -> c_int; + + fn af_get_device_id(device: *mut c_int, input: AfArray) -> c_int; + + fn af_create_strided_array(arr: MutAfArray, data: *const c_void, offset: DimT, + ndims: c_uint, dims: *const DimT, strides: *const DimT, + aftype: uint8_t) -> c_int; + + fn af_get_strides(s0: *mut DimT, s1: *mut DimT, s2: *mut DimT, s3: *mut DimT, + arr: AfArray) -> c_int; + + fn af_get_offset(offset: *mut DimT, arr: AfArray) -> c_int; + + fn af_is_linear(result: *mut c_int, arr: AfArray) -> c_int; + + fn af_is_owner(result: *mut c_int, arr: AfArray) -> c_int; } /// A multidimensional data container @@ -122,21 +137,68 @@ impl Array { } } + /// Constructs a new Array object from strided data + /// + /// This data can possiblly offseted using an additiona `offset` parameter. + /// + /// # Examples + /// + /// ``` + /// let values: &[f32] = &[1.0, 2.0, 3.0]; + /// let indices = Array::new(Dim4::new(&[3, 1, 1, 1]), values, Aftype::F32).unwrap(); + /// ``` + #[allow(unused_mut)] + pub fn new_strided(slice: &[T], offset: i64, + dims: Dim4, strides: Dim4, + aftype: Aftype) -> Result { + unsafe { + let mut temp: i64 = 0; + let err_val = af_create_strided_array(&mut temp as MutAfArray, + slice.as_ptr() as *const c_void, + offset as DimT, + dims.ndims() as c_uint, + dims.get().as_ptr() as * const c_longlong, + strides.get().as_ptr() as * const c_longlong, + aftype as uint8_t); + match err_val { + 0 => Ok(Array {handle: temp}), + _ => Err(AfError::from(err_val)), + } + } + } + /// Returns the backend of the Array /// /// # Return Values /// /// Returns an value of type `Backend` which indicates which backend /// was active when Array was created. - pub fn get_backend(&self) -> Backend { + pub fn get_backend(&self) -> Result { unsafe { let mut ret_val: i32 = 0; - af_get_backend_id(&mut ret_val as *mut c_int, self.handle as AfArray); - match ret_val { - 1 => Backend::AF_BACKEND_CPU, - 2 => Backend::AF_BACKEND_CUDA, - 3 => Backend::AF_BACKEND_OPENCL, - _ => Backend::AF_BACKEND_DEFAULT, + let err_val = af_get_backend_id(&mut ret_val as *mut c_int, self.handle as AfArray); + match (err_val, ret_val) { + (0, 1) => Ok(Backend::CPU), + (0, 2) => Ok(Backend::CUDA), + (0, 3) => Ok(Backend::OPENCL), + _ => Err(AfError::from(err_val)), + } + } + } + + /// Returns the device identifier(integer) on which the Array was created + /// + /// # Return Values + /// + /// Return the device id on which Array was created. + pub fn get_device_id(&self) -> Result { + unsafe { + let mut ret_val: i32 = 0; + let err_val = af_get_device_id(&mut ret_val as *mut c_int, self.handle as AfArray); + match err_val { + 0 => Ok(ret_val), + _ => Err(AfError::from(err_val)), + } } } @@ -172,8 +234,8 @@ impl Array { let mut ret1: i64 = 0; let mut ret2: i64 = 0; let mut ret3: i64 = 0; - let err_val = 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, + let err_val = af_get_dims(&mut ret0 as *mut DimT, &mut ret1 as *mut DimT, + &mut ret2 as *mut DimT, &mut ret3 as *mut DimT, self.handle as AfArray); match err_val { 0 => Ok(Dim4::new(&[ret0 as u64, ret1 as u64, ret2 as u64, ret3 as u64])), @@ -182,6 +244,23 @@ impl Array { } } + /// Returns the strides of the Array + pub fn strides(&self) -> Result { + unsafe { + let mut ret0: i64 = 0; + let mut ret1: i64 = 0; + let mut ret2: i64 = 0; + let mut ret3: i64 = 0; + let err_val = af_get_strides(&mut ret0 as *mut DimT, &mut ret1 as *mut DimT, + &mut ret2 as *mut DimT, &mut ret3 as *mut DimT, + self.handle as AfArray); + match err_val { + 0 => Ok(Dim4::new(&[ret0 as u64, ret1 as u64, ret2 as u64, ret3 as u64])), + _ => Err(AfError::from(err_val)), + } + } + } + /// Returns the number of dimensions of the Array pub fn numdims(&self) -> Result { unsafe { @@ -194,6 +273,18 @@ impl Array { } } + /// Returns the offset to the pointer from where data begins + pub fn offset(&self) -> Result { + unsafe { + let mut ret_val: i64 = 0; + let err_val = af_get_offset(&mut ret_val as *mut DimT, self.handle as AfArray); + match err_val { + 0 => Ok(ret_val), + _ => Err(AfError::from(err_val)), + } + } + } + /// Returns the native FFI handle for Rust object `Array` pub fn get(&self) -> i64 { self.handle @@ -247,6 +338,8 @@ impl Array { is_func!(is_floating, af_is_floating); is_func!(is_integer, af_is_integer); is_func!(is_bool, af_is_bool); + is_func!(is_linear, af_is_linear); + is_func!(is_owner, af_is_owner); /// Cast the Array data type to `target_type` pub fn cast(&self, target_type: Aftype) -> Result { diff --git a/src/backend.rs b/src/backend.rs index 0070cfd80..402ad297f 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -7,6 +7,7 @@ extern { fn af_set_backend(bknd: uint8_t) -> c_int; fn af_get_backend_count(num_backends: *mut c_uint) -> c_int; fn af_get_available_backends(backends: *mut c_int) -> c_int; + fn af_get_active_backend(backend: *mut c_int) -> c_int; } /// Toggle backends between cuda, opencl or cpu @@ -47,12 +48,28 @@ pub fn get_available_backends() -> Result, AfError> { match err_val { 0 => { let mut b = Vec::new(); - if temp & 0b0100 == 0b0100 { b.push(Backend::AF_BACKEND_OPENCL); } - if temp & 0b0010 == 0b0010 { b.push(Backend::AF_BACKEND_CUDA); } - if temp & 0b0001 == 0b0001 { b.push(Backend::AF_BACKEND_CPU); } + if temp & 0b0100 == 0b0100 { b.push(Backend::OPENCL); } + if temp & 0b0010 == 0b0010 { b.push(Backend::CUDA); } + if temp & 0b0001 == 0b0001 { b.push(Backend::CPU); } Ok(b) }, _ => Err(AfError::from(err_val)), } } } + +/// Get current active backend +#[allow(unused_mut)] +pub fn get_active_backend() -> Result { + unsafe { + let mut temp: i32 = 0; + let err_val = af_get_active_backend(&mut temp as *mut c_int); + match (err_val, temp) { + (0, 0) => Ok(Backend::DEFAULT), + (0, 1) => Ok(Backend::CPU), + (0, 2) => Ok(Backend::CUDA), + (0, 4) => Ok(Backend::OPENCL), + _ => Err(AfError::from(err_val)), + } + } +} diff --git a/src/defines.rs b/src/defines.rs index 8d5597d82..c2a4f8ddd 100644 --- a/src/defines.rs +++ b/src/defines.rs @@ -28,6 +28,8 @@ pub enum AfError { ERR_DIFF_TYPE = 205, /// Function does not support GFOR / batch mode ERR_BATCH = 207, + /// Input does not belong to the current device + ERR_DEVICE = 208, // 300-399 Errors for missing software features /// The option is not supported ERR_NOT_SUPPORTED = 301, @@ -51,22 +53,22 @@ pub enum AfError { #[derive(Clone, Copy, Debug, PartialEq)] pub enum Backend { /// Default backend order: OpenCL -> CUDA -> CPU - AF_BACKEND_DEFAULT = 0, + DEFAULT = 0, /// CPU a.k.a sequential algorithms - AF_BACKEND_CPU = 1, + CPU = 1, /// CUDA Compute Backend - AF_BACKEND_CUDA = 2, + CUDA = 2, /// OpenCL Compute Backend - AF_BACKEND_OPENCL = 4 + OPENCL = 4 } impl Display for Backend { fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> { let text = match *self { - Backend::AF_BACKEND_OPENCL => "OpenCL", - Backend::AF_BACKEND_CUDA => "Cuda", - Backend::AF_BACKEND_CPU => "CPU", - Backend::AF_BACKEND_DEFAULT => "Default", + Backend::OPENCL => "OpenCL", + Backend::CUDA => "Cuda", + Backend::CPU => "CPU", + Backend::DEFAULT => "Default", }; write!(f, "{}", text) } @@ -91,6 +93,7 @@ impl Error for AfError { AfError::ERR_TYPE => "The type is not supported by this function", AfError::ERR_DIFF_TYPE => "The type of input arrays are not compatible", AfError::ERR_BATCH => "Function does not support GFOR / batch mode", + AfError::ERR_DEVICE => "Array does not belong to device", AfError::ERR_NOT_SUPPORTED => "The option is not supported", AfError::ERR_NOT_CONFIGURED => "This build of ArrayFire does not support this feature", AfError::ERR_NO_DBL => "This device does not support double", @@ -305,3 +308,17 @@ pub enum HomographyType { /// Least Median of Squares LMEDS = 1, } + +/// Plotting markers +#[repr(C)] +#[derive(Copy, Clone)] +pub enum MarkerType { + NONE = 0, + POINT = 1, + CIRCLE = 2, + SQUARE = 3, + TRIANGLE = 4, + CROSS = 5, + PLUS = 6, + STAR = 7 +} diff --git a/src/device/mod.rs b/src/device/mod.rs index fd17e1fd0..0215b73d0 100644 --- a/src/device/mod.rs +++ b/src/device/mod.rs @@ -1,15 +1,23 @@ extern crate libc; use defines::AfError; -use self::libc::c_int; +use self::libc::{c_int, size_t, c_char}; +use std::ffi::CString; 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_init() -> c_int; fn af_get_device_count(nDevices: *mut c_int) -> c_int; fn af_get_dbl_support(available: *mut c_int, device: c_int) -> c_int; fn af_set_device(device: c_int) -> c_int; fn af_get_device(device: *mut c_int) -> c_int; + fn af_device_mem_info(alloc_bytes: *mut size_t, alloc_buffers: *mut size_t, + lock_bytes: *mut size_t, lock_buffers: *mut size_t) -> c_int; + fn af_print_mem_info(msg: *const c_char, device_id: c_int) -> c_int; + fn af_set_mem_step_size(step_bytes: size_t) -> c_int; + fn af_get_mem_step_size(step_bytes: *mut size_t) -> c_int; + fn af_device_gc() -> c_int; fn af_sync(device: c_int) -> c_int; } @@ -52,6 +60,20 @@ pub fn info() -> Result<(), AfError> { } } +/// Initialize ArrayFire library +/// +/// 0th device will be the default device unless init call +/// is followed by set_device +pub fn init() -> Result<(), AfError> { + unsafe { + let err_val = af_init(); + match err_val { + 0 => Ok(()), + _ => Err(AfError::from(err_val)), + } + } +} + /// Get total number of available devices pub fn device_count() -> Result { unsafe { @@ -111,6 +133,116 @@ pub fn get_device() -> Result { } } +/// Get memory information from the memory manager for the current active device +/// +/// # Parameters +/// +/// This function doesn't take any input parameters +/// +/// # Return Values +/// +/// A quadruple of values regarding the following information. +/// +/// * Number of bytes allocated +/// * Number of buffers allocated +/// * Number of bytes locked +/// * Number of buffers locked +pub fn device_mem_info() -> Result<(u64, u64, u64, u64), AfError> { + unsafe { + let mut o0: u64 = 0; + let mut o1: u64 = 0; + let mut o2: u64 = 0; + let mut o3: u64 = 0; + let err_val = af_device_mem_info(&mut o0 as *mut size_t, + &mut o1 as *mut size_t, + &mut o2 as *mut size_t, + &mut o3 as *mut size_t); + match err_val { + 0 => Ok((o0, o1, o2, o3)), + _ => Err(AfError::from(err_val)), + } + } +} + +/// Print buffer details from the ArrayFire device manager +/// +/// This information is printed in the form of a table. +/// +/// # Parameters +/// +/// - `msg` is a message to print before the table +/// - `device` is the id of the device for which buffer details are to be printed +/// +/// # Return Values +/// +/// None +pub fn print_mem_info(msg: String, device: i32) -> Result<(), AfError> { + unsafe { + let cmsg = CString::new(msg.as_bytes()); + match cmsg { + Ok(v) => { + let err_val = af_print_mem_info(v.to_bytes_with_nul().as_ptr() as * const c_char, + device as c_int); + match err_val { + 0 => Ok(()), + _ => Err(AfError::from(err_val)), + } + }, + Err(_) => Err(AfError::from(AfError::ERR_INTERNAL)), + } + } +} + +/// Set the minimum memory chunk size +/// +/// # Parameters +/// +/// - `step_bytes` is the size of minimum memory chunk in bytes +/// +/// # Return Values +/// +/// None +pub fn set_mem_step_size(step_bytes: u64) -> Result<(), AfError> { + unsafe { + let err_val = af_set_mem_step_size(step_bytes as size_t); + match err_val { + 0 => Ok(()), + _ => Err(AfError::from(err_val)), + } + } +} + +/// Get the minimum memory chunk size +/// +/// # Parameters +/// +/// None +/// +/// # Return Values +/// +/// Returns is the size of minimum memory chunk in bytes +pub fn get_mem_step_size() -> Result { + unsafe { + let mut temp: u64 = 0; + let err_val = af_get_mem_step_size(&mut temp as *mut size_t); + match err_val { + 0 => Ok(temp), + _ => Err(AfError::from(err_val)), + } + } +} + +/// Call the garbage collection routine +pub fn device_gc() -> Result<(), AfError> { + unsafe { + let err_val = af_device_gc(); + match err_val { + 0 => Ok(()), + _ => Err(AfError::from(err_val)), + } + } +} + /// Sync all operations on given device /// /// # Parameters diff --git a/src/graphics.rs b/src/graphics.rs index 718da6e71..1413f9151 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -2,7 +2,7 @@ extern crate libc; use array::Array; use defines::AfError; -use defines::ColorMap; +use defines::{ColorMap, MarkerType}; use self::libc::{c_int, c_uint, c_double, c_char}; use std::ffi::CString; @@ -17,6 +17,7 @@ extern { fn af_set_position(wnd: WndHandle, x: c_uint, y: c_uint) -> c_int; fn af_set_title(wnd: WndHandle, title: *const c_char) -> c_int; fn af_set_size(wnd: WndHandle, w: c_uint, h: c_uint) -> c_int; + fn af_set_visibility(wnd: WndHandle, is_visible: c_int) -> c_int; fn af_draw_image(wnd: WndHandle, arr: AfArray, props: CellPtr) -> c_int; fn af_draw_plot(wnd: WndHandle, x: AfArray, y: AfArray, props: CellPtr) -> c_int; fn af_draw_plot3(wnd: WndHandle, P: AfArray, props: CellPtr) -> c_int; @@ -24,6 +25,8 @@ extern { minval: c_double, maxval: c_double, props: CellPtr) -> c_int; fn af_draw_surface(wnd: WndHandle, xvals: AfArray, yvals: AfArray, S: AfArray, props: CellPtr) -> c_int; + fn af_draw_scatter(wnd: WndHandle, x: AfArray, y: AfArray, marker: c_int, props: CellPtr) -> c_int; + fn af_draw_scatter3(wnd: WndHandle, P: AfArray, marker: c_int, props: CellPtr) -> c_int; fn af_grid(wnd: WndHandle, rows: c_int, cols: c_int) -> c_int; fn af_show(wnd: WndHandle) -> c_int; fn af_is_window_closed(out: *mut c_int, wnd: WndHandle) -> c_int; @@ -151,6 +154,25 @@ impl Window { } } + /// Set window visibility + /// + /// # Parameters + /// + /// - `is_visible` is a boolean indicating whether window is to be hidden or brought into focus + /// + /// # Return Values + /// + /// None + pub fn set_visibility(&self, is_visible: bool) -> Result<(), AfError> { + unsafe { + let err_val = af_set_visibility(self.handle as WndHandle, is_visible as c_int); + match err_val { + 0 => Ok(()), + _ => Err(AfError::from(err_val)), + } + } + } + /// Set window size /// /// # Parameters @@ -307,4 +329,43 @@ impl Window { } } } + + /// Render give Arrays as 2d scatter plot + pub fn draw_scatter(&self, xvals: &Array, yvals: &Array, marker: MarkerType, title: Option) { + let tstr = match title { + Some(s) => s, + None => format!("Cell({},{}))", self.col, self.row) + }; + let cprops = &Cell {row: self.row, col: self.col, title: tstr.clone(), cmap: self.cmap}; + unsafe { + let err_val = af_draw_scatter(self.handle as WndHandle, + xvals.get() as AfArray, + yvals.get() as AfArray, + marker as c_int, + cprops as *const Cell as CellPtr); + match err_val { + 0 => (), + _ => panic!("Rendering scatter failed: {}", err_val), + } + } + } + + /// Render give Array as 3d scatter plot + pub fn draw_scatter3(&self, vals: &Array, marker: MarkerType, title: Option) { + let tstr = match title { + Some(s) => s, + None => format!("Cell({},{}))", self.col, self.row) + }; + let cprops = &Cell {row: self.row, col: self.col, title: tstr.clone(), cmap: self.cmap}; + unsafe { + let err_val = af_draw_scatter3(self.handle as WndHandle, + vals.get() as AfArray, + marker as c_int, + cprops as *const Cell as CellPtr); + match err_val { + 0 => (), + _ => panic!("Rendering scatter3 failed: {}", err_val), + } + } + } } diff --git a/src/image/mod.rs b/src/image/mod.rs index 5188b0819..c81c7deae 100644 --- a/src/image/mod.rs +++ b/src/image/mod.rs @@ -95,6 +95,8 @@ extern { fn af_ycbcr2rgb(out: MutAfArray, input: AfArray, stnd: c_int) -> c_int; fn af_rgb2ycbcr(out: MutAfArray, input: AfArray, stnd: c_int) -> c_int; + fn af_is_image_io_available(out: *mut c_int) -> c_int; + fn af_transform_coordinates(out: MutAfArray, tf: AfArray, d0: c_float, d1: c_float) -> c_int; } /// Calculate the gradients @@ -1141,3 +1143,50 @@ pub fn ycbcr2rgb(input: &Array, standard: YCCStd) -> Result { } } } + +/// Function to check if Image I/O is available +/// +/// # Parameters +/// +/// None +/// +/// # Return Values +/// +/// Return a boolean indicating if ArrayFire was compiled with Image I/O support +pub fn is_imageio_available() -> bool { + unsafe { + let mut temp: i32 = 0; + af_is_image_io_available(&mut temp as *mut c_int); + temp > 0 // Return boolean fla + } +} + +/// Transform input coordinates +/// +/// The transform function uses a perspective transform matrix to transform input coordinates +/// (given as two dimensions) into a coordinates matrix. +/// +/// The output is a 4x2 matrix, indicating the coordinates of the 4 bidimensional transformed +/// points. +/// +/// # Parameters +/// +/// - `tf` is the transformation matrix +/// - `d0` is the first input dimension +/// - `d1` is the second input dimension +/// +/// # Return Values +/// +/// Transformed coordinates +pub fn transform_coords(tf: &Array, d0: f32, d1: f32) -> Result { + unsafe { + let mut temp: i64 = 0; + let err_val = af_transform_coordinates(&mut temp as MutAfArray, + tf.get() as AfArray, + d0 as c_float, d1 as c_float); + match err_val { + 0 => Ok(Array::from(temp)), + _ => Err(AfError::from(err_val)), + } + } +} diff --git a/src/lapack/mod.rs b/src/lapack/mod.rs index ca02805db..e7a32e000 100644 --- a/src/lapack/mod.rs +++ b/src/lapack/mod.rs @@ -26,6 +26,7 @@ extern { 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; + fn af_is_lapack_available(out: *mut c_int) -> c_int; } /// Perform Singular Value Decomposition @@ -414,3 +415,20 @@ pub fn norm(input: &Array, ntype: NormType, p: f64, q: f64) -> Result bool { + unsafe { + let mut temp: i32 = 0; + af_is_lapack_available(&mut temp as *mut c_int); + temp > 0 // Return boolean fla + } +} diff --git a/src/lib.rs b/src/lib.rs index 09d7a5b1e..fe22fd220 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,7 +23,7 @@ pub use arith::{sqrt, log, log1p, log10, log2, pow2, exp, expm1, erf, erfc, root pub use arith::{cbrt, factorial, tgamma, lgamma, iszero, isinf, isnan}; mod arith; -pub use backend::{set_backend, get_backend_count, get_available_backends}; +pub use backend::{set_backend, get_backend_count, get_available_backends, get_active_backend}; mod backend; pub use blas::{matmul, dot, transpose, transpose_inplace}; @@ -37,12 +37,14 @@ pub use data::{reorder, shift, moddims, flat, flip}; pub use data::{select, selectl, selectr, replace, replace_scalar}; mod data; -pub use device::{get_version, info, device_count, is_double_available, set_device, get_device, sync}; +pub use device::{get_version, info, init, device_count, is_double_available, set_device, get_device}; +pub use device::{device_mem_info, print_mem_info, set_mem_step_size, get_mem_step_size, device_gc, sync}; mod device; pub use defines::{Aftype, AfError, Backend, ColorMap, YCCStd, HomographyType}; pub use defines::{InterpType, BorderType, MatchType, NormType}; pub use defines::{Connectivity, ConvMode, ConvDomain, ColorSpace, MatProp}; +pub use defines::{MarkerType}; mod defines; pub use dim4::Dim4; @@ -65,11 +67,11 @@ 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}; -pub use image::{unwrap, wrap, sat, rgb2ycbcr, ycbcr2rgb}; +pub use image::{unwrap, wrap, sat, rgb2ycbcr, ycbcr2rgb, is_imageio_available, transform_coords}; mod image; pub use lapack::{svd, lu, qr, cholesky, solve, solve_lu, inverse, det, rank, norm}; -pub use lapack::{svd_inplace, lu_inplace, qr_inplace, cholesky_inplace}; +pub use lapack::{svd_inplace, lu_inplace, qr_inplace, cholesky_inplace, is_lapack_available}; mod lapack; mod num; From bb8f2da987562af2ead5ec8bf40d6273499b19f9 Mon Sep 17 00:00:00 2001 From: pradeep Date: Sat, 12 Mar 2016 13:45:26 +0530 Subject: [PATCH 07/37] Improved data generation API and Array creation API Defined and implemented a trait `HasAfEnum` for the types supported by ArrayFire. This trait is used by the Array creation and data generation functions now making the function API more terse. Changed the examples to reflect the new modifications. --- examples/helloworld.rs | 6 ++--- examples/pi.rs | 4 ++-- examples/snow.rs | 2 +- examples/unified.rs | 2 +- src/array.rs | 26 +++++++++------------ src/data/mod.rs | 22 +++++++++--------- src/defines.rs | 1 + src/image/mod.rs | 6 ++--- src/index.rs | 14 ++++++------ src/lib.rs | 1 + src/util.rs | 52 ++++++++++++++++++++++++++++++++++++++++++ src/vision/mod.rs | 12 ++++++---- 12 files changed, 100 insertions(+), 48 deletions(-) diff --git a/examples/helloworld.rs b/examples/helloworld.rs index 356d3986c..f61612d0a 100644 --- a/examples/helloworld.rs +++ b/examples/helloworld.rs @@ -10,7 +10,7 @@ fn main() { let num_rows: u64 = 5; let num_cols: u64 = 3; let values: &[f32] = &[1.0, 2.0, 3.0]; - let indices = Array::new(Dim4::new(&[3, 1, 1, 1]), values, Aftype::F32).unwrap(); + let indices = Array::new(values, Dim4::new(&[3, 1, 1, 1])).unwrap(); let dims = Dim4::new(&[num_rows, num_cols, 1, 1]); @@ -74,13 +74,13 @@ fn main() { println!("Set last row to 1's"); let r_dims = Dim4::new(&[3, 1, 1, 1]); let r_input: [f32; 3] = [1.0, 1.0, 1.0]; - let r = Array::new(r_dims, &r_input, Aftype::F32).unwrap(); + let r = Array::new(&r_input, r_dims).unwrap(); print(&set_row(&a, &r, num_rows - 1).unwrap()); println!("Create 2-by-3 matrix from host data"); let d_dims = Dim4::new(&[2, 3, 1, 1]); let d_input: [i32; 6] = [1, 2, 3, 4, 5, 6]; - let d = &Array::new(d_dims, &d_input, Aftype::S32).unwrap(); + let d = &Array::new(&d_input, d_dims).unwrap(); print(d); // printf("Copy last column onto first\n"); diff --git a/examples/pi.rs b/examples/pi.rs index 9ec60d61d..5989fb5de 100644 --- a/examples/pi.rs +++ b/examples/pi.rs @@ -12,8 +12,8 @@ fn main() { let samples = 20_000_000; let dims = Dim4::new(&[samples, 1, 1, 1]); - let x = &randu(dims, Aftype::F32).unwrap(); - let y = &randu(dims, Aftype::F32).unwrap(); + let x = &randu::(dims).unwrap(); + let y = &randu::(dims).unwrap(); let start = PreciseTime::now(); diff --git a/examples/snow.rs b/examples/snow.rs index d812680d9..f51dd137d 100644 --- a/examples/snow.rs +++ b/examples/snow.rs @@ -16,7 +16,7 @@ fn main() { let dims = Dim4::new(&[1280, 720, 3, 1]); loop { - randu(dims, Aftype::F32).as_ref() + randu::(dims).as_ref() .map(|arr| wnd.draw_image(arr, None)); if wnd.is_closed().unwrap() == true { break; } diff --git a/examples/unified.rs b/examples/unified.rs index d865e3401..6a5d7fce5 100644 --- a/examples/unified.rs +++ b/examples/unified.rs @@ -11,7 +11,7 @@ fn test_backend(){ let dims = Dim4::new(&[num_rows, num_cols, 1, 1]); println!("Create a 10-by-10 matrix of random floats on the compute device"); - let a = match randu(dims, Aftype::F32) { + let a = match randu::(dims) { Ok(value) => value, Err(error) => panic!("{}", error), }; diff --git a/src/array.rs b/src/array.rs index 45914b1bf..043e9e3fa 100644 --- a/src/array.rs +++ b/src/array.rs @@ -2,6 +2,7 @@ extern crate libc; use dim4::Dim4; use defines::{AfError, Aftype, Backend}; +use util::HasAfEnum; use self::libc::{uint8_t, c_void, c_int, c_uint, c_longlong}; type MutAfArray = *mut self::libc::c_longlong; @@ -119,11 +120,12 @@ impl Array { /// /// ``` /// let values: &[f32] = &[1.0, 2.0, 3.0]; - /// let indices = Array::new(Dim4::new(&[3, 1, 1, 1]), values, Aftype::F32).unwrap(); + /// let indices = Array::new(values, Dim4::new(&[3, 1, 1, 1])).unwrap(); /// ``` #[allow(unused_mut)] - pub fn new(dims: Dim4, slice: &[T], aftype: Aftype) -> Result { + pub fn new(slice: &[T], dims: Dim4) -> Result { unsafe { + let aftype = T::get_af_dtype(); let mut temp: i64 = 0; let err_val = af_create_array(&mut temp as MutAfArray, slice.as_ptr() as *const c_void, @@ -140,18 +142,11 @@ impl Array { /// Constructs a new Array object from strided data /// /// This data can possiblly offseted using an additiona `offset` parameter. - /// - /// # Examples - /// - /// ``` - /// let values: &[f32] = &[1.0, 2.0, 3.0]; - /// let indices = Array::new(Dim4::new(&[3, 1, 1, 1]), values, Aftype::F32).unwrap(); - /// ``` #[allow(unused_mut)] - pub fn new_strided(slice: &[T], offset: i64, - dims: Dim4, strides: Dim4, - aftype: Aftype) -> Result { + pub fn new_strided(slice: &[T], offset: i64, + dims: Dim4, strides: Dim4) -> Result { unsafe { + let aftype = T::get_af_dtype(); let mut temp: i64 = 0; let err_val = af_create_strided_array(&mut temp as MutAfArray, slice.as_ptr() as *const c_void, @@ -342,10 +337,11 @@ impl Array { is_func!(is_owner, af_is_owner); /// Cast the Array data type to `target_type` - pub fn cast(&self, target_type: Aftype) -> Result { + pub fn cast(&self) -> Result { unsafe { + let trgt_type = T::get_af_dtype(); let mut temp: i64 = 0; - let err_val = af_cast(&mut temp as MutAfArray, self.handle as AfArray, target_type as uint8_t); + let err_val = af_cast(&mut temp as MutAfArray, self.handle as AfArray, trgt_type as uint8_t); match err_val { 0 => Ok(Array::from(temp)), _ => Err(AfError::from(err_val)), @@ -394,7 +390,7 @@ impl Drop for Array { /// /// ``` /// println!("Create a 5-by-3 matrix of random floats on the GPU"); -/// let a = match randu(dims, Aftype::F32) { +/// let a = match randu::(dims) { /// Ok(value) => value, /// Err(error) => panic!("{}", error), /// }; diff --git a/src/data/mod.rs b/src/data/mod.rs index 1b611d844..b5432a568 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -4,10 +4,9 @@ extern crate num; use array::Array; use dim4::Dim4; use defines::AfError; -use defines::Aftype; use self::libc::{uint8_t, c_int, c_uint, c_double}; use self::num::Complex; - +use util::HasAfEnum; use std::vec::Vec; type MutAfArray = *mut self::libc::c_longlong; @@ -220,15 +219,15 @@ pub fn constant(cnst: T, dims: Dim4) -> Result Result { +pub fn range(dims: Dim4, seq_dim: i32) -> Result { unsafe { + let aftype = T::get_af_dtype(); let mut temp: i64 = 0; - let err_val =af_range(&mut temp as MutAfArray, + let err_val = 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); match err_val { @@ -246,14 +245,14 @@ pub fn range(dims: Dim4, seq_dim: i32, aftype: Aftype) -> Result /// /// - `dims` is the dimensions of the sequence to be generated /// - `tdims` is the number of repitions of the unit dimensions -/// - `aftype` is the type of Array to generate /// /// # Return Values /// /// Array #[allow(unused_mut)] -pub fn iota(dims: Dim4, tdims: Dim4, aftype: Aftype) -> Result { +pub fn iota(dims: Dim4, tdims: Dim4) -> Result { unsafe { + let aftype = T::get_af_dtype(); let mut temp: i64 = 0; let err_val =af_iota(&mut temp as MutAfArray, dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT, @@ -293,8 +292,9 @@ pub fn get_seed() -> Result { macro_rules! data_gen_def { ($fn_name:ident, $ffi_name: ident) => ( #[allow(unused_mut)] - pub fn $fn_name(dims: Dim4, aftype: Aftype) -> Result { + pub fn $fn_name(dims: Dim4) -> Result { unsafe { + let aftype = T::get_af_dtype(); let mut temp: i64 = 0; let err_val = $ffi_name(&mut temp as MutAfArray, dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT, @@ -412,9 +412,9 @@ pub fn join_many(dim: i32, inputs: Vec<&Array>) -> Result { /// ``` /// # #[macro_use] extern crate arrayfire; /// # fn main() { -/// let a = randu(Dim4::new(&[5, 3, 1, 1]), Aftype::F32).unwrap(); -/// let b = randu(Dim4::new(&[5, 3, 1, 1]), Aftype::F32).unwrap(); -/// let c = randu(Dim4::new(&[5, 3, 1, 1]), Aftype::F32).unwrap(); +/// let a = randu::(Dim4::new(&[5, 3, 1, 1])).unwrap(); +/// let b = randu::(Dim4::new(&[5, 3, 1, 1])).unwrap(); +/// let c = randu::(Dim4::new(&[5, 3, 1, 1])).unwrap(); /// let d = join_many![2, a, b, c]; /// # } /// ``` diff --git a/src/defines.rs b/src/defines.rs index c2a4f8ddd..8ed0e1687 100644 --- a/src/defines.rs +++ b/src/defines.rs @@ -49,6 +49,7 @@ pub enum AfError { ERR_UNKNOWN = 999 } +/// Compute/Acceleration Backend #[repr(C)] #[derive(Clone, Copy, Debug, PartialEq)] pub enum Backend { diff --git a/src/image/mod.rs b/src/image/mod.rs index c81c7deae..4dc6d0e83 100644 --- a/src/image/mod.rs +++ b/src/image/mod.rs @@ -2,12 +2,12 @@ extern crate libc; use array::Array; use defines::AfError; -use defines::Aftype; use defines::BorderType; use defines::ColorSpace; use defines::Connectivity; use defines::InterpType; use defines::YCCStd; +use util::HasAfEnum; use self::libc::{uint8_t, c_uint, c_int, c_float, c_double}; type MutAfArray = *mut self::libc::c_longlong; @@ -812,14 +812,14 @@ pub fn color_space(input: &Array, /// /// - `input` is the input image /// - `conn` can take one of the values of [Connectivity](./enum.Connectivity.html) -/// - `aftype` can take one of the values of [Aftype](./enum.Aftype.html) /// /// # Return Values /// /// Array with labels indicating different regions #[allow(unused_mut)] -pub fn regions(input: &Array, conn: Connectivity, aftype: Aftype) -> Result { +pub fn regions(input: &Array, conn: Connectivity) -> Result { unsafe { + let aftype = T::get_af_dtype(); let mut temp: i64 = 0; let err_val = af_regions(&mut temp as MutAfArray, input.get() as AfArray, conn as uint8_t, aftype as uint8_t); diff --git a/src/index.rs b/src/index.rs index 2aca11327..91378debb 100644 --- a/src/index.rs +++ b/src/index.rs @@ -125,7 +125,7 @@ impl Drop for Indexer { /// # Examples /// /// ``` -/// let a = randu(dims, Aftype::F32).unwrap(); +/// let a = randu::(dims).unwrap(); /// let seqs = &[Seq::new(1.0, 3.0, 1.0), Seq::default()]; /// let sub = index(&a, seqs).unwrap(); /// println!("a(seq(1, 3, 1), span)"); @@ -153,7 +153,7 @@ pub fn index(input: &Array, seqs: &[Seq]) -> Result /// # Examples /// /// ``` -/// let a = randu(dims, Aftype::F32).unwrap(); +/// let a = randu::(dims).unwrap(); /// println!("Grab last row of the random matrix"); /// print(&a); /// print(&row(&a, num_rows - 1).unwrap()); @@ -189,7 +189,7 @@ pub fn set_rows(input: &Array, new_rows: &Array, first: u64, last: u64) -> Resul /// # Examples /// /// ``` -/// let a = randu(dims, Aftype::F32).unwrap(); +/// let a = randu::(dims).unwrap(); /// println!("Grab last col of the random matrix"); /// print(&a); /// print(&row(&a, num_cols - 1).unwrap()); @@ -328,9 +328,9 @@ pub fn assign_seq(lhs: &Array, seqs: &[Seq], rhs: &Array) -> Result< /// /// ``` /// let values: &[f32] = &[1.0, 2.0, 3.0]; -/// let indices = Array::new(Dim4::new(&[3, 1, 1, 1]), values, Aftype::F32).unwrap(); +/// let indices = Array::new(values, Dim4::new(&[3, 1, 1, 1])).unwrap(); /// let seq4gen = Seq::new(0.0, 2.0, 1.0); -/// let a = randu(Dim4::new(&[5, 3, 1, 1]), Aftype::F32).unwrap(); +/// let a = randu::(Dim4::new(&[5, 3, 1, 1])).unwrap(); /// // [5 3 1 1] /// // 0.0000 0.2190 0.3835 /// // 0.1315 0.0470 0.5194 @@ -371,9 +371,9 @@ pub fn index_gen(input: &Array, indices: Indexer) -> Result { /// /// ``` /// let values: &[f32] = &[1.0, 2.0, 3.0]; -/// let indices = Array::new(Dim4::new(&[3, 1, 1, 1]), values, Aftype::F32).unwrap(); +/// let indices = Array::new(values, Dim4::new(&[3, 1, 1, 1])).unwrap(); /// let seq4gen = Seq::new(0.0, 2.0, 1.0); -/// let a = randu(Dim4::new(&[5, 3, 1, 1]), Aftype::F32).unwrap(); +/// let a = randu::(Dim4::new(&[5, 3, 1, 1])).unwrap(); /// // [5 3 1 1] /// // 0.0000 0.2190 0.3835 /// // 0.1315 0.0470 0.5194 diff --git a/src/lib.rs b/src/lib.rs index fe22fd220..00a214db0 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -91,6 +91,7 @@ pub use statistics::{var_all, mean_all, stdev_all, median_all}; pub use statistics::{mean_all_weighted, var_all_weighted}; mod statistics; +pub use util::{HasAfEnum}; mod util; pub use vision::Features; diff --git a/src/util.rs b/src/util.rs index a26a74c0c..201a543bc 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,3 +1,5 @@ +extern crate num; + use defines::AfError; use defines::Aftype; use defines::InterpType; @@ -7,6 +9,7 @@ use defines::MatProp; use defines::MatchType; use defines::ColorMap; use std::mem; +use self::num::Complex; impl From for AfError { fn from(t: i32) -> AfError { @@ -72,3 +75,52 @@ impl From for ColorMap { unsafe { mem::transmute(t) } } } + +/// Types of the data that can be generated using ArrayFire data generation functions. +/// +/// The trait HasAfEnum has been defined internally for the following types. We strongly suggest +/// not to implement this trait in your program for user defined types because ArrayFire functions +/// will only work for the following data types currently. Any such trait implementation for types +/// other than the ones listed below will result in undefined behavior. +/// +/// - f32 +/// - f64 +/// - num::Complex\ +/// - num::Complex\ +/// - bool +/// - i32 +/// - u32 +/// - u8 +/// - i64 +/// - u64 +/// - i16 +/// - u16 +/// +pub trait HasAfEnum { + fn get_af_dtype() -> Aftype; +} + +macro_rules! impl_has_af_enum { + ($rust_t: ty, $af_dtype: expr) => ( + impl HasAfEnum for $rust_t { + fn get_af_dtype() -> Aftype { + $af_dtype + } + } + ) +} + +impl_has_af_enum!(f32, Aftype::F32); +impl_has_af_enum!(Complex, Aftype::C32); +impl_has_af_enum!(f64, Aftype::F64); +impl_has_af_enum!(Complex, Aftype::C64); +// FIXME: Rust bool may become incompatible in memory layout with C-ABI +// Currently, it is of size 1-byte +impl_has_af_enum!(bool, Aftype::B8); +impl_has_af_enum!(i32, Aftype::S32); +impl_has_af_enum!(u32, Aftype::U32); +impl_has_af_enum!(u8, Aftype::U8); +impl_has_af_enum!(i64, Aftype::S64); +impl_has_af_enum!(u64, Aftype::U64); +impl_has_af_enum!(i16, Aftype::S16); +impl_has_af_enum!(u16, Aftype::U16); diff --git a/src/vision/mod.rs b/src/vision/mod.rs index 23ab89e5b..c61c7da6f 100644 --- a/src/vision/mod.rs +++ b/src/vision/mod.rs @@ -1,7 +1,8 @@ extern crate libc; use array::Array; -use defines::{AfError, HomographyType, Aftype, MatchType}; +use defines::{AfError, HomographyType, MatchType}; +use util::HasAfEnum; use self::libc::{c_void, uint8_t, c_uint, c_int, c_float, c_double, c_longlong}; type MutAfArray = *mut self::libc::c_longlong; @@ -503,11 +504,12 @@ pub fn dog(input: &Array, radius1: i32, radius2: i32) -> Result /// /// - `H` is a 3x3 array containing the estimated homography. /// - `inliers` is the number of inliers that the homography was estimated to comprise, in the case that htype is AF_HOMOGRAPHY_RANSAC, a higher inlier_thr value will increase the estimated inliers. Note that if the number of inliers is too low, it is likely that a bad homography will be returned. -pub fn homography(x_src: &Array, y_src: &Array, - x_dst: &Array, y_dst: &Array, - htype: HomographyType, inlier_thr: f32, - iterations: u32, otype: Aftype) -> Result<(Array, i32), AfError> { +pub fn homography(x_src: &Array, y_src: &Array, + x_dst: &Array, y_dst: &Array, + htype: HomographyType, inlier_thr: f32, + iterations: u32) -> Result<(Array, i32), AfError> { unsafe { + let otype = OutType::get_af_dtype(); let mut inliers: i32 = 0; let mut temp: i64 = 0; let err_val = af_homography(&mut temp as MutAfArray, &mut inliers as *mut c_int, From b2c042ea4c7fcb35b18cc28927f5a9e32483012a Mon Sep 17 00:00:00 2001 From: pradeep Date: Sat, 12 Mar 2016 13:52:25 +0530 Subject: [PATCH 08/37] Fixing typos --- src/array.rs | 2 +- src/image/mod.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/array.rs b/src/array.rs index 043e9e3fa..a597e10c2 100644 --- a/src/array.rs +++ b/src/array.rs @@ -141,7 +141,7 @@ impl Array { /// Constructs a new Array object from strided data /// - /// This data can possiblly offseted using an additiona `offset` parameter. + /// The data pointed by the slice passed to this function can possibily be offseted using an additional `offset` parameter. #[allow(unused_mut)] pub fn new_strided(slice: &[T], offset: i64, dims: Dim4, strides: Dim4) -> Result { diff --git a/src/image/mod.rs b/src/image/mod.rs index 4dc6d0e83..724a9b29d 100644 --- a/src/image/mod.rs +++ b/src/image/mod.rs @@ -817,12 +817,12 @@ pub fn color_space(input: &Array, /// /// Array with labels indicating different regions #[allow(unused_mut)] -pub fn regions(input: &Array, conn: Connectivity) -> Result { +pub fn regions(input: &Array, conn: Connectivity) -> Result { unsafe { - let aftype = T::get_af_dtype(); + let otype = OutType::get_af_dtype(); let mut temp: i64 = 0; let err_val = af_regions(&mut temp as MutAfArray, input.get() as AfArray, - conn as uint8_t, aftype as uint8_t); + conn as uint8_t, otype as uint8_t); match err_val { 0 => Ok(Array::from(temp)), _ => Err(AfError::from(err_val)), From c3f79219e09126f84d9ffb7d2a3167e4d6de6315 Mon Sep 17 00:00:00 2001 From: pradeep Date: Sat, 12 Mar 2016 14:55:52 +0530 Subject: [PATCH 09/37] Added mem_info macro Moved the following macros to separate module(macros) * mem_info * join_many --- examples/pi.rs | 5 +++ src/data/mod.rs | 45 +++--------------------- src/lib.rs | 1 + src/macros.rs | 91 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+), 40 deletions(-) create mode 100644 src/macros.rs diff --git a/examples/pi.rs b/examples/pi.rs index 5989fb5de..744063e99 100644 --- a/examples/pi.rs +++ b/examples/pi.rs @@ -1,3 +1,4 @@ +#[macro_use(mem_info)] extern crate arrayfire as af; extern crate time; @@ -17,6 +18,8 @@ fn main() { let start = PreciseTime::now(); + mem_info!("Before benchmark"); + for bench_iter in 0..100 { let pi_val = add(&mul(x, x, false).unwrap(), &mul(y, y, false).unwrap(), false) .and_then( |z| sqrt(&z) ) @@ -29,4 +32,6 @@ fn main() { let end = PreciseTime::now(); println!("Estimated Pi Value in {} seconds", start.to(end) / 100); + + mem_info!("After benchmark"); } diff --git a/src/data/mod.rs b/src/data/mod.rs index b5432a568..a554a147a 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -395,9 +395,13 @@ pub fn join(dim: i32, first: &Array, second: &Array) -> Result { #[allow(unused_mut)] pub fn join_many(dim: i32, inputs: Vec<&Array>) -> Result { unsafe { + let mut v = Vec::new(); + for i in inputs { + v.push(i.get()); + } let mut temp: i64 = 0; let err_val = af_join_many(&mut temp as MutAfArray, dim as c_int, - inputs.len() as c_uint, inputs.as_ptr() as *const AfArray); + v.len() as c_uint, v.as_ptr() as *const AfArray); match err_val { 0 => Ok(Array::from(temp)), _ => Err(AfError::from(err_val)), @@ -405,45 +409,6 @@ pub fn join_many(dim: i32, inputs: Vec<&Array>) -> Result { } } -/// Join multiple Arrays along a given dimension -/// -/// # Examples -/// -/// ``` -/// # #[macro_use] extern crate arrayfire; -/// # fn main() { -/// let a = randu::(Dim4::new(&[5, 3, 1, 1])).unwrap(); -/// let b = randu::(Dim4::new(&[5, 3, 1, 1])).unwrap(); -/// let c = randu::(Dim4::new(&[5, 3, 1, 1])).unwrap(); -/// let d = join_many![2, a, b, c]; -/// # } -/// ``` -/// -/// # Panics -/// -/// Using this macro to create an Array from multiple Arrays doesn't implicitly check for errors -/// during FFI calls. Therefore, make sure your inputs are correct. In case, you do need proper -/// error checking, use the [function version](./fn.join_many.html) of this macro. -// 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)] diff --git a/src/lib.rs b/src/lib.rs index 00a214db0..c72da3459 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -73,6 +73,7 @@ mod image; pub use lapack::{svd, lu, qr, cholesky, solve, solve_lu, inverse, det, rank, norm}; pub use lapack::{svd_inplace, lu_inplace, qr_inplace, cholesky_inplace, is_lapack_available}; mod lapack; +mod macros; mod num; pub use signal::{approx1, approx2}; diff --git a/src/macros.rs b/src/macros.rs new file mode 100644 index 000000000..a874591f6 --- /dev/null +++ b/src/macros.rs @@ -0,0 +1,91 @@ +/// Macro to print the current stats of ArrayFire's memory manager. +/// +/// `mem_info!` print 4 values: +/// +/// Name | Description +/// -------------------------|------------------------- +/// Allocated Bytes | Total number of bytes allocated by the memory manager +/// Allocated Buffers | Total number of buffers allocated +/// Locked (In Use) Bytes | Number of bytes that are in use by active arrays +/// Locked (In Use) Buffers | Number of buffers that are in use by active arrays +/// +/// The `Allocated Bytes` is always a multiple of the memory step size. The +/// default step size is 1024 bytes. This means when a buffer is to be +/// allocated, the size is always rounded up to a multiple of the step size. +/// You can use [get_mem_step_size](./fn.get_mem_step_size.html) to check the +/// current step size and [set_mem_step_size](./fn.set_mem_step_size.html) to +/// set a custom resolution size. +/// +/// The `Allocated Buffers` is the number of buffers that use up the allocated +/// bytes. This includes buffers currently in scope, as well as buffers marked +/// as free, ie, from arrays gone out of scope. The free buffers are available +/// for use by new arrays that might be created. +/// +/// The `Locked Bytes` is the number of bytes in use that cannot be +/// reallocated at the moment. The difference of Allocated Bytes and Locked +/// Bytes is the total bytes available for reallocation. +/// +/// The `Locked Buffers` is the number of buffer in use that cannot be +/// reallocated at the moment. The difference of Allocated Buffers and Locked +/// Buffers is the number of buffers available for reallocation. +/// +/// # Parameters +/// +/// - `msg` is the message that is printed to screen before printing stats +/// +/// # Examples +/// +/// ``` +/// mem_info!("Here"); +/// ``` +/// +/// Sample Output: +/// +/// ``` +/// AF Memory: Here +/// Allocated [ Bytes | Buffers ] = [ 4096 | 4 ] +/// In Use [ Bytes | Buffers ] = [ 2048 | 2 ] +/// ``` +#[macro_export] +macro_rules! mem_info { + [$msg: expr] => { + { + let (abytes, abuffs, lbytes, lbuffs) = device_mem_info().unwrap(); + println!("AF Memory: {:?}", $msg); + println!("Allocated [Bytes | Buffers] = [ {} | {} ]", abytes, abuffs); + println!("In Use [Bytes | Buffers] = [ {} | {} ]", lbytes, lbuffs); + } + }; +} + +/// Join multiple Arrays along a given dimension +/// +/// # Examples +/// +/// ``` +/// # #[macro_use] extern crate arrayfire; +/// # fn main() { +/// let a = randu::(Dim4::new(&[5, 3, 1, 1])).unwrap(); +/// let b = randu::(Dim4::new(&[5, 3, 1, 1])).unwrap(); +/// let c = randu::(Dim4::new(&[5, 3, 1, 1])).unwrap(); +/// let d = join_many![2, a, b, c]; +/// # } +/// ``` +/// +/// # Panics +/// +/// This macro just calls [join_many](./fn.join_many.html) function after collecting all +/// the input arrays into a vector. +// 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); + )* + join_many($dim, temp_vec) + } + }; +} From 21972e7f12d4b04f5eec8b7e0367fcec1b4f02b8 Mon Sep 17 00:00:00 2001 From: pradeep Date: Sat, 12 Mar 2016 15:04:51 +0530 Subject: [PATCH 10/37] Fixed example code in join_many macro documentation --- src/macros.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index a874591f6..83bbc4c5d 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -60,15 +60,17 @@ macro_rules! mem_info { /// Join multiple Arrays along a given dimension /// +/// All the Arrays provided to this macro should be of type `&Array` +/// /// # Examples /// /// ``` /// # #[macro_use] extern crate arrayfire; /// # fn main() { -/// let a = randu::(Dim4::new(&[5, 3, 1, 1])).unwrap(); -/// let b = randu::(Dim4::new(&[5, 3, 1, 1])).unwrap(); -/// let c = randu::(Dim4::new(&[5, 3, 1, 1])).unwrap(); -/// let d = join_many![2, a, b, c]; +/// let a = &randu::(Dim4::new(&[5, 3, 1, 1])).unwrap(); +/// let b = &randu::(Dim4::new(&[5, 3, 1, 1])).unwrap(); +/// let c = &randu::(Dim4::new(&[5, 3, 1, 1])).unwrap(); +/// let d = join_many![2; a, b, c]; /// # } /// ``` /// From 7ba96af5396d3e5296d5d5ce2d3e35f09247b322 Mon Sep 17 00:00:00 2001 From: pradeep Date: Sun, 13 Mar 2016 16:04:49 +0530 Subject: [PATCH 11/37] Fixed documentation tests(example code stubs) --- examples/helloworld.rs | 2 +- src/array.rs | 25 ++++++++++++++----------- src/data/mod.rs | 10 +++++----- src/device/mod.rs | 2 +- src/dim4.rs | 5 +++++ src/graphics.rs | 13 +++++++------ src/image/mod.rs | 2 +- src/index.rs | 15 ++++++++++++--- src/macros.rs | 24 ++++++++++++++++++------ 9 files changed, 64 insertions(+), 34 deletions(-) diff --git a/examples/helloworld.rs b/examples/helloworld.rs index f61612d0a..e9b1d7dd5 100644 --- a/examples/helloworld.rs +++ b/examples/helloworld.rs @@ -15,7 +15,7 @@ fn main() { let dims = Dim4::new(&[num_rows, num_cols, 1, 1]); println!("Create a 5-by-3 matrix of random floats on the GPU"); - let a = match randu(dims, Aftype::F32) { + let a = match randu::(dims) { Ok(value) => value, Err(error) => panic!("{}", error), }; diff --git a/src/array.rs b/src/array.rs index a597e10c2..1d0c39d43 100644 --- a/src/array.rs +++ b/src/array.rs @@ -119,6 +119,7 @@ impl Array { /// # Examples /// /// ``` + /// use arrayfire::{Array, Dim4}; /// let values: &[f32] = &[1.0, 2.0, 3.0]; /// let indices = Array::new(values, Dim4::new(&[3, 1, 1, 1])).unwrap(); /// ``` @@ -388,25 +389,27 @@ impl Drop for Array { /// /// # Examples /// -/// ``` +/// ``` +/// use arrayfire::{Dim4, print, randu}; /// println!("Create a 5-by-3 matrix of random floats on the GPU"); +/// let dims = Dim4::new(&[3, 1, 1, 1]); /// let a = match randu::(dims) { /// Ok(value) => value, /// Err(error) => panic!("{}", error), /// }; /// print(&a); -/// ``` +/// ``` /// -/// The sample output will look like below: +/// The sample output will look like below: /// -/// ``` -/// [5 3 1 1] -/// 0.7402 0.4464 0.7762 -/// 0.9210 0.6673 0.2948 -/// 0.0390 0.1099 0.7140 -/// 0.9690 0.4702 0.3585 -/// 0.9251 0.5132 0.6814 -/// ``` +/// ```bash +/// [5 3 1 1] +/// 0.7402 0.4464 0.7762 +/// 0.9210 0.6673 0.2948 +/// 0.0390 0.1099 0.7140 +/// 0.9690 0.4702 0.3585 +/// 0.9251 0.5132 0.6814 +/// ``` pub fn print(input: &Array) -> Result<(), AfError> { unsafe { let ret_val = af_print_array(input.get() as AfArray); diff --git a/src/data/mod.rs b/src/data/mod.rs index a554a147a..54b1f3cc1 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -537,7 +537,7 @@ pub fn upper(input: &Array, is_unit_diag: bool) -> Result { /// This function does the C-equivalent of the following statement, except that the operation /// happens on a GPU for all elements simultaneously. /// -/// ``` +/// ```ignore /// c = cond ? a : b; /// where cond, a & b are all objects of type Array /// ``` /// @@ -570,7 +570,7 @@ pub fn select(a: &Array, cond: &Array, b: &Array) -> Result { /// This function does the C-equivalent of the following statement, except that the operation /// happens on a GPU for all elements simultaneously. /// -/// ``` +/// ```ignore /// c = cond ? a : b; /// where a is a scalar(f64) and b is Array /// ``` /// @@ -603,7 +603,7 @@ pub fn selectl(a: f64, cond: &Array, b: &Array) -> Result { /// This function does the C-equivalent of the following statement, except that the operation /// happens on a GPU for all elements simultaneously. /// -/// ``` +/// ```ignore /// c = cond ? a : b; /// where a is Array and b is a scalar(f64) /// ``` /// @@ -636,7 +636,7 @@ pub fn selectr(a: &Array, cond: &Array, b: f64) -> Result { /// This function does the C-equivalent of the following statement, except that the operation /// happens on a GPU for all elements simultaneously. /// -/// ``` +/// ```ignore /// a = cond ? a : b; /// where cond, a & b are all objects of type Array /// ``` /// @@ -666,7 +666,7 @@ pub fn replace(a: &mut Array, cond: &Array, b: &Array) -> Result<(), AfError> { /// This function does the C-equivalent of the following statement, except that the operation /// happens on a GPU for all elements simultaneously. /// -/// ``` +/// ```ignore /// a = cond ? a : b; /// where cond, a are Arrays and b is scalar(f64) /// ``` /// diff --git a/src/device/mod.rs b/src/device/mod.rs index 0215b73d0..c888a2a51 100644 --- a/src/device/mod.rs +++ b/src/device/mod.rs @@ -45,7 +45,7 @@ pub fn get_version() -> Result<(i32, i32, i32), AfError> { /// /// An example output of `af::info` call looks like below /// -/// ``` +/// ```ignore /// ArrayFire v3.0.0 (CUDA, 64-bit Mac OSX, build d8d4b38) /// Platform: CUDA Toolkit 7, Driver: CUDA Driver Version: 7000 /// [0] GeForce GT 750M, 2048 MB, CUDA Compute 3.0 diff --git a/src/dim4.rs b/src/dim4.rs index 23d2eee33..5a9a721a6 100644 --- a/src/dim4.rs +++ b/src/dim4.rs @@ -19,6 +19,8 @@ impl Default for Dim4 { /// # Examples /// /// ``` +/// use arrayfire::Dim4; +/// /// let dims = Dim4::new(&[4, 4, 2, 1]); /// println!("0th Dimension length is {}", dims[0]); // -> 4 /// println!("1th Dimension length is {}", dims[1]); // -> 4 @@ -38,6 +40,8 @@ impl Index for Dim4 { /// # Examples /// /// ``` +/// use arrayfire::Dim4; +/// /// let dims = Dim4::new(&[4, 4, 2, 1]); /// println!("0th Dimension length is {}", dims[0]); // -> 4 /// ``` @@ -53,6 +57,7 @@ impl Dim4 { /// # Examples /// /// ``` + /// use arrayfire::Dim4; /// let dims = Dim4::new(&[4, 4, 2, 1]); /// ``` pub fn new(dims: &[u64; 4]) -> Dim4 { diff --git a/src/graphics.rs b/src/graphics.rs index 1413f9151..c00ac4327 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -54,22 +54,23 @@ pub struct Cell { /// /// # Examples /// -/// ``` -/// let wnd = Window::new(1280, 720, String::from("Image Histogram")).unwrap(); -/// let img = match load_image("Path to image", true/*If color image, 'false' otherwise*/) { +/// ```no_run +/// use arrayfire::{histogram, load_image, Window}; +/// let mut wnd = Window::new(1280, 720, String::from("Image Histogram")).unwrap(); +/// let img = match load_image("Path to image".to_string(), true/*If color image, 'false' otherwise*/) { /// Ok(img) => img, /// Err(err) => panic!("Image loading failed with error code {}", err), /// }; -/// let hst = histogram(img, 256, 0, 255).unwrap(); +/// let hst = histogram(&img, 256, 0 as f64, 255 as f64).unwrap(); /// /// loop { /// wnd.grid(2, 1); /// /// wnd.set_view(0, 0); -/// wnd.draw_image(img, Some("Input Image")); +/// wnd.draw_image(&img, Some("Input Image".to_string())); /// /// wnd.set_view(1, 0); -/// wnd.draw_histogram(hst, 0.0, 255.0, Some("Input Image Histogram")); +/// wnd.draw_hist(&hst, 0.0, 255.0, Some("Input Image Histogram".to_string())); /// /// wnd.show(); /// diff --git a/src/image/mod.rs b/src/image/mod.rs index 724a9b29d..f12f0d866 100644 --- a/src/image/mod.rs +++ b/src/image/mod.rs @@ -968,7 +968,7 @@ hsvrgb_func_def!(rgb2hsv, af_rgb2hsv); /// /// # Examples /// -/// ``` +/// ```ignore /// A [5 5 1 1] /// 10 15 20 25 30 /// 11 16 21 26 31 diff --git a/src/index.rs b/src/index.rs index 91378debb..fe5071231 100644 --- a/src/index.rs +++ b/src/index.rs @@ -125,6 +125,8 @@ impl Drop for Indexer { /// # Examples /// /// ``` +/// use arrayfire::{Dim4, Seq, index, randu, print}; +/// let dims = Dim4::new(&[5, 5, 1, 1]); /// let a = randu::(dims).unwrap(); /// let seqs = &[Seq::new(1.0, 3.0, 1.0), Seq::default()]; /// let sub = index(&a, seqs).unwrap(); @@ -153,10 +155,12 @@ pub fn index(input: &Array, seqs: &[Seq]) -> Result /// # Examples /// /// ``` +/// use arrayfire::{Dim4, randu, row, print}; +/// let dims = Dim4::new(&[5, 5, 1, 1]); /// let a = randu::(dims).unwrap(); /// println!("Grab last row of the random matrix"); /// print(&a); -/// print(&row(&a, num_rows - 1).unwrap()); +/// print(&row(&a, 4).unwrap()); /// ``` #[allow(dead_code)] pub fn row(input: &Array, row_num: u64) -> Result { @@ -189,10 +193,12 @@ pub fn set_rows(input: &Array, new_rows: &Array, first: u64, last: u64) -> Resul /// # Examples /// /// ``` +/// use arrayfire::{Dim4, randu, col, print}; +/// let dims = Dim4::new(&[5, 5, 1, 1]); /// let a = randu::(dims).unwrap(); /// println!("Grab last col of the random matrix"); /// print(&a); -/// print(&row(&a, num_cols - 1).unwrap()); +/// print(&col(&a, 4).unwrap()); /// ``` #[allow(dead_code)] pub fn col(input: &Array, col_num: u64) -> Result { @@ -287,6 +293,7 @@ pub fn lookup(input: &Array, indices: &Array, seq_dim: i32) -> Result(lhs: &Array, seqs: &[Seq], rhs: &Array) -> Result< /// # Examples /// /// ``` +/// use arrayfire::{Array, Dim4, Seq, print, randu, index_gen, Indexer}; /// let values: &[f32] = &[1.0, 2.0, 3.0]; /// let indices = Array::new(values, Dim4::new(&[3, 1, 1, 1])).unwrap(); /// let seq4gen = Seq::new(0.0, 2.0, 1.0); @@ -370,6 +378,7 @@ pub fn index_gen(input: &Array, indices: Indexer) -> Result { /// # Examples /// /// ``` +/// use arrayfire::{Array, Dim4, Seq, print, randu, constant, Indexer, assign_gen}; /// let values: &[f32] = &[1.0, 2.0, 3.0]; /// let indices = Array::new(values, Dim4::new(&[3, 1, 1, 1])).unwrap(); /// let seq4gen = Seq::new(0.0, 2.0, 1.0); @@ -390,7 +399,7 @@ pub fn index_gen(input: &Array, indices: Indexer) -> Result { /// idxrs.set_index(&indices, 0, None); // 2nd parameter is indexing dimension /// idxrs.set_index(&seq4gen, 1, Some(false)); // 3rd parameter indicates batch operation /// -/// let sub2 = assign_gen(&a, idxrs, &b).unwrap(); +/// let sub2 = assign_gen(&a, &idxrs, &b).unwrap(); /// println!("a(indices, seq(0, 2, 1))"); print(&sub2); /// // [5 3 1 1] /// // 0.0000 0.2190 0.3835 diff --git a/src/macros.rs b/src/macros.rs index 83bbc4c5d..03310637a 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -36,12 +36,20 @@ /// # Examples /// /// ``` -/// mem_info!("Here"); +/// # #[macro_use(mem_info)] extern crate arrayfire; +/// # fn main() { +/// use arrayfire::{Dim4, device_mem_info, print, randu}; +/// +/// let dims = Dim4::new(&[5, 5, 1, 1]); +/// let a = randu::(dims).unwrap(); +/// print(&a); +/// mem_info!("Hello!"); +/// # } /// ``` /// /// Sample Output: /// -/// ``` +/// ```ignore /// AF Memory: Here /// Allocated [ Bytes | Buffers ] = [ 4096 | 4 ] /// In Use [ Bytes | Buffers ] = [ 2048 | 2 ] @@ -66,11 +74,15 @@ macro_rules! mem_info { /// /// ``` /// # #[macro_use] extern crate arrayfire; +/// /// # fn main() { -/// let a = &randu::(Dim4::new(&[5, 3, 1, 1])).unwrap(); -/// let b = &randu::(Dim4::new(&[5, 3, 1, 1])).unwrap(); -/// let c = &randu::(Dim4::new(&[5, 3, 1, 1])).unwrap(); -/// let d = join_many![2; a, b, c]; +/// use arrayfire::{Dim4, join_many, print, randu}; +/// +/// let a = &randu::(Dim4::new(&[5, 3, 1, 1])).unwrap(); +/// let b = &randu::(Dim4::new(&[5, 3, 1, 1])).unwrap(); +/// let c = &randu::(Dim4::new(&[5, 3, 1, 1])).unwrap(); +/// let d = join_many![2; a, b, c]; +/// print(&d.unwrap()); /// # } /// ``` /// From 69f1a65cdc75d7aee559b59398422b5fde875a03 Mon Sep 17 00:00:00 2001 From: pradeep Date: Mon, 21 Mar 2016 17:04:58 +0530 Subject: [PATCH 12/37] Add build badges from ci to README --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index fa0bdf883..3944d55ed 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,7 @@ # Arrayfire Rust Bindings [![Join the chat at https://gitter.im/arrayfire/arrayfire-rust](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/arrayfire/arrayfire-rust?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +| Linux | Windows | OSX | +|:-------:|:-------:|:---:| +| [![Build Status](http://ci.arrayfire.org/buildStatus/icon?job=arrayfire-wrappers/rust-linux)](http://ci.arrayfire.org/view/All/job/arrayfire-wrappers/job/rust-linux/) | [![Build Status](http://ci.arrayfire.org/buildStatus/icon?job=arrayfire-wrappers/rust-windows)](http://ci.arrayfire.org/view/All/job/arrayfire-wrappers/job/rust-windows/) | [![Build Status](http://ci.arrayfire.org/buildStatus/icon?job=arrayfire-wrappers/rust-osx)](http://ci.arrayfire.org/view/All/job/arrayfire-wrappers/job/rust-osx/) | [ArrayFire](https://github.com/arrayfire/arrayfire) is a high performance library for parallel computing with an easy-to-use API. It enables users to write scientific computing code that is portable across CUDA, OpenCL and CPU devices. This project provides Rust bindings for the ArrayFire library. The wrapper is currently compliant with ArrayFire 3.2 API. If you find any bugs, please report them [here](https://github.com/arrayfire/arrayfire-rust/issues). From 58a9fd9d73813db6393d27f0e96beab735347cae Mon Sep 17 00:00:00 2001 From: Jason Ramapuram Date: Fri, 25 Mar 2016 11:10:38 +0100 Subject: [PATCH 13/37] unwrap index printing --- src/index.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.rs b/src/index.rs index fe5071231..00aeeb437 100644 --- a/src/index.rs +++ b/src/index.rs @@ -131,7 +131,7 @@ impl Drop for Indexer { /// let seqs = &[Seq::new(1.0, 3.0, 1.0), Seq::default()]; /// let sub = index(&a, seqs).unwrap(); /// println!("a(seq(1, 3, 1), span)"); -/// print(&sub); +/// print(&sub).unwrap(); /// ``` pub fn index(input: &Array, seqs: &[Seq]) -> Result where c_double: From From 96bccdf72a8858cfd6f9ea655f88638c045e0aac Mon Sep 17 00:00:00 2001 From: Jason Ramapuram Date: Sat, 26 Mar 2016 12:39:32 +0100 Subject: [PATCH 14/37] more unused fixes --- src/array.rs | 3 ++- src/index.rs | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/array.rs b/src/array.rs index 1d0c39d43..c83a1cea1 100644 --- a/src/array.rs +++ b/src/array.rs @@ -119,9 +119,10 @@ impl Array { /// # Examples /// /// ``` - /// use arrayfire::{Array, Dim4}; + /// use arrayfire::{Array, Dim4, print}; /// let values: &[f32] = &[1.0, 2.0, 3.0]; /// let indices = Array::new(values, Dim4::new(&[3, 1, 1, 1])).unwrap(); + /// print(&indices).unwrap(); /// ``` #[allow(unused_mut)] pub fn new(slice: &[T], dims: Dim4) -> Result { diff --git a/src/index.rs b/src/index.rs index 00aeeb437..ef70ff233 100644 --- a/src/index.rs +++ b/src/index.rs @@ -160,7 +160,7 @@ pub fn index(input: &Array, seqs: &[Seq]) -> Result /// let a = randu::(dims).unwrap(); /// println!("Grab last row of the random matrix"); /// print(&a); -/// print(&row(&a, 4).unwrap()); +/// print(&row(&a, 4).unwrap()).unwrap(); /// ``` #[allow(dead_code)] pub fn row(input: &Array, row_num: u64) -> Result { @@ -355,7 +355,7 @@ pub fn assign_seq(lhs: &Array, seqs: &[Seq], rhs: &Array) -> Result< /// idxrs.set_index(&seq4gen, 1, Some(false)); // 3rd parameter indicates batch operation /// /// let sub2 = index_gen(&a, idxrs).unwrap(); -/// println!("a(indices, seq(0, 2, 1))"); print(&sub2); +/// println!("a(indices, seq(0, 2, 1))"); print(&sub2).unwrap(); /// // [3 3 1 1] /// // 0.1315 0.0470 0.5194 /// // 0.7556 0.6789 0.8310 @@ -400,7 +400,7 @@ pub fn index_gen(input: &Array, indices: Indexer) -> Result { /// idxrs.set_index(&seq4gen, 1, Some(false)); // 3rd parameter indicates batch operation /// /// let sub2 = assign_gen(&a, &idxrs, &b).unwrap(); -/// println!("a(indices, seq(0, 2, 1))"); print(&sub2); +/// println!("a(indices, seq(0, 2, 1))"); print(&sub2).unwrap(); /// // [5 3 1 1] /// // 0.0000 0.2190 0.3835 /// // 2.0000 2.0000 2.0000 From 3c2f70cd790c2f814171b616de265eb93b0ad623 Mon Sep 17 00:00:00 2001 From: Jason Ramapuram Date: Sat, 26 Mar 2016 12:58:44 +0100 Subject: [PATCH 15/37] add unwrap for set_index calls --- src/index.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/index.rs b/src/index.rs index ef70ff233..9b9cc4c5b 100644 --- a/src/index.rs +++ b/src/index.rs @@ -351,8 +351,8 @@ pub fn assign_seq(lhs: &Array, seqs: &[Seq], rhs: &Array) -> Result< /// Ok(v) => v, /// Err(e) => panic!("{}",e), /// }; -/// idxrs.set_index(&indices, 0, None); // 2nd parameter is indexing dimension -/// idxrs.set_index(&seq4gen, 1, Some(false)); // 3rd parameter indicates batch operation +/// idxrs.set_index(&indices, 0, None).unwrap(); // 2nd parameter is indexing dimension +/// idxrs.set_index(&seq4gen, 1, Some(false)).unwrap(); // 3rd parameter indicates batch operation /// /// let sub2 = index_gen(&a, idxrs).unwrap(); /// println!("a(indices, seq(0, 2, 1))"); print(&sub2).unwrap(); @@ -396,8 +396,8 @@ pub fn index_gen(input: &Array, indices: Indexer) -> Result { /// Ok(v) => v, /// Err(e) => panic!("{}",e), /// }; -/// idxrs.set_index(&indices, 0, None); // 2nd parameter is indexing dimension -/// idxrs.set_index(&seq4gen, 1, Some(false)); // 3rd parameter indicates batch operation +/// idxrs.set_index(&indices, 0, None).unwrap(); // 2nd parameter is indexing dimension +/// idxrs.set_index(&seq4gen, 1, Some(false)).unwrap(); // 3rd parameter indicates batch operation /// /// let sub2 = assign_gen(&a, &idxrs, &b).unwrap(); /// println!("a(indices, seq(0, 2, 1))"); print(&sub2).unwrap(); From fe4b481edf219cc149d8e32266e80d3eb8792673 Mon Sep 17 00:00:00 2001 From: Jason Ramapuram Date: Wed, 30 Mar 2016 02:47:55 +0200 Subject: [PATCH 16/37] Add support for partialeq & debug to dim4 Very annoying doing: ```rust if arr.dims().unwrap().get().clone() == arr2.dims().unwrap().get().clone() {} ``` --- src/dim4.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dim4.rs b/src/dim4.rs index 5a9a721a6..29eda2375 100644 --- a/src/dim4.rs +++ b/src/dim4.rs @@ -2,7 +2,7 @@ use std::fmt; use std::ops::Index; /// Dim4 is used to store [Array](./struct.Array.html) dimensions -#[derive(Copy, Clone)] +#[derive(Copy, Clone, PartialEq, Debug)] pub struct Dim4 { dims: [u64; 4], } From f22a5fb799a5b8a2892a10cdee762992970ced50 Mon Sep 17 00:00:00 2001 From: pradeep Date: Mon, 4 Apr 2016 16:18:37 +0530 Subject: [PATCH 17/37] add af_print macro Fixes #63 --- examples/helloworld.rs | 28 +++++++++++++--------------- src/macros.rs | 28 ++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 15 deletions(-) diff --git a/examples/helloworld.rs b/examples/helloworld.rs index e9b1d7dd5..0539e3190 100644 --- a/examples/helloworld.rs +++ b/examples/helloworld.rs @@ -1,3 +1,4 @@ +#[macro_use(af_print)] extern crate arrayfire as af; use af::*; @@ -14,12 +15,11 @@ fn main() { let dims = Dim4::new(&[num_rows, num_cols, 1, 1]); - println!("Create a 5-by-3 matrix of random floats on the GPU"); let a = match randu::(dims) { Ok(value) => value, Err(error) => panic!("{}", error), }; - print(&a); + af_print!("Create a 5-by-3 matrix of random floats on the GPU", a); println!("Element-wise arithmetic"); let b = sin(&a) @@ -34,17 +34,17 @@ fn main() { .unwrap(); let b3 = ! &a; - println!("sin(a) + 1.5 => "); print(&b); - println!("sin(a) + cos(a) => "); print(&b2); - println!("!a => "); print(&b3); + af_print!("sin(a) + 1.5 => ", b); + af_print!("sin(a) + cos(a) => ", b2); + af_print!("!a => ", b3); let test = &a + &b; - println!("a + b"); print(&test); + af_print!("a + b", test); // Index array using sequences let seqs = &[Seq::new(1u32, 3, 1), Seq::default()]; let sub = index(&a, seqs).unwrap(); - println!("a(seq(1,3,1), span)"); print(&sub); + af_print!("a(seq(1,3,1), span)", sub); //Index array using array and sequence let seq4gen = Seq::new(0u32, 2, 1); @@ -57,7 +57,7 @@ fn main() { idxrs.set_index(&seq4gen, 1, Some(false)); let sub2 = index_gen(&a, idxrs).unwrap(); - println!("a(indices, seq(0, 2, 1))"); print(&sub2); + af_print!("a(indices, seq(0, 2, 1))", sub2); // printf("Negate the first three elements of second column\n"); // B(seq(0, 2), 1) = B(seq(0, 2), 1) * -1; @@ -71,17 +71,16 @@ fn main() { print(&row(&a, num_rows - 1).unwrap()); print(&col(&a, num_cols - 1).unwrap()); - println!("Set last row to 1's"); let r_dims = Dim4::new(&[3, 1, 1, 1]); let r_input: [f32; 3] = [1.0, 1.0, 1.0]; let r = Array::new(&r_input, r_dims).unwrap(); - print(&set_row(&a, &r, num_rows - 1).unwrap()); + let ur = set_row(&a, &r, num_rows - 1).unwrap(); + af_print!("Set last row to 1's", ur); - println!("Create 2-by-3 matrix from host data"); let d_dims = Dim4::new(&[2, 3, 1, 1]); let d_input: [i32; 6] = [1, 2, 3, 4, 5, 6]; - let d = &Array::new(&d_input, d_dims).unwrap(); - print(d); + let d = Array::new(&d_input, d_dims).unwrap(); + af_print!("Create 2-by-3 matrix from host data", d); // printf("Copy last column onto first\n"); // D.col(0) = D.col(end); @@ -95,8 +94,7 @@ fn main() { print(&x.1); }); - println!("u8 constant array"); let u8_cnst = &constant(1 as u8, dims).unwrap(); - print(u8_cnst); + af_print!("u8 constant array", u8_cnst); println!("Is u8_cnst array float precision type ? {}", u8_cnst.is_single().unwrap()); } diff --git a/src/macros.rs b/src/macros.rs index 03310637a..213be2e6d 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -103,3 +103,31 @@ macro_rules! join_many { } }; } + +/// Print given message before printing out the Array to standard output +/// +/// # Examples +/// +/// ``` +/// # #[macro_use] extern crate arrayfire; +/// +/// # fn main() { +/// use arrayfire::{Dim4, print, randu}; +/// let dims = Dim4::new(&[3, 1, 1, 1]); +/// let a = match randu::(dims) { +/// Ok(value) => value, +/// Err(error) => panic!("{}", error), +/// }; +/// af_print!("Create a 5-by-3 matrix of random floats on the GPU", a); +/// # } +/// ``` +/// +#[macro_export] +macro_rules! af_print { + [$msg: expr, $x: ident] => { + { + println!("{}", $msg); + print(&$x).unwrap(); + } + }; +} From e403475d8fca7529d7eb4c304814d564e1fa666e Mon Sep 17 00:00:00 2001 From: Jason Ramapuram Date: Wed, 20 Apr 2016 11:48:16 +0200 Subject: [PATCH 18/37] add clone and partialeq to all enums --- src/defines.rs | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/defines.rs b/src/defines.rs index 8ed0e1687..e6274af9a 100644 --- a/src/defines.rs +++ b/src/defines.rs @@ -4,7 +4,7 @@ use std::fmt::Error as FmtError; /// Error codes #[repr(C)] -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, PartialEq)] pub enum AfError { /// The function returned successfully SUCCESS = 0, @@ -106,7 +106,7 @@ impl Error for AfError { } /// Types of Array data type -#[derive(Copy, Clone)] +#[derive(Clone, Copy, Debug, PartialEq)] pub enum Aftype { /// 32 bit float F32 = 0, @@ -135,7 +135,7 @@ pub enum Aftype { } /// Dictates the interpolation method to be used by a function -#[derive(Copy, Clone)] +#[derive(Clone, Copy, Debug, PartialEq)] pub enum InterpType { /// Nearest Neighbor interpolation method NEAREST = 0, @@ -148,7 +148,7 @@ pub enum InterpType { } /// Helps determine how to pad kernels along borders -#[derive(Copy, Clone)] +#[derive(Clone, Copy, Debug, PartialEq)] pub enum BorderType { /// Pad using zeros ZERO = 0, @@ -157,7 +157,7 @@ pub enum BorderType { } /// Used by `regions` function to identify type of connectivity -#[derive(Copy, Clone)] +#[derive(Clone, Copy, Debug, PartialEq)] pub enum Connectivity { /// North-East-South-West (N-E-S-W) connectivity from given pixel/point FOUR = 4, @@ -166,7 +166,7 @@ pub enum Connectivity { } /// Helps determine the size of output of convolution -#[derive(Copy, Clone)] +#[derive(Clone, Copy, Debug, PartialEq)] pub enum ConvMode { /// Default convolution mode where output size is same as input size DEFAULT = 0, @@ -175,7 +175,7 @@ pub enum ConvMode { } /// Helps determine if convolution is in Spatial or Frequency domain -#[derive(Copy, Clone)] +#[derive(Clone, Copy, Debug, PartialEq)] pub enum ConvDomain { /// ArrayFire chooses whether the convolution will be in spatial domain or frequency domain AUTO = 0, @@ -186,7 +186,7 @@ pub enum ConvDomain { } /// Error metric used by `matchTemplate` function -#[derive(Copy, Clone)] +#[derive(Clone, Copy, Debug, PartialEq)] pub enum MatchType { /// Sum of Absolute Differences SAD = 0, @@ -209,7 +209,7 @@ pub enum MatchType { } /// Identify the color space of given image(Array) -#[derive(Copy, Clone)] +#[derive(Clone, Copy, Debug, PartialEq)] pub enum ColorSpace { /// Grayscale color space GRAY = 0, @@ -220,7 +220,7 @@ pub enum ColorSpace { } /// Helps determine the type of a Matrix -#[derive(Copy, Clone)] +#[derive(Clone, Copy, Debug, PartialEq)] pub enum MatProp { /// Default (no-op) NONE, @@ -248,7 +248,7 @@ pub enum MatProp { /// Norm type #[allow(non_camel_case_types)] -#[derive(Copy, Clone)] +#[derive(Clone, Copy, Debug, PartialEq)] pub enum NormType { /// Treats input as a vector and return sum of absolute values VECTOR_1 = 0, @@ -270,7 +270,7 @@ pub enum NormType { /// Dictates what color map is used for Image rendering #[repr(C)] -#[derive(Copy, Clone)] +#[derive(Clone, Copy, Debug, PartialEq)] pub enum ColorMap { /// Default color map is grayscale range [0-1] DEFAULT = 0, @@ -290,7 +290,7 @@ pub enum ColorMap { /// YCbCr Standards #[repr(C)] -#[derive(Copy, Clone)] +#[derive(Clone, Copy, Debug, PartialEq)] pub enum YCCStd { /// ITU-R BT.601 (formerly CCIR 601) standard YCC_601 = 601, @@ -302,7 +302,7 @@ pub enum YCCStd { /// Homography type #[repr(C)] -#[derive(Copy, Clone)] +#[derive(Clone, Copy, Debug, PartialEq)] pub enum HomographyType { /// RANdom SAmple Consensus algorithm RANSAC = 0, @@ -312,7 +312,7 @@ pub enum HomographyType { /// Plotting markers #[repr(C)] -#[derive(Copy, Clone)] +#[derive(Clone, Copy, Debug, PartialEq)] pub enum MarkerType { NONE = 0, POINT = 1, From 755544e6cf2a0c292acf78eeaa11bf4e7d8ab38a Mon Sep 17 00:00:00 2001 From: Mitchell Metcalfe Date: Sat, 23 Apr 2016 19:46:02 +1000 Subject: [PATCH 19/37] Retain the arrays returned from Features's accessors (#68) * Retain the arrays returned from Features's accessors --- src/vision/mod.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/vision/mod.rs b/src/vision/mod.rs index c61c7da6f..30148d4d8 100644 --- a/src/vision/mod.rs +++ b/src/vision/mod.rs @@ -1,5 +1,6 @@ extern crate libc; +use std::mem; use array::Array; use defines::{AfError, HomographyType, MatchType}; use util::HasAfEnum; @@ -78,8 +79,13 @@ macro_rules! feat_func_def { unsafe { let mut temp: i64 = 0; let err_val = $ffi_name(&mut temp as MutAfArray, self.feat as Feat); + + let temp_array = Array::from(temp); + let retained = temp_array.clone(); + unsafe { mem::forget(temp_array); } + match err_val { - 0 => Ok(Array::from(temp)), + 0 => Ok(retained), _ => Err(AfError::from(err_val)), } } From d737dd4e827b4d1b25ab35c1e32d706c29b2d153 Mon Sep 17 00:00:00 2001 From: pradeep Date: Wed, 27 Apr 2016 21:00:46 +0530 Subject: [PATCH 20/37] Replace Result returns in API with callback based error handling With this change, all functions and operations return appropriate values/objects instead of wrapping those values inside a Result<> object. All errors reported by FFI calls are handled by a global error handling function that is registered by a call to the function `register_error_handler` that accepts either a closure or a function. By default, the error handler is set to a internal function that prints the error message to standard output and then panics. --- Cargo.toml | 2 +- examples/helloworld.rs | 53 +++----- examples/histogram.rs | 36 ++---- examples/pi.rs | 17 +-- examples/snow.rs | 10 +- examples/unified.rs | 42 +++---- src/algorithm/mod.rs | 129 ++++++++------------ src/arith/mod.rs | 65 +++++----- src/array.rs | 149 +++++++++-------------- src/backend.rs | 51 ++++---- src/blas/mod.rs | 32 ++--- src/data/mod.rs | 220 +++++++++++++--------------------- src/defines.rs | 4 +- src/device/mod.rs | 102 ++++++---------- src/error.rs | 33 +++++ src/graphics.rs | 121 ++++++------------- src/image/mod.rs | 266 +++++++++++++++-------------------------- src/index.rs | 198 +++++++++++++----------------- src/lapack/mod.rs | 118 +++++++----------- src/lib.rs | 5 +- src/macros.rs | 19 ++- src/signal/mod.rs | 202 +++++++++++-------------------- src/statistics/mod.rs | 67 ++++------- src/util.rs | 43 +++---- src/vision/mod.rs | 114 +++++++----------- 25 files changed, 818 insertions(+), 1280 deletions(-) create mode 100644 src/error.rs diff --git a/Cargo.toml b/Cargo.toml index bbd9a1a14..3aab53cc5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ libc = "0.1.10" num = "0.1.27" time = "0.1.32" -[build-dependencies.rustc-serialize] +[build-dependencies] rustc-serialize = "0.3.16" [lib] diff --git a/examples/helloworld.rs b/examples/helloworld.rs index 0539e3190..ed79171e7 100644 --- a/examples/helloworld.rs +++ b/examples/helloworld.rs @@ -11,27 +11,17 @@ fn main() { let num_rows: u64 = 5; let num_cols: u64 = 3; let values: &[f32] = &[1.0, 2.0, 3.0]; - let indices = Array::new(values, Dim4::new(&[3, 1, 1, 1])).unwrap(); + let indices = Array::new(values, Dim4::new(&[3, 1, 1, 1])); let dims = Dim4::new(&[num_rows, num_cols, 1, 1]); - let a = match randu::(dims) { - Ok(value) => value, - Err(error) => panic!("{}", error), - }; + let a = randu::(dims); af_print!("Create a 5-by-3 matrix of random floats on the GPU", a); println!("Element-wise arithmetic"); - let b = sin(&a) - .and_then(|x| add(&x, &1.5, false)) - .unwrap(); + let b = add(&sin(&a), &1.5, false); - let b2 = sin(&a). - and_then(|x| { - cos(&a) - .and_then(|y| add(&x, &y, false)) - }) - .unwrap(); + let b2 = add(&sin(&a), &cos(&a), false); let b3 = ! &a; af_print!("sin(a) + 1.5 => ", b); @@ -43,20 +33,17 @@ fn main() { // Index array using sequences let seqs = &[Seq::new(1u32, 3, 1), Seq::default()]; - let sub = index(&a, seqs).unwrap(); + let sub = index(&a, seqs); af_print!("a(seq(1,3,1), span)", sub); //Index array using array and sequence let seq4gen = Seq::new(0u32, 2, 1); - let mut idxrs = match Indexer::new() { - Ok(v) => v, - Err(e) => panic!("{}",e), - }; + let mut idxrs = Indexer::new(); idxrs.set_index(&indices, 0, None); idxrs.set_index(&seq4gen, 1, Some(false)); - let sub2 = index_gen(&a, idxrs).unwrap(); + let sub2 = index_gen(&a, idxrs); af_print!("a(indices, seq(0, 2, 1))", sub2); // printf("Negate the first three elements of second column\n"); @@ -64,22 +51,22 @@ fn main() { // af_print(B); println!("Fourier transform the result"); - fft(&b, 1.0, 0).map(|x| print(&x)); + print(&fft(&b, 1.0, 0)); println!("Grab last row & col of the random matrix"); print(&a); - print(&row(&a, num_rows - 1).unwrap()); - print(&col(&a, num_cols - 1).unwrap()); + print(&row(&a, num_rows - 1)); + print(&col(&a, num_cols - 1)); let r_dims = Dim4::new(&[3, 1, 1, 1]); let r_input: [f32; 3] = [1.0, 1.0, 1.0]; - let r = Array::new(&r_input, r_dims).unwrap(); - let ur = set_row(&a, &r, num_rows - 1).unwrap(); + let r = Array::new(&r_input, r_dims); + let ur = set_row(&a, &r, num_rows - 1); af_print!("Set last row to 1's", ur); let d_dims = Dim4::new(&[2, 3, 1, 1]); let d_input: [i32; 6] = [1, 2, 3, 4, 5, 6]; - let d = Array::new(&d_input, d_dims).unwrap(); + let d = Array::new(&d_input, d_dims); af_print!("Create 2-by-3 matrix from host data", d); // printf("Copy last column onto first\n"); @@ -88,13 +75,11 @@ fn main() { // // Sort A println!("Sort A and print sorted array and corresponding indices"); - sort_index(&a, 0, true) - .map(| x | { - print(&x.0); - print(&x.1); - }); + let x = sort_index(&a, 0, true); + print(&x.0); + print(&x.1); - let u8_cnst = &constant(1 as u8, dims).unwrap(); + let u8_cnst = &constant(1 as u8, dims); af_print!("u8 constant array", u8_cnst); - println!("Is u8_cnst array float precision type ? {}", u8_cnst.is_single().unwrap()); -} + println!("Is u8_cnst array float precision type ? {}", u8_cnst.is_single()); +} \ No newline at end of file diff --git a/examples/histogram.rs b/examples/histogram.rs index 5a32b6820..e17f243b5 100644 --- a/examples/histogram.rs +++ b/examples/histogram.rs @@ -13,34 +13,22 @@ fn main() { let assets_dir = PathBuf::from(&env::var("CARGO_MANIFEST_DIR").unwrap()) .join("arrayfire").join("assets").join("examples").join("images"); - let img_wnd = match Window::new(480, 640, String::from("Input Image")) { - Ok(v) => { v.set_position(100, 100).unwrap(); v }, - Err(e)=> panic!("Window creation failed, exiting: {}", e), - }; - - let hst_wnd = match Window::new(512, 512, String::from("Input Image Histogram")) { - Ok(v) => { v.set_position(600, 100).unwrap(); v }, - Err(e)=> panic!("Window creation failed, exiting: {}", e), - }; - - let (man, hst) = match load_image(format!("{}/man.jpg", assets_dir.display()), false) { - Ok(v) => match histogram(&v, 256, 0.0, 255.0) { - Ok(h) => (v, h), - Err(e)=> panic!("Histogram computation failed, exiting: {}", e), - }, - Err(e)=> panic!("Image loading failed, exiting: {}", e), - }; - - let disp_img = man.dims() - .and_then(|x| constant(255 as f32, x)) - .and_then(|x| div(&man, &x, false)) - .unwrap(); + let img_wnd = Window::new(480, 640, String::from("Input Image")); + img_wnd.set_position(100, 100); + + let hst_wnd = Window::new(512, 512, String::from("Input Image Histogram")); + hst_wnd.set_position(600, 100); + + let man = load_image(format!("{}/man.jpg", assets_dir.display()), false); + let hst = histogram(&man, 256, 0.0, 255.0); + + let disp_img = div(&man, &constant(255 as f32, man.dims()), false); loop { img_wnd.draw_image(&disp_img, None); hst_wnd.draw_hist(&hst, 0.0, 255.0, None); - if img_wnd.is_closed().unwrap() == true { break; } - if hst_wnd.is_closed().unwrap() == true { break; } + if img_wnd.is_closed() == true { break; } + if hst_wnd.is_closed() == true { break; } } } diff --git a/examples/pi.rs b/examples/pi.rs index 744063e99..a32b94c63 100644 --- a/examples/pi.rs +++ b/examples/pi.rs @@ -13,20 +13,21 @@ fn main() { let samples = 20_000_000; let dims = Dim4::new(&[samples, 1, 1, 1]); - let x = &randu::(dims).unwrap(); - let y = &randu::(dims).unwrap(); + let x = &randu::(dims); + let y = &randu::(dims); let start = PreciseTime::now(); mem_info!("Before benchmark"); for bench_iter in 0..100 { - let pi_val = add(&mul(x, x, false).unwrap(), &mul(y, y, false).unwrap(), false) - .and_then( |z| sqrt(&z) ) - .and_then( |z| le(&z, &constant(1, dims).unwrap(), false) ) - .and_then( |z| sum_all(&z) ) - .map( |z| z.0 * 4.0/(samples as f64) ) - .unwrap(); + let xsqrd = &mul(x, x, false); + let ysqrd = &mul(y, y, false); + let xplusy = &add(xsqrd, ysqrd, false); + let root = &sqrt(xplusy); + let cnst = &constant(1, dims); + let (real, imag) = sum_all(&le(root, cnst, false)); + let pi_val = real*4.0/(samples as f64); } let end = PreciseTime::now(); diff --git a/examples/snow.rs b/examples/snow.rs index f51dd137d..bdeb394f6 100644 --- a/examples/snow.rs +++ b/examples/snow.rs @@ -8,17 +8,13 @@ fn main() { set_device(0); info(); - let wnd = match Window::new(1280, 720, String::from("Snow")) { - Ok(v) => v, - Err(e)=> panic!("Window creation failed, exiting"), - }; + let wnd = Window::new(1280, 720, String::from("Snow")); let dims = Dim4::new(&[1280, 720, 3, 1]); loop { - randu::(dims).as_ref() - .map(|arr| wnd.draw_image(arr, None)); + wnd.draw_image(&randu::(dims), None); - if wnd.is_closed().unwrap() == true { break; } + if wnd.is_closed() == true { break; } } } diff --git a/examples/unified.rs b/examples/unified.rs index 6a5d7fce5..bb617caa1 100644 --- a/examples/unified.rs +++ b/examples/unified.rs @@ -11,46 +11,34 @@ fn test_backend(){ let dims = Dim4::new(&[num_rows, num_cols, 1, 1]); println!("Create a 10-by-10 matrix of random floats on the compute device"); - let a = match randu::(dims) { - Ok(value) => value, - Err(error) => panic!("{}", error), - }; + let a = randu::(dims); print(&a); } #[allow(unused_must_use)] fn main() { - println!("There are {:?} available backends", get_backend_count().unwrap()); - let available = get_available_backends().unwrap(); + println!("There are {:?} available backends", get_backend_count()); + let available = get_available_backends(); - if available.contains(&Backend::CPU){ + if available.contains(&Backend::CPU) { println!("Evaluating CPU Backend..."); - let err = set_backend(Backend::CPU); - println!("There are {} CPU compute devices", device_count().unwrap()); - match err { - Ok(_) => test_backend(), - Err(e) => println!("CPU backend error: {}", e), - }; + set_backend(Backend::CPU); + println!("There are {} CPU compute devices", device_count()); + test_backend(); } - if available.contains(&Backend::CUDA){ + if available.contains(&Backend::CUDA) { println!("Evaluating CUDA Backend..."); - let err = set_backend(Backend::CUDA); - println!("There are {} CUDA compute devices", device_count().unwrap()); - match err { - Ok(_) => test_backend(), - Err(e) => println!("CUDA backend error: {}", e), - }; + set_backend(Backend::CUDA); + println!("There are {} CUDA compute devices", device_count()); + test_backend(); } - if available.contains(&Backend::OPENCL){ + if available.contains(&Backend::OPENCL) { println!("Evaluating OpenCL Backend..."); - let err = set_backend(Backend::OPENCL); - println!("There are {} OpenCL compute devices", device_count().unwrap()); - match err { - Ok(_) => test_backend(), - Err(e) => println!("OpenCL backend error: {}", e), - }; + set_backend(Backend::OPENCL); + println!("There are {} OpenCL compute devices", device_count()); + test_backend(); } } diff --git a/src/algorithm/mod.rs b/src/algorithm/mod.rs index 62d3f983b..98284daed 100644 --- a/src/algorithm/mod.rs +++ b/src/algorithm/mod.rs @@ -2,6 +2,7 @@ extern crate libc; use array::Array; use defines::AfError; +use error::HANDLE_ERROR; use self::libc::{c_int, c_uint, c_double}; type MutAfArray = *mut self::libc::c_longlong; @@ -60,15 +61,13 @@ macro_rules! dim_reduce_func_def { /// /// Reduced Array #[allow(unused_mut)] - pub fn $fn_name(input: &Array, dim: i32) -> Result { + pub fn $fn_name(input: &Array, dim: i32) -> Array { unsafe { let mut temp: i64 = 0; let err_val = $ffi_name(&mut temp as MutAfArray, input.get() as AfArray, dim as c_int); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } ) @@ -99,15 +98,13 @@ dim_reduce_func_def!(diff2, af_diff2); /// # Return Values /// /// Reduced Array -pub fn sum_nan(input: &Array, dim: i32, nanval: f64) -> Result { +pub fn sum_nan(input: &Array, dim: i32, nanval: f64) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_sum_nan(&mut temp as MutAfArray, input.get() as AfArray, dim as c_int, nanval as c_double); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -124,15 +121,13 @@ pub fn sum_nan(input: &Array, dim: i32, nanval: f64) -> Result { /// # Return Values /// /// Reduced Array -pub fn product_nan(input: &Array, dim: i32, nanval: f64) -> Result { +pub fn product_nan(input: &Array, dim: i32, nanval: f64) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_product_nan(&mut temp as MutAfArray, input.get() as AfArray, dim as c_int, nanval as c_double); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -149,16 +144,14 @@ macro_rules! all_reduce_func_def { /// A tuple of reduction result. For non-complex data type Arrays, second value of tuple is /// zero. #[allow(unused_mut)] - pub fn $fn_name(input: &Array) -> Result<(f64, f64), AfError> { + pub fn $fn_name(input: &Array) -> (f64, f64) { unsafe { let mut real: f64 = 0.0; let mut imag: f64 = 0.0; let err_val = $ffi_name(&mut real as MutDouble, &mut imag as MutDouble, input.get() as AfArray); - match err_val { - 0 => Ok((real, imag)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + (real, imag) } } ) @@ -186,16 +179,14 @@ all_reduce_func_def!(count_all, af_count_all); /// /// A tuple of reduction result. For non-complex data type Arrays, second value of tuple is /// zero. -pub fn sum_nan_all(input: &Array, val: f64) -> Result<(f64, f64), AfError> { +pub fn sum_nan_all(input: &Array, val: f64) -> (f64, f64) { unsafe { let mut real: f64 = 0.0; let mut imag: f64 = 0.0; let err_val = af_sum_nan_all(&mut real as MutDouble, &mut imag as MutDouble, input.get() as AfArray, val as c_double); - match err_val { - 0 => Ok((real, imag)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + (real, imag) } } @@ -213,16 +204,14 @@ pub fn sum_nan_all(input: &Array, val: f64) -> Result<(f64, f64), AfError> { /// /// A tuple of reduction result. For non-complex data type Arrays, second value of tuple is /// zero. -pub fn product_nan_all(input: &Array, val: f64) -> Result<(f64, f64), AfError> { +pub fn product_nan_all(input: &Array, val: f64) -> (f64, f64) { unsafe { let mut real: f64 = 0.0; let mut imag: f64 = 0.0; let err_val = af_product_nan_all(&mut real as MutDouble, &mut imag as MutDouble, input.get() as AfArray, val as c_double); - match err_val { - 0 => Ok((real, imag)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + (real, imag) } } @@ -241,16 +230,14 @@ macro_rules! dim_ireduce_func_def { /// /// The indices Array has the index of the result element along the reduction dimension. #[allow(unused_mut)] - pub fn $fn_name(input: &Array, dim: i32) -> Result<(Array, Array), AfError> { + pub fn $fn_name(input: &Array, dim: i32) -> (Array, Array) { unsafe { let mut temp: i64 = 0; let mut idx: i64 = 0; let err_val = $ffi_name(&mut temp as MutAfArray, &mut idx as MutAfArray, input.get() as AfArray, dim as c_int); - match err_val { - 0 => Ok((Array::from(temp), Array::from(idx))), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + (Array::from(temp), Array::from(idx)) } } ) @@ -275,17 +262,15 @@ macro_rules! all_ireduce_func_def { /// /// The third value of triplet is the index of result element from reduction operation. #[allow(unused_mut)] - pub fn $fn_name(input: &Array) -> Result<(f64, f64, u32), AfError> { + pub fn $fn_name(input: &Array) -> (f64, f64, u32) { unsafe { let mut real: f64 = 0.0; let mut imag: f64 = 0.0; let mut temp: u32 = 0; let err_val = $ffi_name(&mut real as MutDouble, &mut imag as MutDouble, &mut temp as MutUint, input.get() as AfArray); - match err_val { - 0 => Ok((real, imag, temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + (real, imag, temp) } } ) @@ -306,14 +291,12 @@ all_ireduce_func_def!(imax_all, af_imax_all); /// /// Array of indices where the input Array has non-zero values. #[allow(unused_mut)] -pub fn locate(input: &Array) -> Result { +pub fn locate(input: &Array) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_where(&mut temp as MutAfArray, input.get() as AfArray); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -331,15 +314,13 @@ pub fn locate(input: &Array) -> Result { /// /// Sorted Array. #[allow(unused_mut)] -pub fn sort(input: &Array, dim: u32, ascending: bool) -> Result { +pub fn sort(input: &Array, dim: u32, ascending: bool) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_sort(&mut temp as MutAfArray, input.get() as AfArray, - dim as c_uint, ascending as c_int); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + dim as c_uint, ascending as c_int); + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -359,17 +340,15 @@ pub fn sort(input: &Array, dim: u32, ascending: bool) -> Result /// /// The second Array contains the original indices of the sorted values. #[allow(unused_mut)] -pub fn sort_index(input: &Array, dim: u32, ascending: bool) -> Result<(Array, Array), AfError> { +pub fn sort_index(input: &Array, dim: u32, ascending: bool) -> (Array, Array) { unsafe { let mut temp: i64 = 0; let mut idx: i64 = 0; let err_val = af_sort_index(&mut temp as MutAfArray, &mut idx as MutAfArray, input.get() as AfArray, dim as c_uint, ascending as c_int); - match err_val { - 0 => Ok((Array::from(temp), Array::from(idx))), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + (Array::from(temp), Array::from(idx)) } } @@ -393,17 +372,15 @@ pub fn sort_index(input: &Array, dim: u32, ascending: bool) -> Result<(Array, Ar /// The second Array contains the sorted values. #[allow(unused_mut)] pub fn sort_by_key(keys: &Array, vals: &Array, dim: u32, - ascending: bool) -> Result<(Array, Array), AfError> { + ascending: bool) -> (Array, Array) { unsafe { let mut temp: i64 = 0; let mut temp2: i64 = 0; let err_val = 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); - match err_val { - 0 => Ok((Array::from(temp), Array::from(temp2))), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + (Array::from(temp), Array::from(temp2)) } } @@ -418,15 +395,13 @@ pub fn sort_by_key(keys: &Array, vals: &Array, dim: u32, /// /// An Array of unique values from the input Array. #[allow(unused_mut)] -pub fn set_unique(input: &Array, is_sorted: bool) -> Result { +pub fn set_unique(input: &Array, is_sorted: bool) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_set_unique(&mut temp as MutAfArray, input.get() as AfArray, is_sorted as c_int); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -442,15 +417,13 @@ pub fn set_unique(input: &Array, is_sorted: bool) -> Result { /// /// An Array with union of the input sets #[allow(unused_mut)] -pub fn set_union(first: &Array, second: &Array, is_unique: bool) -> Result { +pub fn set_union(first: &Array, second: &Array, is_unique: bool) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_set_union(&mut temp as MutAfArray, first.get() as AfArray, - second.get() as AfArray, is_unique as c_int); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + second.get() as AfArray, is_unique as c_int); + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -466,14 +439,12 @@ pub fn set_union(first: &Array, second: &Array, is_unique: bool) -> Result Result { +pub fn set_intersect(first: &Array, second: &Array, is_unique: bool) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_set_intersect(&mut temp as MutAfArray, first.get() as AfArray, - second.get() as AfArray, is_unique as c_int); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + second.get() as AfArray, is_unique as c_int); + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } -} +} \ No newline at end of file diff --git a/src/arith/mod.rs b/src/arith/mod.rs index 982597255..5c2066ece 100644 --- a/src/arith/mod.rs +++ b/src/arith/mod.rs @@ -4,6 +4,7 @@ extern crate num; use dim4::Dim4; use array::Array; use defines::AfError; +use error::HANDLE_ERROR; use self::libc::{c_int}; use data::{constant, tile}; use self::num::Complex; @@ -102,10 +103,9 @@ impl<'f> Not for &'f Array { fn not(self) -> Array { unsafe { let mut temp: i64 = 0; - match af_not(&mut temp as MutAfArray, self.get() as AfArray) { - 0 => Array::from(temp), - _ => panic!("Negation of Array failed, please check input"), - } + let err_val = af_not(&mut temp as MutAfArray, self.get() as AfArray); + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } } @@ -113,14 +113,12 @@ impl<'f> Not for &'f Array { macro_rules! unary_func { ($fn_name: ident, $ffi_fn: ident) => ( #[allow(unused_mut)] - pub fn $fn_name(input: &Array) -> Result { + pub fn $fn_name(input: &Array) -> Array { unsafe { let mut temp: i64 = 0; let err_val = $ffi_fn(&mut temp as MutAfArray, input.get() as AfArray); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } ) @@ -171,16 +169,14 @@ 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) -> Result { + pub fn $fn_name(lhs: &Array, rhs: &Array) -> Array { unsafe { let mut temp: i64 = 0; let err_val = $ffi_fn(&mut temp as MutAfArray, lhs.get() as AfArray, rhs.get() as AfArray, 0); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } ) @@ -204,7 +200,7 @@ macro_rules! convertable_type_def { ($rust_type: ty) => ( impl Convertable for $rust_type { fn convert(&self) -> Array { - constant(*self, Dim4::new(&[1,1,1,1])).unwrap() + constant(*self, Dim4::new(&[1,1,1,1])) } } ) @@ -226,29 +222,27 @@ impl Convertable for Array { macro_rules! overloaded_binary_func { ($fn_name: ident, $help_name: ident, $ffi_name: ident) => ( - fn $help_name(lhs: &Array, rhs: &Array, batch: bool) -> Result { + fn $help_name(lhs: &Array, rhs: &Array, batch: bool) -> Array { unsafe { let mut temp: i64 = 0; let err_val = $ffi_name(&mut temp as MutAfArray, lhs.get() as AfArray, rhs.get() as AfArray, batch as c_int); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } - pub fn $fn_name (arg1: &T, arg2: &U, batch: bool) -> Result where T: Convertable, U: Convertable { + pub fn $fn_name (arg1: &T, arg2: &U, batch: bool) -> Array where T: Convertable, U: Convertable { let lhs = arg1.convert(); let rhs = arg2.convert(); - match (lhs.is_scalar().unwrap(), rhs.is_scalar().unwrap()) { + match (lhs.is_scalar(), rhs.is_scalar()) { ( true, false) => { - let l = tile(&lhs, rhs.dims().unwrap()).unwrap(); + let l = tile(&lhs, rhs.dims()); $help_name(&l, &rhs, batch) }, (false, true) => { - let r = tile(&rhs, lhs.dims().unwrap()).unwrap(); + let r = tile(&rhs, lhs.dims()); $help_name(&lhs, &r, batch) }, _ => $help_name(&lhs, &rhs, batch), @@ -283,14 +277,13 @@ macro_rules! arith_scalar_func { type Output = Array; fn $fn_name(self, rhs: $rust_type) -> Array { - let cnst_arr = constant(rhs, self.dims().unwrap()).unwrap(); + let cnst_arr = constant(rhs, self.dims()); unsafe { let mut temp: i64 = 0; - match $ffi_fn(&mut temp as MutAfArray, self.get() as AfArray, - cnst_arr.get() as AfArray, 0) { - 0 => Array::from(temp), - _ => panic!("Arithmetic operator on Array failed"), - } + let err_val = $ffi_fn(&mut temp as MutAfArray, self.get() as AfArray, + cnst_arr.get() as AfArray, 0); + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } } @@ -324,12 +317,10 @@ macro_rules! arith_func { fn $fn_name(self, rhs:&'f Array) -> Array { unsafe { let mut temp: i64 = 0; - match $ffi_fn(&mut temp as MutAfArray, - self.get() as AfArray, rhs.get() as AfArray, - 0) { - 0 => Array::from(temp), - _ => panic!("Failed to perform arithmetic operation"), - } + let err_val = $ffi_fn(&mut temp as MutAfArray, + self.get() as AfArray, rhs.get() as AfArray, 0); + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } } @@ -345,4 +336,4 @@ 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); +arith_func!(Shr, shr, af_bitshiftr); \ No newline at end of file diff --git a/src/array.rs b/src/array.rs index c83a1cea1..906d19cd3 100644 --- a/src/array.rs +++ b/src/array.rs @@ -1,7 +1,8 @@ extern crate libc; use dim4::Dim4; -use defines::{AfError, Aftype, Backend}; +use defines::{AfError, DType, Backend}; +use error::HANDLE_ERROR; use util::HasAfEnum; use self::libc::{uint8_t, c_void, c_int, c_uint, c_longlong}; @@ -100,14 +101,12 @@ pub struct Array { macro_rules! is_func { ($fn_name: ident, $ffi_fn: ident) => ( /// Checks if the Array is of specific format/data type. - pub fn $fn_name(&self) -> Result { + pub fn $fn_name(&self) -> bool { unsafe { let mut ret_val: i32 = 0; let err_val = $ffi_fn(&mut ret_val as *mut c_int, self.handle as AfArray); - match err_val { - 0 => Ok(ret_val>0), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + ret_val>0 } } ) @@ -121,11 +120,11 @@ impl Array { /// ``` /// use arrayfire::{Array, Dim4, print}; /// let values: &[f32] = &[1.0, 2.0, 3.0]; - /// let indices = Array::new(values, Dim4::new(&[3, 1, 1, 1])).unwrap(); - /// print(&indices).unwrap(); + /// let indices = Array::new(values, Dim4::new(&[3, 1, 1, 1])); + /// print(&indices); /// ``` #[allow(unused_mut)] - pub fn new(slice: &[T], dims: Dim4) -> Result { + pub fn new(slice: &[T], dims: Dim4) -> Array { unsafe { let aftype = T::get_af_dtype(); let mut temp: i64 = 0; @@ -134,10 +133,8 @@ impl Array { dims.ndims() as c_uint, dims.get().as_ptr() as * const c_longlong, aftype as uint8_t); - match err_val { - 0 => Ok(Array {handle: temp}), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -146,7 +143,7 @@ impl Array { /// The data pointed by the slice passed to this function can possibily be offseted using an additional `offset` parameter. #[allow(unused_mut)] pub fn new_strided(slice: &[T], offset: i64, - dims: Dim4, strides: Dim4) -> Result { + dims: Dim4, strides: Dim4) -> Array { unsafe { let aftype = T::get_af_dtype(); let mut temp: i64 = 0; @@ -157,10 +154,8 @@ impl Array { dims.get().as_ptr() as * const c_longlong, strides.get().as_ptr() as * const c_longlong, aftype as uint8_t); - match err_val { - 0 => Ok(Array {handle: temp}), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -170,15 +165,16 @@ impl Array { /// /// Returns an value of type `Backend` which indicates which backend /// was active when Array was created. - pub fn get_backend(&self) -> Result { + pub fn get_backend(&self) -> Backend { unsafe { let mut ret_val: i32 = 0; let err_val = af_get_backend_id(&mut ret_val as *mut c_int, self.handle as AfArray); + HANDLE_ERROR(AfError::from(err_val)); match (err_val, ret_val) { - (0, 1) => Ok(Backend::CPU), - (0, 2) => Ok(Backend::CUDA), - (0, 3) => Ok(Backend::OPENCL), - _ => Err(AfError::from(err_val)), + (0, 1) => Backend::CPU, + (0, 2) => Backend::CUDA, + (0, 3) => Backend::OPENCL, + _ => Backend::DEFAULT, } } } @@ -188,44 +184,37 @@ impl Array { /// # Return Values /// /// Return the device id on which Array was created. - pub fn get_device_id(&self) -> Result { + pub fn get_device_id(&self) -> i32 { unsafe { let mut ret_val: i32 = 0; let err_val = af_get_device_id(&mut ret_val as *mut c_int, self.handle as AfArray); - match err_val { - 0 => Ok(ret_val), - _ => Err(AfError::from(err_val)), - - } + HANDLE_ERROR(AfError::from(err_val)); + ret_val } } /// Returns the number of elements in the Array - pub fn elements(&self) -> Result { + pub fn elements(&self) -> i64 { unsafe { let mut ret_val: i64 = 0; let err_val = af_get_elements(&mut ret_val as MutAfArray, self.handle as AfArray); - match err_val { - 0 => Ok(ret_val), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + ret_val } } /// Returns the Array data type - pub fn get_type(&self) -> Result { + pub fn get_type(&self) -> DType { unsafe { let mut ret_val: u8 = 0; let err_val = af_get_type(&mut ret_val as *mut uint8_t, self.handle as AfArray); - match err_val { - 0 => Ok(Aftype::from(ret_val)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + DType::from(ret_val) } } /// Returns the dimensions of the Array - pub fn dims(&self) -> Result { + pub fn dims(&self) -> Dim4 { unsafe { let mut ret0: i64 = 0; let mut ret1: i64 = 0; @@ -234,15 +223,13 @@ impl Array { let err_val = af_get_dims(&mut ret0 as *mut DimT, &mut ret1 as *mut DimT, &mut ret2 as *mut DimT, &mut ret3 as *mut DimT, self.handle as AfArray); - match err_val { - 0 => Ok(Dim4::new(&[ret0 as u64, ret1 as u64, ret2 as u64, ret3 as u64])), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Dim4::new(&[ret0 as u64, ret1 as u64, ret2 as u64, ret3 as u64]) } } /// Returns the strides of the Array - pub fn strides(&self) -> Result { + pub fn strides(&self) -> Dim4 { unsafe { let mut ret0: i64 = 0; let mut ret1: i64 = 0; @@ -251,34 +238,28 @@ impl Array { let err_val = af_get_strides(&mut ret0 as *mut DimT, &mut ret1 as *mut DimT, &mut ret2 as *mut DimT, &mut ret3 as *mut DimT, self.handle as AfArray); - match err_val { - 0 => Ok(Dim4::new(&[ret0 as u64, ret1 as u64, ret2 as u64, ret3 as u64])), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Dim4::new(&[ret0 as u64, ret1 as u64, ret2 as u64, ret3 as u64]) } } /// Returns the number of dimensions of the Array - pub fn numdims(&self) -> Result { + pub fn numdims(&self) -> u32 { unsafe { let mut ret_val: u32 = 0; let err_val = af_get_numdims(&mut ret_val as *mut c_uint, self.handle as AfArray); - match err_val { - 0 => Ok(ret_val), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + ret_val } } /// Returns the offset to the pointer from where data begins - pub fn offset(&self) -> Result { + pub fn offset(&self) -> i64 { unsafe { let mut ret_val: i64 = 0; let err_val = af_get_offset(&mut ret_val as *mut DimT, self.handle as AfArray); - match err_val { - 0 => Ok(ret_val), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + ret_val } } @@ -288,38 +269,30 @@ impl Array { } /// Copies the data from the Array to the mutable slice `data` - pub fn host(&self, data: &mut [T]) -> Result<(), AfError> { + pub fn host(&self, data: &mut [T]) { unsafe { - let ret_val = af_get_data_ptr(data.as_mut_ptr() as *mut c_void, self.handle as AfArray); - match ret_val { - 0 => Ok(()), - _ => Err(AfError::from(ret_val)), - } + let err_val = af_get_data_ptr(data.as_mut_ptr() as *mut c_void, self.handle as AfArray); + HANDLE_ERROR(AfError::from(err_val)); } } /// Evaluates any pending lazy expressions that represent the data in the Array object - pub fn eval(&self) -> Result<(), AfError> { + pub fn eval(&self) { unsafe { - let ret_val = af_eval(self.handle as AfArray); - match ret_val { - 0 => Ok(()), - _ => Err(AfError::from(ret_val)), - } + let err_val = af_eval(self.handle as AfArray); + HANDLE_ERROR(AfError::from(err_val)); } } /// Makes an copy of the Array /// /// Internally, this is handled by reference counting - pub fn copy(&self) -> Result { + pub fn copy(&self) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_copy_array(&mut temp as MutAfArray, self.handle as AfArray); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -339,15 +312,13 @@ impl Array { is_func!(is_owner, af_is_owner); /// Cast the Array data type to `target_type` - pub fn cast(&self) -> Result { + pub fn cast(&self) -> Array { unsafe { let trgt_type = T::get_af_dtype(); let mut temp: i64 = 0; let err_val = af_cast(&mut temp as MutAfArray, self.handle as AfArray, trgt_type as uint8_t); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } } @@ -394,10 +365,7 @@ impl Drop for Array { /// use arrayfire::{Dim4, print, randu}; /// println!("Create a 5-by-3 matrix of random floats on the GPU"); /// let dims = Dim4::new(&[3, 1, 1, 1]); -/// let a = match randu::(dims) { -/// Ok(value) => value, -/// Err(error) => panic!("{}", error), -/// }; +/// let a = randu::(dims); /// print(&a); /// ``` /// @@ -411,12 +379,9 @@ impl Drop for Array { /// 0.9690 0.4702 0.3585 /// 0.9251 0.5132 0.6814 /// ``` -pub fn print(input: &Array) -> Result<(), AfError> { +pub fn print(input: &Array) { unsafe { - let ret_val = af_print_array(input.get() as AfArray); - match ret_val { - 0 => Ok(()), - _ => Err(AfError::from(ret_val)), - } + let err_val = af_print_array(input.get() as AfArray); + HANDLE_ERROR(AfError::from(err_val)); } -} +} \ No newline at end of file diff --git a/src/backend.rs b/src/backend.rs index 402ad297f..26d5b2ba0 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -1,6 +1,7 @@ extern crate libc; use defines::{AfError, Backend}; +use error::HANDLE_ERROR; use self::libc::{c_int, c_uint, uint8_t}; extern { @@ -15,61 +16,55 @@ extern { /// # Parameters /// /// - `backend` to which to switch to -pub fn set_backend(backend: Backend) -> Result<(), AfError> { +pub fn set_backend(backend: Backend) { unsafe { let err_val = af_set_backend(backend as uint8_t); - match err_val { - 0 => Ok(()), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); } } /// Get the available backend count #[allow(unused_mut)] -pub fn get_backend_count() -> Result { +pub fn get_backend_count() -> u32 { unsafe { let mut temp: u32 = 0; let err_val = af_get_backend_count(&mut temp as *mut c_uint); - match err_val { - 0 => Ok(temp), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + temp } } /// Get the available backends #[allow(unused_mut)] -pub fn get_available_backends() -> Result, AfError> { +pub fn get_available_backends() -> Vec { unsafe { let mut temp: i32 = 0; let err_val = af_get_available_backends(&mut temp as *mut c_int); - match err_val { - 0 => { - let mut b = Vec::new(); - if temp & 0b0100 == 0b0100 { b.push(Backend::OPENCL); } - if temp & 0b0010 == 0b0010 { b.push(Backend::CUDA); } - if temp & 0b0001 == 0b0001 { b.push(Backend::CPU); } - Ok(b) - }, - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + + let mut b = Vec::new(); + if temp & 0b0100 == 0b0100 { b.push(Backend::OPENCL); } + if temp & 0b0010 == 0b0010 { b.push(Backend::CUDA); } + if temp & 0b0001 == 0b0001 { b.push(Backend::CPU); } + + b } } /// Get current active backend #[allow(unused_mut)] -pub fn get_active_backend() -> Result { +pub fn get_active_backend() -> Backend { unsafe { let mut temp: i32 = 0; let err_val = af_get_active_backend(&mut temp as *mut c_int); + HANDLE_ERROR(AfError::from(err_val)); match (err_val, temp) { - (0, 0) => Ok(Backend::DEFAULT), - (0, 1) => Ok(Backend::CPU), - (0, 2) => Ok(Backend::CUDA), - (0, 4) => Ok(Backend::OPENCL), - _ => Err(AfError::from(err_val)), + (0, 0) => Backend::DEFAULT, + (0, 1) => Backend::CPU, + (0, 2) => Backend::CUDA, + (0, 4) => Backend::OPENCL, + _ => panic!("Invalid backend retrieved, undefined behavior."), } } -} +} \ No newline at end of file diff --git a/src/blas/mod.rs b/src/blas/mod.rs index 30c2163fe..49bad1c69 100644 --- a/src/blas/mod.rs +++ b/src/blas/mod.rs @@ -3,6 +3,7 @@ extern crate libc; use array::Array; use defines::AfError; use defines::MatProp; +use error::HANDLE_ERROR; use self::libc::{c_uint, c_int}; use util::to_u32; @@ -35,16 +36,14 @@ extern { /// The result Array of matrix multiplication #[allow(unused_mut)] pub fn matmul(lhs: &Array, rhs: &Array, - optlhs: MatProp, optrhs: MatProp) -> Result { + optlhs: MatProp, optrhs: MatProp) -> Array { unsafe { let mut temp: i64 = 0; let err_val = 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); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -64,16 +63,14 @@ pub fn matmul(lhs: &Array, rhs: &Array, /// The result of dot product. #[allow(unused_mut)] pub fn dot(lhs: &Array, rhs: &Array, - optlhs: MatProp, optrhs: MatProp) -> Result { + optlhs: MatProp, optrhs: MatProp) -> Array { unsafe { let mut temp: i64 = 0; let err_val = 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); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -89,15 +86,13 @@ pub fn dot(lhs: &Array, rhs: &Array, /// /// Transposed Array. #[allow(unused_mut)] -pub fn transpose(arr: &Array, conjugate: bool) -> Result { +pub fn transpose(arr: &Array, conjugate: bool) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_transpose(&mut temp as MutAfArray, arr.get() as AfArray, conjugate as c_int); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -109,12 +104,9 @@ pub fn transpose(arr: &Array, conjugate: bool) -> Result { /// - `conjugate` is a boolean that indicates if the transpose operation needs to be a conjugate /// transpose #[allow(unused_mut)] -pub fn transpose_inplace(arr: &mut Array, conjugate: bool) -> Result<(), AfError> { +pub fn transpose_inplace(arr: &mut Array, conjugate: bool) { unsafe { let err_val = af_transpose_inplace(arr.get() as AfArray, conjugate as c_int); - match err_val { - 0 => Ok(()), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); } } diff --git a/src/data/mod.rs b/src/data/mod.rs index 54b1f3cc1..6c8b6509b 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -4,6 +4,7 @@ extern crate num; use array::Array; use dim4::Dim4; use defines::AfError; +use error::HANDLE_ERROR; use self::libc::{uint8_t, c_int, c_uint, c_double}; use self::num::Complex; use util::HasAfEnum; @@ -68,87 +69,77 @@ extern { } pub trait ConstGenerator { - fn generate(&self, dims: Dim4) -> Result; + fn generate(&self, dims: Dim4) -> Array; } #[allow(unused_mut)] impl ConstGenerator for i64 { - fn generate(&self, dims: Dim4) -> Result { + fn generate(&self, dims: Dim4) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_constant_long(&mut temp as MutAfArray, *self as Intl, dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } } #[allow(unused_mut)] impl ConstGenerator for u64 { - fn generate(&self, dims: Dim4) -> Result { + fn generate(&self, dims: Dim4) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_constant_ulong(&mut temp as MutAfArray, *self as Uintl, dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } } #[allow(unused_mut)] impl ConstGenerator for Complex { - fn generate(&self, dims: Dim4) -> Result { + fn generate(&self, dims: Dim4) -> Array { unsafe { let mut temp: i64 = 0; let err_val = 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); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } } #[allow(unused_mut)] impl ConstGenerator for Complex { - fn generate(&self, dims: Dim4) -> Result { + fn generate(&self, dims: Dim4) -> Array { unsafe { let mut temp: i64 = 0; let err_val = 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); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } } #[allow(unused_mut)] impl ConstGenerator for bool { - fn generate(&self, dims: Dim4) -> Result { + fn generate(&self, dims: Dim4) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_constant(&mut temp as MutAfArray, *self as c_int as c_double, dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT, 4); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } } @@ -157,16 +148,14 @@ macro_rules! cnst { ($rust_type:ty, $ffi_type:expr) => ( #[allow(unused_mut)] impl ConstGenerator for $rust_type { - fn generate(&self, dims: Dim4) -> Result { + fn generate(&self, dims: Dim4) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_constant(&mut temp as MutAfArray, *self as c_double, dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT, $ffi_type); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } } @@ -206,7 +195,7 @@ cnst!(u16 , 11); /// # Return Values /// /// An Array of given dimensions with constant value -pub fn constant(cnst: T, dims: Dim4) -> Result { +pub fn constant(cnst: T, dims: Dim4) -> Array { cnst.generate(dims) } @@ -223,17 +212,15 @@ pub fn constant(cnst: T, dims: Dim4) -> Result(dims: Dim4, seq_dim: i32) -> Result { +pub fn range(dims: Dim4, seq_dim: i32) -> Array { unsafe { let aftype = T::get_af_dtype(); let mut temp: i64 = 0; let err_val = 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); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -250,7 +237,7 @@ pub fn range(dims: Dim4, seq_dim: i32) -> Result { /// /// Array #[allow(unused_mut)] -pub fn iota(dims: Dim4, tdims: Dim4) -> Result { +pub fn iota(dims: Dim4, tdims: Dim4) -> Array { unsafe { let aftype = T::get_af_dtype(); let mut temp: i64 = 0; @@ -258,51 +245,42 @@ pub fn iota(dims: Dim4, tdims: Dim4) -> Result { 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); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } /// Set seed for random number generation -pub fn set_seed(seed: u64) -> Result<(), AfError> { +pub fn set_seed(seed: u64) { unsafe { let err_val = af_set_seed(seed as Uintl); - match err_val { - 0 => Ok(()), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); } } /// Get the seed of random number generator #[allow(unused_mut)] -pub fn get_seed() -> Result { +pub fn get_seed() -> u64 { unsafe { let mut temp: u64 = 0; let err_val = af_get_seed(&mut temp as *mut Uintl); - match err_val { - 0 => Ok(temp), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + temp } } macro_rules! data_gen_def { ($fn_name:ident, $ffi_name: ident) => ( #[allow(unused_mut)] - pub fn $fn_name(dims: Dim4) -> Result { + pub fn $fn_name(dims: Dim4) -> Array { unsafe { let aftype = T::get_af_dtype(); let mut temp: i64 = 0; let err_val = $ffi_name(&mut temp as MutAfArray, dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT, aftype as uint8_t); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } ) @@ -324,14 +302,12 @@ data_gen_def!(identity, af_identity); /// /// An Array with values as a diagonal Matrix #[allow(unused_mut)] -pub fn diag_create(input: &Array, dim: i32) -> Result { +pub fn diag_create(input: &Array, dim: i32) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_diag_create(&mut temp as MutAfArray, input.get() as AfArray, dim as c_int); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -346,15 +322,13 @@ pub fn diag_create(input: &Array, dim: i32) -> Result { /// /// An Array with values of the diagonal from input Array #[allow(unused_mut)] -pub fn diag_extract(input: &Array, dim: i32) -> Result { +pub fn diag_extract(input: &Array, dim: i32) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_diag_extract(&mut temp as MutAfArray, input.get() as AfArray, dim as c_int); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -370,15 +344,13 @@ pub fn diag_extract(input: &Array, dim: i32) -> Result { /// /// Concatenated Array #[allow(unused_mut)] -pub fn join(dim: i32, first: &Array, second: &Array) -> Result { +pub fn join(dim: i32, first: &Array, second: &Array) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_join(&mut temp as MutAfArray, dim as c_int, first.get() as AfArray, second.get() as AfArray); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -393,7 +365,7 @@ pub fn join(dim: i32, first: &Array, second: &Array) -> Result { /// /// Concatenated Array #[allow(unused_mut)] -pub fn join_many(dim: i32, inputs: Vec<&Array>) -> Result { +pub fn join_many(dim: i32, inputs: Vec<&Array>) -> Array { unsafe { let mut v = Vec::new(); for i in inputs { @@ -402,26 +374,22 @@ pub fn join_many(dim: i32, inputs: Vec<&Array>) -> Result { let mut temp: i64 = 0; let err_val = af_join_many(&mut temp as MutAfArray, dim as c_int, v.len() as c_uint, v.as_ptr() as *const AfArray); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + 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) -> Result { + pub fn $fn_name(input: &Array, dims: Dim4) -> Array { unsafe { let mut temp: i64 = 0; let err_val = $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); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } ) @@ -441,28 +409,24 @@ data_func_def!(shift, af_shift); /// # Return Values /// Reshaped Array #[allow(unused_mut)] -pub fn moddims(input: &Array, dims: Dim4) -> Result { +pub fn moddims(input: &Array, dims: Dim4) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_moddims(&mut temp as MutAfArray, input.get() as AfArray, dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } /// Flatten the multidimensional Array to an 1D Array #[allow(unused_mut)] -pub fn flat(input: &Array) -> Result { +pub fn flat(input: &Array) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_flat(&mut temp as MutAfArray, input.get() as AfArray); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -477,14 +441,12 @@ pub fn flat(input: &Array) -> Result { /// /// Flipped Array #[allow(unused_mut)] -pub fn flip(input: &Array, dim: u32) -> Result { +pub fn flip(input: &Array, dim: u32) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_flip(&mut temp as MutAfArray, input.get() as AfArray, dim as c_uint); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -498,15 +460,13 @@ pub fn flip(input: &Array, dim: u32) -> Result { /// # Return Values /// Array #[allow(unused_mut)] -pub fn lower(input: &Array, is_unit_diag: bool) -> Result { +pub fn lower(input: &Array, is_unit_diag: bool) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_lower(&mut temp as MutAfArray, input.get() as AfArray, is_unit_diag as c_int); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -520,15 +480,13 @@ pub fn lower(input: &Array, is_unit_diag: bool) -> Result { /// # Return Values /// Array #[allow(unused_mut)] -pub fn upper(input: &Array, is_unit_diag: bool) -> Result { +pub fn upper(input: &Array, is_unit_diag: bool) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_upper(&mut temp as MutAfArray, input.get() as AfArray, is_unit_diag as c_int); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -553,15 +511,13 @@ pub fn upper(input: &Array, is_unit_diag: bool) -> Result { /// /// An Array #[allow(unused_mut)] -pub fn select(a: &Array, cond: &Array, b: &Array) -> Result { +pub fn select(a: &Array, cond: &Array, b: &Array) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_select(&mut temp as MutAfArray, cond.get() as AfArray, - a.get() as AfArray, b.get() as AfArray); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + a.get() as AfArray, b.get() as AfArray); + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -586,15 +542,13 @@ pub fn select(a: &Array, cond: &Array, b: &Array) -> Result { /// /// An Array #[allow(unused_mut)] -pub fn selectl(a: f64, cond: &Array, b: &Array) -> Result { +pub fn selectl(a: f64, cond: &Array, b: &Array) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_select_scalar_l(&mut temp as MutAfArray, cond.get() as AfArray, a as c_double, b.get() as AfArray); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -619,15 +573,13 @@ pub fn selectl(a: f64, cond: &Array, b: &Array) -> Result { /// /// An Array #[allow(unused_mut)] -pub fn selectr(a: &Array, cond: &Array, b: f64) -> Result { +pub fn selectr(a: &Array, cond: &Array, b: f64) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_select_scalar_r(&mut temp as MutAfArray, cond.get() as AfArray, - a.get() as AfArray, b as c_double); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + a.get() as AfArray, b as c_double); + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -649,15 +601,12 @@ pub fn selectr(a: &Array, cond: &Array, b: f64) -> Result { /// /// # Return Values /// -/// An Array +/// None #[allow(unused_mut)] -pub fn replace(a: &mut Array, cond: &Array, b: &Array) -> Result<(), AfError> { +pub fn replace(a: &mut Array, cond: &Array, b: &Array) { unsafe { let err_val = af_replace(a.get() as AfArray, cond.get() as AfArray, b.get() as AfArray); - match err_val { - 0 => Ok(()), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); } } @@ -679,14 +628,11 @@ pub fn replace(a: &mut Array, cond: &Array, b: &Array) -> Result<(), AfError> { /// /// # Return Values /// -/// An Array +/// None #[allow(unused_mut)] -pub fn replace_scalar(a: &mut Array, cond: &Array, b: f64) -> Result<(), AfError> { +pub fn replace_scalar(a: &mut Array, cond: &Array, b: f64) { unsafe { let err_val = af_replace_scalar(a.get() as AfArray, cond.get() as AfArray, b as c_double); - match err_val { - 0 => Ok(()), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); } -} +} \ No newline at end of file diff --git a/src/defines.rs b/src/defines.rs index e6274af9a..d33a9fe2b 100644 --- a/src/defines.rs +++ b/src/defines.rs @@ -16,7 +16,7 @@ pub enum AfError { /// There was an error with the runtime environment ERR_RUNTIME = 103, // 200-299 Errors in input parameters - /// The input array is not a valid af_array object + /// The input array is not a valid Array object ERR_INVALID_ARRAY = 201, /// One of the function arguments is incorrect ERR_ARG = 202, @@ -107,7 +107,7 @@ impl Error for AfError { /// Types of Array data type #[derive(Clone, Copy, Debug, PartialEq)] -pub enum Aftype { +pub enum DType { /// 32 bit float F32 = 0, /// 32 bit complex float diff --git a/src/device/mod.rs b/src/device/mod.rs index c888a2a51..f8dfd57ea 100644 --- a/src/device/mod.rs +++ b/src/device/mod.rs @@ -1,6 +1,7 @@ extern crate libc; use defines::AfError; +use error::HANDLE_ERROR; use self::libc::{c_int, size_t, c_char}; use std::ffi::CString; @@ -25,17 +26,15 @@ extern { /// /// # Return Values /// A triplet of integers indicating major, minor & fix release version numbers. -pub fn get_version() -> Result<(i32, i32, i32), AfError> { +pub fn get_version() -> (i32, i32, i32) { unsafe { let mut maj: i32 = 0; let mut min: i32 = 0; let mut pat: i32 = 0; let err_val = af_get_version(&mut maj as *mut c_int, &mut min as *mut c_int, &mut pat as *mut c_int); - match err_val { - 0 => Ok((maj, min, pat)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + (maj, min, pat) } } @@ -50,13 +49,10 @@ pub fn get_version() -> Result<(i32, i32, i32), AfError> { /// Platform: CUDA Toolkit 7, Driver: CUDA Driver Version: 7000 /// [0] GeForce GT 750M, 2048 MB, CUDA Compute 3.0 /// ``` -pub fn info() -> Result<(), AfError> { +pub fn info() { unsafe { let err_val = af_info(); - match err_val { - 0 => Ok(()), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); } } @@ -64,25 +60,20 @@ pub fn info() -> Result<(), AfError> { /// /// 0th device will be the default device unless init call /// is followed by set_device -pub fn init() -> Result<(), AfError> { +pub fn init() { unsafe { let err_val = af_init(); - match err_val { - 0 => Ok(()), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); } } /// Get total number of available devices -pub fn device_count() -> Result { +pub fn device_count() -> i32 { unsafe { let mut temp: i32 = 0; let err_val = af_get_device_count(&mut temp as *mut c_int); - match err_val { - 0 => Ok(temp), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + temp } } @@ -95,14 +86,12 @@ pub fn device_count() -> Result { /// # Return Values /// /// `True` if `device` device has double support, `False` otherwise. -pub fn is_double_available(device: i32) -> Result { +pub fn is_double_available(device: i32) -> bool { unsafe { let mut temp: i32 = 0; let err_val = af_get_dbl_support(&mut temp as *mut c_int, device as c_int); - match err_val { - 0 => Ok(temp > 0), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + temp > 0 } } @@ -111,25 +100,20 @@ pub fn is_double_available(device: i32) -> Result { /// # Parameters /// /// - `device` is the value of the device identifier which has to be set as active -pub fn set_device(device: i32) -> Result<(), AfError> { +pub fn set_device(device: i32) { unsafe { let err_val = af_set_device(device as c_int); - match err_val { - 0 => Ok(()), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); } } /// Get the current active device id -pub fn get_device() -> Result { +pub fn get_device() -> i32 { unsafe { let mut temp: i32 = 0; let err_val = af_get_device(&mut temp as *mut c_int); - match err_val { - 0 => Ok(temp), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + temp } } @@ -147,7 +131,7 @@ pub fn get_device() -> Result { /// * Number of buffers allocated /// * Number of bytes locked /// * Number of buffers locked -pub fn device_mem_info() -> Result<(u64, u64, u64, u64), AfError> { +pub fn device_mem_info() -> (u64, u64, u64, u64) { unsafe { let mut o0: u64 = 0; let mut o1: u64 = 0; @@ -157,10 +141,8 @@ pub fn device_mem_info() -> Result<(u64, u64, u64, u64), AfError> { &mut o1 as *mut size_t, &mut o2 as *mut size_t, &mut o3 as *mut size_t); - match err_val { - 0 => Ok((o0, o1, o2, o3)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + (o0, o1, o2, o3) } } @@ -176,19 +158,16 @@ pub fn device_mem_info() -> Result<(u64, u64, u64, u64), AfError> { /// # Return Values /// /// None -pub fn print_mem_info(msg: String, device: i32) -> Result<(), AfError> { +pub fn print_mem_info(msg: String, device: i32) { unsafe { let cmsg = CString::new(msg.as_bytes()); match cmsg { Ok(v) => { let err_val = af_print_mem_info(v.to_bytes_with_nul().as_ptr() as * const c_char, device as c_int); - match err_val { - 0 => Ok(()), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); }, - Err(_) => Err(AfError::from(AfError::ERR_INTERNAL)), + Err(_) => HANDLE_ERROR(AfError::ERR_INTERNAL), } } } @@ -202,13 +181,10 @@ pub fn print_mem_info(msg: String, device: i32) -> Result<(), AfError> { /// # Return Values /// /// None -pub fn set_mem_step_size(step_bytes: u64) -> Result<(), AfError> { +pub fn set_mem_step_size(step_bytes: u64) { unsafe { let err_val = af_set_mem_step_size(step_bytes as size_t); - match err_val { - 0 => Ok(()), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); } } @@ -221,25 +197,20 @@ pub fn set_mem_step_size(step_bytes: u64) -> Result<(), AfError> { /// # Return Values /// /// Returns is the size of minimum memory chunk in bytes -pub fn get_mem_step_size() -> Result { +pub fn get_mem_step_size() -> u64 { unsafe { let mut temp: u64 = 0; let err_val = af_get_mem_step_size(&mut temp as *mut size_t); - match err_val { - 0 => Ok(temp), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + temp } } /// Call the garbage collection routine -pub fn device_gc() -> Result<(), AfError> { +pub fn device_gc() { unsafe { let err_val = af_device_gc(); - match err_val { - 0 => Ok(()), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); } } @@ -252,12 +223,9 @@ pub fn device_gc() -> Result<(), AfError> { /// # Return Values /// /// None -pub fn sync(device: i32) -> Result<(), AfError> { +pub fn sync(device: i32) { unsafe { let err_val = af_sync(device as c_int); - match err_val { - 0 => Ok(()), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); } -} +} \ No newline at end of file diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 000000000..875b46d34 --- /dev/null +++ b/src/error.rs @@ -0,0 +1,33 @@ +use defines::AfError; + +pub type ErrorCallback = Fn(AfError); + +pub static mut HANDLE_ERROR: &'static ErrorCallback = &handle_error_general; + +pub fn register_error_handler(callback: &'static ErrorCallback) { + unsafe { + HANDLE_ERROR = callback; + } +} + +pub fn handle_error_general(error_code: AfError) { + match error_code { + AfError::SUCCESS => {}, /* No-op */ + AfError::ERR_NO_MEM => panic!("The system or device ran out of memory"), + AfError::ERR_DRIVER => panic!("There was an error in the device driver"), + AfError::ERR_RUNTIME => panic!("There was an error with the runtime environment"), + AfError::ERR_INVALID_ARRAY => panic!("The input array is not a valid Array object"), + AfError::ERR_ARG => panic!("One of the function arguments is incorrect"), + AfError::ERR_SIZE => panic!("The size is incorrect"), + AfError::ERR_TYPE => panic!("The type is not suppported by this function"), + AfError::ERR_DIFF_TYPE => panic!("The type of the input arrays are not compatible"), + AfError::ERR_BATCH => panic!("Function does not support GFOR / batch mode"), + AfError::ERR_DEVICE => panic!("Input does not belong to the current device"), + AfError::ERR_NOT_SUPPORTED => panic!("Unsupported operation/parameter option"), + AfError::ERR_NOT_CONFIGURED => panic!("This build of ArrayFire does not support this feature"), + AfError::ERR_NO_DBL => panic!("This device does not support double"), + AfError::ERR_NO_GFX => panic!("This build of ArrayFire was not built with graphics or this device does not support graphics"), + AfError::ERR_INTERNAL => panic!("There was an internal error either in ArrayFire or in a project upstream"), + AfError::ERR_UNKNOWN => panic!("Unknown Error"), + } +} \ No newline at end of file diff --git a/src/graphics.rs b/src/graphics.rs index c00ac4327..42a2dbd18 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -3,6 +3,7 @@ extern crate libc; use array::Array; use defines::AfError; use defines::{ColorMap, MarkerType}; +use error::HANDLE_ERROR; use self::libc::{c_int, c_uint, c_double, c_char}; use std::ffi::CString; @@ -56,12 +57,9 @@ pub struct Cell { /// /// ```no_run /// use arrayfire::{histogram, load_image, Window}; -/// let mut wnd = Window::new(1280, 720, String::from("Image Histogram")).unwrap(); -/// let img = match load_image("Path to image".to_string(), true/*If color image, 'false' otherwise*/) { -/// Ok(img) => img, -/// Err(err) => panic!("Image loading failed with error code {}", err), -/// }; -/// let hst = histogram(&img, 256, 0 as f64, 255 as f64).unwrap(); +/// let mut wnd = Window::new(1280, 720, String::from("Image Histogram")); +/// let img = load_image("Path to image".to_string(), true/*If color image, 'false' otherwise*/); +/// let hst = histogram(&img, 256, 0 as f64, 255 as f64); /// /// loop { /// wnd.grid(2, 1); @@ -74,7 +72,7 @@ pub struct Cell { /// /// wnd.show(); /// -/// if wnd.is_closed().unwrap() == true { break; } +/// if wnd.is_closed() == true { break; } /// } /// ``` #[derive(Clone)] @@ -107,50 +105,42 @@ impl Drop for Window { impl Window { /// Creates new Window object #[allow(unused_mut)] - pub fn new(width: i32, height: i32, title: String) -> Result { + pub fn new(width: i32, height: i32, title: String) -> Window { unsafe { let mut temp: u64 = 0; let cstr_ret = CString::new(title.as_bytes()); match cstr_ret { Ok(cstr) => { - let err_val = af_create_window(&mut temp as MutWndHandle - , width as c_int, height as c_int - , cstr.to_bytes_with_nul().as_ptr() as *const c_char); - match err_val { - 0 => Ok(Window::from(temp)), - _ => Err(AfError::from(err_val)), - } + let err_val = af_create_window(&mut temp as MutWndHandle, + width as c_int, height as c_int, + cstr.to_bytes_with_nul().as_ptr() as *const c_char); + HANDLE_ERROR(AfError::from(err_val)); + Window::from(temp) }, - Err(_) => Err(AfError::ERR_INTERNAL), + Err(_) => panic!("String creation failed while prepping params for window creation."), } } } /// Set window starting position on the screen - pub fn set_position(&self, x: u32, y: u32) -> Result<(), AfError> { + pub fn set_position(&self, x: u32, y: u32) { unsafe { let err_val = af_set_position(self.handle as WndHandle, x as c_uint, y as c_uint); - match err_val { - 0 => Ok(()), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); } } /// Set window title - pub fn set_title(&self, title: String) -> Result<(), AfError> { + pub fn set_title(&self, title: String) { unsafe { let cstr_ret = CString::new(title.as_bytes()); match cstr_ret { Ok(cstr) => { - let err_val = af_set_title(self.handle as WndHandle - , cstr.to_bytes_with_nul().as_ptr() as *const c_char); - match err_val { - 0 => Ok(()), - _ => Err(AfError::from(err_val)), - } + let err_val = af_set_title(self.handle as WndHandle, + cstr.to_bytes_with_nul().as_ptr() as *const c_char); + HANDLE_ERROR(AfError::from(err_val)); }, - Err(_) => Err(AfError::ERR_INTERNAL), + Err(_) => HANDLE_ERROR(AfError::ERR_INTERNAL), } } } @@ -164,13 +154,10 @@ impl Window { /// # Return Values /// /// None - pub fn set_visibility(&self, is_visible: bool) -> Result<(), AfError> { + pub fn set_visibility(&self, is_visible: bool) { unsafe { let err_val = af_set_visibility(self.handle as WndHandle, is_visible as c_int); - match err_val { - 0 => Ok(()), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); } } @@ -180,13 +167,10 @@ impl Window { /// /// - `w` is the target width of window /// - `h` is the target height of window - pub fn set_size(&self, w: u32, h: u32) -> Result<(), AfError> { + pub fn set_size(&self, w: u32, h: u32) { unsafe { let err_val = af_set_size(self.handle as WndHandle, w as c_uint, h as c_uint); - match err_val { - 0 => Ok(()), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); } } @@ -197,39 +181,31 @@ impl Window { } /// Returns true if the window close is triggered by the user - pub fn is_closed(&self) -> Result { + pub fn is_closed(&self) -> bool { unsafe { let mut temp: i32 = 1; let err_val = af_is_window_closed(&mut temp as *mut c_int, self.handle as WndHandle); - match err_val { - 0 => Ok(temp > 0), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + temp > 0 } } /// Used to setup display layout in multiview mode - pub fn grid(&self, rows: i32, cols: i32) -> Result<(), AfError> { + pub fn grid(&self, rows: i32, cols: i32) { unsafe { let err_val = af_grid(self.handle as WndHandle, rows as c_int, cols as c_int); - match err_val { - 0 => Ok(()), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); } } /// Used in multiview mode to swap back buffer with front buffer to show the recently rendered /// frame - pub fn show(&mut self) -> Result<(), AfError> { + pub fn show(&mut self) { unsafe { let err_val = af_show(self.handle as WndHandle); - if err_val != 0 { - return Err(AfError::from(err_val)); - } + HANDLE_ERROR(AfError::from(err_val)); self.row = -1; self.col = -1; - Ok(()) } } @@ -250,10 +226,7 @@ impl Window { unsafe { let err_val = af_draw_image(self.handle as WndHandle, input.get() as AfArray, cprops as *const Cell as CellPtr); - match err_val { - 0 => (), - _ => panic!("Rendering the image failed: {}", err_val), - } + HANDLE_ERROR(AfError::from(err_val)); } } @@ -269,10 +242,7 @@ impl Window { x.get() as AfArray, y.get() as AfArray, cprops as *const Cell as CellPtr); - match err_val { - 0 => (), - _ => panic!("Rendering 2d line plot failed: {}", err_val), - } + HANDLE_ERROR(AfError::from(err_val)); } } @@ -286,10 +256,7 @@ impl Window { unsafe { let err_val = af_draw_plot3(self.handle as WndHandle, points.get() as AfArray, cprops as *const Cell as CellPtr); - match err_val { - 0 => (), - _ => panic!("Rendering 3d line plot failed: {}", err_val), - } + HANDLE_ERROR(AfError::from(err_val)); } } @@ -304,10 +271,7 @@ impl Window { let err_val = af_draw_hist(self.handle as WndHandle, hst.get() as AfArray, minval as c_double, maxval as c_double, cprops as *const Cell as CellPtr); - match err_val { - 0 => (), - _ => panic!("Rendering histogram failed: {}", err_val), - } + HANDLE_ERROR(AfError::from(err_val)); } } @@ -324,10 +288,7 @@ impl Window { yvals.get() as AfArray, zvals.get() as AfArray, cprops as *const Cell as CellPtr); - match err_val { - 0 => (), - _ => panic!("Rendering surface failed: {}", err_val), - } + HANDLE_ERROR(AfError::from(err_val)); } } @@ -344,10 +305,7 @@ impl Window { yvals.get() as AfArray, marker as c_int, cprops as *const Cell as CellPtr); - match err_val { - 0 => (), - _ => panic!("Rendering scatter failed: {}", err_val), - } + HANDLE_ERROR(AfError::from(err_val)); } } @@ -363,10 +321,7 @@ impl Window { vals.get() as AfArray, marker as c_int, cprops as *const Cell as CellPtr); - match err_val { - 0 => (), - _ => panic!("Rendering scatter3 failed: {}", err_val), - } + HANDLE_ERROR(AfError::from(err_val)); } } -} +} \ No newline at end of file diff --git a/src/image/mod.rs b/src/image/mod.rs index f12f0d866..19bbc9639 100644 --- a/src/image/mod.rs +++ b/src/image/mod.rs @@ -1,12 +1,8 @@ extern crate libc; use array::Array; -use defines::AfError; -use defines::BorderType; -use defines::ColorSpace; -use defines::Connectivity; -use defines::InterpType; -use defines::YCCStd; +use defines::{AfError, BorderType, ColorSpace, Connectivity, InterpType, YCCStd}; +use error::HANDLE_ERROR; use util::HasAfEnum; use self::libc::{uint8_t, c_uint, c_int, c_float, c_double}; @@ -115,16 +111,14 @@ extern { /// /// The second Array is `dy` which is the gradient along the 2nd dimension. #[allow(unused_mut)] -pub fn gradient(input: &Array) -> Result<(Array, Array), AfError> { +pub fn gradient(input: &Array) -> (Array, Array) { unsafe { let mut dx: i64 = 0; let mut dy: i64 = 0; let err_val = af_gradient(&mut dx as MutAfArray, &mut dy as MutAfArray, input.get() as AfArray); - match err_val { - 0 => Ok((Array::from(dx), Array::from(dy))), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + (Array::from(dx), Array::from(dy)) } } @@ -139,16 +133,14 @@ pub fn gradient(input: &Array) -> Result<(Array, Array), AfError> { /// /// An Array with pixel values loaded from the image #[allow(unused_mut)] -pub fn load_image(filename: String, is_color: bool) -> Result { +pub fn load_image(filename: String, is_color: bool) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_load_image(&mut temp as MutAfArray, filename.clone().as_bytes().as_ptr() as *const u8, is_color as c_int); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -171,15 +163,13 @@ pub fn load_image(filename: String, is_color: bool) -> Result { /// /// An Array with pixel values loaded from the image #[allow(unused_mut)] -pub fn load_image_native(filename: String) -> Result { +pub fn load_image_native(filename: String) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_load_image_native(&mut temp as MutAfArray, filename.clone().as_bytes().as_ptr() as *const u8); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -190,14 +180,11 @@ pub fn load_image_native(filename: String) -> Result { /// - `filename` is the abolute path(includes filename) at which input Array is going to be saved /// - `input` is the Array to be stored into the image file #[allow(unused_mut)] -pub fn save_image(filename: String, input: &Array) -> Result<(), AfError> { +pub fn save_image(filename: String, input: &Array) { unsafe { let err_val = af_save_image(filename.clone().as_bytes().as_ptr() as *const u8, input.get() as AfArray); - match err_val { - 0 => Ok(()), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); } } @@ -218,14 +205,11 @@ pub fn save_image(filename: String, input: &Array) -> Result<(), AfError> { /// - `filename` is name of file to be saved /// - `input` is the Array to be saved. Should be U8 for saving 8-bit image, U16 for 16-bit image, and F32 for 32-bit image. #[allow(unused_mut)] -pub fn save_image_native(filename: String, input: &Array) -> Result<(), AfError> { +pub fn save_image_native(filename: String, input: &Array) { unsafe { let err_val = af_save_image_native(filename.clone().as_bytes().as_ptr() as *const u8, input.get() as AfArray); - match err_val { - 0 => Ok(()), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); } } @@ -251,15 +235,13 @@ pub fn save_image_native(filename: String, input: &Array) -> Result<(), AfError> /// Resized Array #[allow(unused_mut)] pub fn resize(input: &Array, odim0: i64, odim1: i64, - method: InterpType) -> Result { + method: InterpType) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_resize(&mut temp as MutAfArray, input.get() as AfArray, odim0 as DimT, odim1 as DimT, method as uint8_t); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -294,17 +276,15 @@ pub fn resize(input: &Array, odim0: i64, odim1: i64, /// Resized Array #[allow(unused_mut)] pub fn transform(input: &Array, trans: &Array, odim0: i64, odim1: i64, - method: InterpType, is_inverse: bool) -> Result { + method: InterpType, is_inverse: bool) -> Array { unsafe { let mut temp: i64 = 0; let err_val = 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); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -339,15 +319,13 @@ pub fn transform(input: &Array, trans: &Array, odim0: i64, odim1: i64, /// Rotated Array #[allow(unused_mut)] pub fn rotate(input: &Array, theta: f64, crop: bool, - method: InterpType) -> Result { + method: InterpType) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_rotate(&mut temp as MutAfArray, input.get() as AfArray, theta as c_float, crop as c_int, method as uint8_t); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -380,7 +358,7 @@ pub fn rotate(input: &Array, theta: f64, crop: bool, /// Translated Image(Array). #[allow(unused_mut)] pub fn translate(input: &Array, trans0: f32, trans1: f32, - odim0: i64, odim1: i64, method: InterpType) -> Result { + odim0: i64, odim1: i64, method: InterpType) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_translate(&mut temp as MutAfArray, @@ -388,10 +366,8 @@ pub fn translate(input: &Array, trans0: f32, trans1: f32, trans0 as c_float, trans1 as c_float, odim0 as DimT, odim1 as DimT, method as uint8_t); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -415,7 +391,7 @@ pub fn translate(input: &Array, trans0: f32, trans1: f32, /// Translated Image(Array). #[allow(unused_mut)] pub fn scale(input: &Array, scale0: f32, scale1: f32, - odim0: i64, odim1: i64, method: InterpType) -> Result { + odim0: i64, odim1: i64, method: InterpType) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_scale(&mut temp as MutAfArray, @@ -423,10 +399,8 @@ pub fn scale(input: &Array, scale0: f32, scale1: f32, scale0 as c_float, scale1 as c_float, odim0 as DimT, odim1 as DimT, method as uint8_t); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -456,17 +430,15 @@ pub fn scale(input: &Array, scale0: f32, scale1: f32, /// Skewed Image #[allow(unused_mut)] pub fn skew(input: &Array, skew0: f32, skew1: f32, odim0: i64, odim1: i64, - method: InterpType, is_inverse: bool) -> Result { + method: InterpType, is_inverse: bool) -> Array { unsafe { let mut temp: i64 = 0; let err_val = 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); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -495,15 +467,13 @@ pub fn skew(input: &Array, skew0: f32, skew1: f32, odim0: i64, odim1: i64, /// Histogram of input Array #[allow(unused_mut)] pub fn histogram(input: &Array, nbins: u32, - minval: f64, maxval: f64) -> Result { + minval: f64, maxval: f64) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_histogram(&mut temp as MutAfArray, input.get() as AfArray, nbins as c_uint, minval as c_double, maxval as c_double); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -527,15 +497,13 @@ pub fn histogram(input: &Array, nbins: u32, /// /// Dilated Image(Array) #[allow(unused_mut)] -pub fn dilate(input: &Array, mask: &Array) -> Result { +pub fn dilate(input: &Array, mask: &Array) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_dilate(&mut temp as MutAfArray, input.get() as AfArray, mask.get() as AfArray); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -560,15 +528,13 @@ pub fn dilate(input: &Array, mask: &Array) -> Result { /// /// Eroded Image(Array) #[allow(unused_mut)] -pub fn erode(input: &Array, mask: &Array) -> Result { +pub fn erode(input: &Array, mask: &Array) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_erode(&mut temp as MutAfArray, input.get() as AfArray, mask.get() as AfArray); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -586,15 +552,13 @@ pub fn erode(input: &Array, mask: &Array) -> Result { /// /// Dilated Volume(Array) #[allow(unused_mut)] -pub fn dilate3(input: &Array, mask: &Array) -> Result { +pub fn dilate3(input: &Array, mask: &Array) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_dilate3(&mut temp as MutAfArray, input.get() as AfArray, mask.get() as AfArray); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -612,15 +576,13 @@ pub fn dilate3(input: &Array, mask: &Array) -> Result { /// /// Eroded Volume(Array) #[allow(unused_mut)] -pub fn erode3(input: &Array, mask: &Array) -> Result { +pub fn erode3(input: &Array, mask: &Array) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_erode3(&mut temp as MutAfArray, input.get() as AfArray, mask.get() as AfArray); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -645,16 +607,14 @@ pub fn erode3(input: &Array, mask: &Array) -> Result { /// Filtered Image - Array #[allow(unused_mut)] pub fn bilateral(input: &Array, spatial_sigma: f32, chromatic_sigma: f32, - iscolor: bool) -> Result { + iscolor: bool) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_bilateral(&mut temp as MutAfArray, input.get() as AfArray, spatial_sigma as c_float, chromatic_sigma as c_float, iscolor as c_int); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -680,16 +640,14 @@ pub fn bilateral(input: &Array, spatial_sigma: f32, chromatic_sigma: f32, /// Filtered Image - Array #[allow(unused_mut)] pub fn mean_shift(input: &Array, spatial_sigma: f32, chromatic_sigma: f32, - iter: u32, iscolor: bool) -> Result { + iter: u32, iscolor: bool) -> Array { unsafe { let mut temp: i64 = 0; let err_val = 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); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -697,15 +655,13 @@ macro_rules! filt_func_def { ($fn_name: ident, $ffi_name: ident) => ( #[allow(unused_mut)] pub fn $fn_name(input: &Array, wlen: u64, wwid: u64, - etype: BorderType) -> Result { + etype: BorderType) -> Array { unsafe { let mut temp: i64 = 0; let err_val = $ffi_name(&mut temp as MutAfArray, input.get() as AfArray, wlen as DimT, wwid as DimT, etype as uint8_t); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } ) @@ -738,16 +694,14 @@ filt_func_def!(maxfilt, af_maxfilt); /// An Array with gaussian kernel values #[allow(unused_mut)] pub fn gaussian_kernel(rows: i32, cols: i32, - sigma_r: f64, sigma_c: f64) -> Result { + sigma_r: f64, sigma_c: f64) -> Array { unsafe { let mut temp: i64 = 0; let err_val = 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); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -787,15 +741,13 @@ pub fn gaussian_kernel(rows: i32, cols: i32, /// An Array with input image values in target color space #[allow(unused_mut)] pub fn color_space(input: &Array, - tospace: ColorSpace, fromspace: ColorSpace) -> Result { + tospace: ColorSpace, fromspace: ColorSpace) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_color_space(&mut temp as MutAfArray, input.get() as AfArray, tospace as uint8_t, fromspace as uint8_t); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -817,16 +769,14 @@ pub fn color_space(input: &Array, /// /// Array with labels indicating different regions #[allow(unused_mut)] -pub fn regions(input: &Array, conn: Connectivity) -> Result { +pub fn regions(input: &Array, conn: Connectivity) -> Array { unsafe { let otype = OutType::get_af_dtype(); let mut temp: i64 = 0; let err_val = af_regions(&mut temp as MutAfArray, input.get() as AfArray, conn as uint8_t, otype as uint8_t); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -848,16 +798,14 @@ pub fn regions(input: &Array, conn: Connectivity) -> Result< /// /// The second Array has derivatives along vertical direction #[allow(unused_mut)] -pub fn sobel(input: &Array, ker_size: u32) -> Result<(Array, Array), AfError> { +pub fn sobel(input: &Array, ker_size: u32) -> (Array, Array) { unsafe { let mut dx: i64 = 0; let mut dy: i64 = 0; let err_val = af_sobel_operator(&mut dx as MutAfArray, &mut dy as MutAfArray, input.get() as AfArray, ker_size as c_uint); - match err_val { - 0 => Ok((Array::from(dx), Array::from(dy))), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + (Array::from(dx), Array::from(dy)) } } @@ -871,15 +819,13 @@ pub fn sobel(input: &Array, ker_size: u32) -> Result<(Array, Array), AfError> { /// # Return Values /// Equalized Array #[allow(unused_mut)] -pub fn hist_equal(input: &Array, hist: &Array) -> Result { +pub fn hist_equal(input: &Array, hist: &Array) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_hist_equal(&mut temp as MutAfArray, input.get() as AfArray, hist.get() as AfArray); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -893,15 +839,13 @@ macro_rules! grayrgb_func_def { /// - `g` is fraction of green channel to appear in output /// - `b` is fraction of blue channel to appear in output #[allow(unused_mut)] - pub fn $fn_name(input: &Array, r: f32, g: f32, b: f32) -> Result { + pub fn $fn_name(input: &Array, r: f32, g: f32, b: f32) -> Array { unsafe { let mut temp: i64 = 0; let err_val = $ffi_name(&mut temp as MutAfArray, input.get() as AfArray, r as c_float, g as c_float, b as c_float); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } ) @@ -914,14 +858,12 @@ macro_rules! hsvrgb_func_def { ($fn_name: ident, $ffi_name: ident) => ( /// Color space conversion functions #[allow(unused_mut)] - pub fn $fn_name(input: &Array) -> Result { + pub fn $fn_name(input: &Array) -> Array { unsafe { let mut temp: i64 = 0; let err_val = $ffi_name(&mut temp as MutAfArray, input.get() as AfArray); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } ) @@ -1004,15 +946,13 @@ pub fn unwrap(input: &Array, wx: i64, wy: i64, sx: i64, sy: i64, px: i64, py: i64, - is_column: bool) -> Result { + is_column: bool) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_unwrap(&mut temp as MutAfArray, input.get() as AfArray, wx, wy, sx, sy, px, py, is_column as c_int); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -1042,15 +982,13 @@ pub fn unwrap(input: &Array, pub fn wrap(input: &Array, ox: i64, oy: i64, wx: i64, wy: i64, sx: i64, sy: i64, px: i64, py: i64, - is_column: bool) -> Result { + is_column: bool) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_wrap(&mut temp as MutAfArray, input.get() as AfArray, ox, oy, wx, wy, sx, sy, px, py, is_column as c_int); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -1063,14 +1001,12 @@ pub fn wrap(input: &Array, /// # Return Values /// /// Summed area table (a.k.a Integral Image) of the input image. -pub fn sat(input: &Array) -> Result { +pub fn sat(input: &Array) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_sat(&mut temp as MutAfArray, input.get() as AfArray); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -1094,15 +1030,13 @@ pub fn sat(input: &Array) -> Result { /// # Return Values /// /// Image(Array) in YCbCr color space -pub fn rgb2ycbcr(input: &Array, standard: YCCStd) -> Result { +pub fn rgb2ycbcr(input: &Array, standard: YCCStd) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_rgb2ycbcr(&mut temp as MutAfArray, input.get() as AfArray, standard as c_int); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -1132,15 +1066,13 @@ pub fn rgb2ycbcr(input: &Array, standard: YCCStd) -> Result { /// # Return Values /// /// Image(Array) in RGB color space -pub fn ycbcr2rgb(input: &Array, standard: YCCStd) -> Result { +pub fn ycbcr2rgb(input: &Array, standard: YCCStd) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_ycbcr2rgb(&mut temp as MutAfArray, input.get() as AfArray, standard as c_int); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -1157,7 +1089,7 @@ pub fn is_imageio_available() -> bool { unsafe { let mut temp: i32 = 0; af_is_image_io_available(&mut temp as *mut c_int); - temp > 0 // Return boolean fla + temp > 0 // Return boolean flag } } @@ -1178,15 +1110,13 @@ pub fn is_imageio_available() -> bool { /// # Return Values /// /// Transformed coordinates -pub fn transform_coords(tf: &Array, d0: f32, d1: f32) -> Result { +pub fn transform_coords(tf: &Array, d0: f32, d1: f32) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_transform_coordinates(&mut temp as MutAfArray, tf.get() as AfArray, d0 as c_float, d1 as c_float); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } -} +} \ No newline at end of file diff --git a/src/index.rs b/src/index.rs index 9b9cc4c5b..ba7cdf05b 100644 --- a/src/index.rs +++ b/src/index.rs @@ -2,6 +2,7 @@ extern crate libc; use array::Array; use defines::AfError; +use error::HANDLE_ERROR; use seq::Seq; use self::libc::{c_double, c_int, c_uint}; @@ -36,7 +37,7 @@ pub struct Indexer { // Any object to be able to be passed on to [./struct.Indexer.html#method.set_index] method // should implement this trait with appropriate implementation pub trait Indexable { - fn set(&self, idxr: &Indexer, dim: u32, is_batch: Option) -> Result<(), AfError>; + fn set(&self, idxr: &Indexer, dim: u32, is_batch: Option); } /// Enables [Array](./struct.Array.html) to be used to index another Array @@ -45,15 +46,12 @@ pub trait Indexable { /// [assign_gen](./fn.assign_gen.html) impl Indexable for Array { #[allow(unused_variables)] - fn set(&self, idxr: &Indexer, dim: u32, is_batch: Option) -> Result<(), AfError> { + fn set(&self, idxr: &Indexer, dim: u32, is_batch: Option) { unsafe { let err_val = af_set_array_indexer(idxr.clone().get() as MutAfIndex, self.get() as AfArray, dim as DimT); - match err_val { - 0 => Ok(()), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); } } } @@ -63,34 +61,29 @@ impl Indexable for Array { /// This is used in functions [index_gen](./fn.index_gen.html) and /// [assign_gen](./fn.assign_gen.html) impl Indexable for Seq where c_double: From { - fn set(&self, idxr: &Indexer, dim: u32, is_batch: Option) -> Result<(), AfError> { + fn set(&self, idxr: &Indexer, dim: u32, is_batch: Option) { unsafe { let err_val = af_set_seq_indexer(idxr.clone().get() as MutAfIndex, &SeqInternal::from_seq(self) as *const SeqInternal, dim as DimT, is_batch.unwrap() as c_int); - match err_val { - 0 => Ok(()), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); } } } impl Indexer { #[allow(unused_mut)] - pub fn new() -> Result { + pub fn new() -> Indexer { unsafe { let mut temp: i64 = 0; let err_val = af_create_indexers(&mut temp as MutAfIndex); - match err_val { - 0 => Ok(Indexer{handle: temp, count: 0}), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Indexer{handle: temp, count: 0} } } /// Set either [Array](./struct.Array.html) or [Seq](./struct.Seq.html) to index an Array along `idx` dimension - pub fn set_index(&mut self, idx: &T, dim: u32, is_batch: Option) -> Result<(), AfError> { + pub fn set_index(&mut self, idx: &T, dim: u32, is_batch: Option) { self.count = self.count + 1; idx.set(self, dim, is_batch) } @@ -127,14 +120,14 @@ impl Drop for Indexer { /// ``` /// use arrayfire::{Dim4, Seq, index, randu, print}; /// let dims = Dim4::new(&[5, 5, 1, 1]); -/// let a = randu::(dims).unwrap(); +/// let a = randu::(dims); /// let seqs = &[Seq::new(1.0, 3.0, 1.0), Seq::default()]; -/// let sub = index(&a, seqs).unwrap(); +/// let sub = index(&a, seqs); /// println!("a(seq(1, 3, 1), span)"); -/// print(&sub).unwrap(); +/// print(&sub); /// ``` -pub fn index(input: &Array, seqs: &[Seq]) -> Result - where c_double: From +pub fn index(input: &Array, seqs: &[Seq]) -> Array + where c_double: From { unsafe { let mut temp: i64 = 0; @@ -143,10 +136,8 @@ pub fn index(input: &Array, seqs: &[Seq]) -> Result let err_val = af_index(&mut temp as MutAfArray , input.get() as AfArray, seqs.len() as u32 , seqs.as_ptr() as *const SeqInternal); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -157,35 +148,35 @@ pub fn index(input: &Array, seqs: &[Seq]) -> Result /// ``` /// use arrayfire::{Dim4, randu, row, print}; /// let dims = Dim4::new(&[5, 5, 1, 1]); -/// let a = randu::(dims).unwrap(); +/// let a = randu::(dims); /// println!("Grab last row of the random matrix"); /// print(&a); -/// print(&row(&a, 4).unwrap()).unwrap(); +/// print(&row(&a, 4)); /// ``` #[allow(dead_code)] -pub fn row(input: &Array, row_num: u64) -> Result { +pub fn row(input: &Array, row_num: u64) -> Array { index(input, &[Seq::new(row_num as f64, row_num as f64, 1.0), Seq::default()]) } #[allow(dead_code)] /// Set row `row_num` in `input` Array to a new Array `new_row` -pub fn set_row(input: &Array, new_row: &Array, row_num: u64) -> Result { - assign_seq(input, &[Seq::new(row_num as f64, row_num as f64, 1.0), Seq::default()] - , new_row) +pub fn set_row(input: &Array, new_row: &Array, row_num: u64) -> Array { + assign_seq(input, + &[Seq::new(row_num as f64, row_num as f64, 1.0), Seq::default()], + new_row) } #[allow(dead_code)] /// Get all rows from `first` to `last` in the `input` Array -pub fn rows(input: &Array, first: u64, last: u64) -> Result { +pub fn rows(input: &Array, first: u64, last: u64) -> Array { index(input, &[Seq::new(first as f64, last as f64, 1.0), Seq::default()]) } #[allow(dead_code)] /// Set rows from `first` to `last` in `input` Array with rows from Array `new_rows` -pub fn set_rows(input: &Array, new_rows: &Array, first: u64, last: u64) -> Result { - assign_seq(input, &[Seq::new(first as f64, last as f64, 1.0), Seq::default()] - , new_rows) +pub fn set_rows(input: &Array, new_rows: &Array, first: u64, last: u64) -> Array { + assign_seq(input, &[Seq::new(first as f64, last as f64, 1.0), Seq::default()], new_rows) } /// Extract `col_num` col from `input` Array @@ -195,94 +186,85 @@ pub fn set_rows(input: &Array, new_rows: &Array, first: u64, last: u64) -> Resul /// ``` /// use arrayfire::{Dim4, randu, col, print}; /// let dims = Dim4::new(&[5, 5, 1, 1]); -/// let a = randu::(dims).unwrap(); +/// let a = randu::(dims); /// println!("Grab last col of the random matrix"); /// print(&a); -/// print(&col(&a, 4).unwrap()); +/// print(&col(&a, 4)); /// ``` #[allow(dead_code)] -pub fn col(input: &Array, col_num: u64) -> Result { - index(input, &[Seq::default() - , Seq::new(col_num as f64, col_num as f64, 1.0)]) +pub fn col(input: &Array, col_num: u64) -> Array { + index(input, &[Seq::default(), Seq::new(col_num as f64, col_num as f64, 1.0)]) } #[allow(dead_code)] /// Set col `col_num` in `input` Array to a new Array `new_col` -pub fn set_col(input: &Array, new_col: &Array, col_num: u64) -> Result { - assign_seq(input, &[Seq::default(), Seq::new(col_num as f64, col_num as f64, 1.0)] - , new_col) +pub fn set_col(input: &Array, new_col: &Array, col_num: u64) -> Array { + assign_seq(input, + &[Seq::default(), Seq::new(col_num as f64, col_num as f64, 1.0)], + new_col) } #[allow(dead_code)] /// Get all cols from `first` to `last` in the `input` Array -pub fn cols(input: &Array, first: u64, last: u64) -> Result { - index(input, &[Seq::default() - , Seq::new(first as f64, last as f64, 1.0)]) +pub fn cols(input: &Array, first: u64, last: u64) -> Array { + index(input, &[Seq::default(), Seq::new(first as f64, last as f64, 1.0)]) } #[allow(dead_code)] /// Set cols from `first` to `last` in `input` Array with cols from Array `new_cols` -pub fn set_cols(input: &Array, new_cols: &Array, first: u64, last: u64) -> Result { - assign_seq(input, &[Seq::default(), Seq::new(first as f64, last as f64, 1.0)] - , new_cols) +pub fn set_cols(input: &Array, new_cols: &Array, first: u64, last: u64) -> Array { + assign_seq(input, &[Seq::default(), Seq::new(first as f64, last as f64, 1.0)], new_cols) } #[allow(dead_code)] /// Get slice `slice_num` from `input` Array /// /// Slices indicate that the indexing is along 3rd dimension -pub fn slice(input: &Array, slice_num: u64) -> Result { - index(input, &[Seq::default() - , Seq::default() - , Seq::new(slice_num as f64, slice_num as f64, 1.0)]) +pub fn slice(input: &Array, slice_num: u64) -> Array { + index(input, + &[Seq::default(), Seq::default(), Seq::new(slice_num as f64, slice_num as f64, 1.0)]) } #[allow(dead_code)] /// Set slice `slice_num` in `input` Array to a new Array `new_slice` /// /// Slices indicate that the indexing is along 3rd dimension -pub fn set_slice(input: &Array, new_slice: &Array, slice_num: u64) -> Result { - assign_seq(input, &[Seq::default() - , Seq::default() - , Seq::new(slice_num as f64, slice_num as f64, 1.0)] - , new_slice) +pub fn set_slice(input: &Array, new_slice: &Array, slice_num: u64) -> Array { + assign_seq(input, + &[Seq::default(), Seq::default(), Seq::new(slice_num as f64, slice_num as f64, 1.0)], + new_slice) } #[allow(dead_code)] /// Get slices from `first` to `last` in `input` Array /// /// Slices indicate that the indexing is along 3rd dimension -pub fn slices(input: &Array, first: u64, last: u64) -> Result { - index(input, &[Seq::default() - , Seq::default() - , Seq::new(first as f64, last as f64, 1.0)]) +pub fn slices(input: &Array, first: u64, last: u64) -> Array { + index(input, + &[Seq::default(), Seq::default(), Seq::new(first as f64, last as f64, 1.0)]) } #[allow(dead_code)] /// Set `first` to `last` slices of `input` Array to a new Array `new_slices` /// /// Slices indicate that the indexing is along 3rd dimension -pub fn set_slices(input: &Array, new_slices: &Array, first: u64, last: u64) -> Result { - assign_seq(input, &[Seq::default() - , Seq::default() - , Seq::new(first as f64, last as f64, 1.0)] - , new_slices) +pub fn set_slices(input: &Array, new_slices: &Array, first: u64, last: u64) -> Array { + assign_seq(input, + &[Seq::default() , Seq::default(), Seq::new(first as f64, last as f64, 1.0)], + new_slices) } - /// Lookup(hash) an Array using another Array /// /// Given a dimension `seq_dim`, `indices` are lookedup in `input` and returned as a new /// Array if found -pub fn lookup(input: &Array, indices: &Array, seq_dim: i32) -> Result { +pub fn lookup(input: &Array, indices: &Array, seq_dim: i32) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_lookup(&mut temp as MutAfArray, input.get() as AfArray, indices.get() as AfArray, seq_dim as c_uint); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -294,10 +276,10 @@ pub fn lookup(input: &Array, indices: &Array, seq_dim: i32) -> Result Result(lhs: &Array, seqs: &[Seq], rhs: &Array) -> Result +pub fn assign_seq(lhs: &Array, seqs: &[Seq], rhs: &Array) -> Array where c_double: From { unsafe{ @@ -322,10 +304,8 @@ pub fn assign_seq(lhs: &Array, seqs: &[Seq], rhs: &Array) -> Result< let err_val = af_assign_seq(&mut temp as MutAfArray, lhs.get() as AfArray, seqs.len() as c_uint, seqs.as_ptr() as *const SeqInternal, rhs.get() as AfArray); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -336,9 +316,9 @@ pub fn assign_seq(lhs: &Array, seqs: &[Seq], rhs: &Array) -> Result< /// ``` /// use arrayfire::{Array, Dim4, Seq, print, randu, index_gen, Indexer}; /// let values: &[f32] = &[1.0, 2.0, 3.0]; -/// let indices = Array::new(values, Dim4::new(&[3, 1, 1, 1])).unwrap(); +/// let indices = Array::new(values, Dim4::new(&[3, 1, 1, 1])); /// let seq4gen = Seq::new(0.0, 2.0, 1.0); -/// let a = randu::(Dim4::new(&[5, 3, 1, 1])).unwrap(); +/// let a = randu::(Dim4::new(&[5, 3, 1, 1])); /// // [5 3 1 1] /// // 0.0000 0.2190 0.3835 /// // 0.1315 0.0470 0.5194 @@ -347,29 +327,24 @@ pub fn assign_seq(lhs: &Array, seqs: &[Seq], rhs: &Array) -> Result< /// // 0.5328 0.9347 0.0535 /// /// -/// let mut idxrs = match Indexer::new() { -/// Ok(v) => v, -/// Err(e) => panic!("{}",e), -/// }; -/// idxrs.set_index(&indices, 0, None).unwrap(); // 2nd parameter is indexing dimension -/// idxrs.set_index(&seq4gen, 1, Some(false)).unwrap(); // 3rd parameter indicates batch operation +/// let mut idxrs = Indexer::new(); +/// idxrs.set_index(&indices, 0, None); // 2nd parameter is indexing dimension +/// idxrs.set_index(&seq4gen, 1, Some(false)); // 3rd parameter indicates batch operation /// -/// let sub2 = index_gen(&a, idxrs).unwrap(); -/// println!("a(indices, seq(0, 2, 1))"); print(&sub2).unwrap(); +/// let sub2 = index_gen(&a, idxrs); +/// println!("a(indices, seq(0, 2, 1))"); print(&sub2); /// // [3 3 1 1] /// // 0.1315 0.0470 0.5194 /// // 0.7556 0.6789 0.8310 /// // 0.4587 0.6793 0.0346 /// ``` -pub fn index_gen(input: &Array, indices: Indexer) -> Result { +pub fn index_gen(input: &Array, indices: Indexer) -> Array { unsafe{ let mut temp: i64 = 0; let err_val = af_index_gen(&mut temp as MutAfArray, input.get() as AfArray, indices.len() as DimT, indices.get() as *const IndexT); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -380,9 +355,9 @@ pub fn index_gen(input: &Array, indices: Indexer) -> Result { /// ``` /// use arrayfire::{Array, Dim4, Seq, print, randu, constant, Indexer, assign_gen}; /// let values: &[f32] = &[1.0, 2.0, 3.0]; -/// let indices = Array::new(values, Dim4::new(&[3, 1, 1, 1])).unwrap(); +/// let indices = Array::new(values, Dim4::new(&[3, 1, 1, 1])); /// let seq4gen = Seq::new(0.0, 2.0, 1.0); -/// let a = randu::(Dim4::new(&[5, 3, 1, 1])).unwrap(); +/// let a = randu::(Dim4::new(&[5, 3, 1, 1])); /// // [5 3 1 1] /// // 0.0000 0.2190 0.3835 /// // 0.1315 0.0470 0.5194 @@ -390,17 +365,14 @@ pub fn index_gen(input: &Array, indices: Indexer) -> Result { /// // 0.4587 0.6793 0.0346 /// // 0.5328 0.9347 0.0535 /// -/// let b = constant(2.0 as f32, Dim4::new(&[3, 3, 1, 1])).unwrap(); +/// let b = constant(2.0 as f32, Dim4::new(&[3, 3, 1, 1])); /// -/// let mut idxrs = match Indexer::new() { -/// Ok(v) => v, -/// Err(e) => panic!("{}",e), -/// }; -/// idxrs.set_index(&indices, 0, None).unwrap(); // 2nd parameter is indexing dimension -/// idxrs.set_index(&seq4gen, 1, Some(false)).unwrap(); // 3rd parameter indicates batch operation +/// let mut idxrs = Indexer::new(); +/// idxrs.set_index(&indices, 0, None); // 2nd parameter is indexing dimension +/// idxrs.set_index(&seq4gen, 1, Some(false)); // 3rd parameter indicates batch operation /// -/// let sub2 = assign_gen(&a, &idxrs, &b).unwrap(); -/// println!("a(indices, seq(0, 2, 1))"); print(&sub2).unwrap(); +/// let sub2 = assign_gen(&a, &idxrs, &b); +/// println!("a(indices, seq(0, 2, 1))"); print(&sub2); /// // [5 3 1 1] /// // 0.0000 0.2190 0.3835 /// // 2.0000 2.0000 2.0000 @@ -408,16 +380,14 @@ pub fn index_gen(input: &Array, indices: Indexer) -> Result { /// // 2.0000 2.0000 2.0000 /// // 0.5328 0.9347 0.0535 /// ``` -pub fn assign_gen(lhs: &Array, indices: &Indexer, rhs: &Array) -> Result { +pub fn assign_gen(lhs: &Array, indices: &Indexer, rhs: &Array) -> Array { unsafe{ let mut temp: i64 = 0; let err_val = af_assign_gen(&mut temp as MutAfArray, lhs.get() as AfArray, indices.len() as DimT, indices.get() as *const IndexT, rhs.get() as AfArray); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -436,4 +406,4 @@ impl SeqInternal { step: From::from(s.step()), } } -} +} \ No newline at end of file diff --git a/src/lapack/mod.rs b/src/lapack/mod.rs index e7a32e000..3afec476e 100644 --- a/src/lapack/mod.rs +++ b/src/lapack/mod.rs @@ -1,8 +1,8 @@ extern crate libc; use array::Array; -use defines::AfError; -use defines::{MatProp, NormType}; +use defines::{AfError, MatProp, NormType}; +use error::HANDLE_ERROR; use util::to_u32; use self::libc::{uint8_t, c_int, c_uint, c_double}; @@ -53,17 +53,15 @@ extern { /// /// The third Array is the output array containing V ^ H #[allow(unused_mut)] -pub fn svd(input: &Array) -> Result<(Array, Array, Array), AfError> { +pub fn svd(input: &Array) -> (Array, Array, Array) { unsafe { let mut u: i64 = 0; let mut s: i64 = 0; let mut vt: i64 = 0; let err_val = af_svd(&mut u as MutAfArray, &mut s as MutAfArray, &mut vt as MutAfArray, input.get() as AfArray); - match err_val { - 0 => Ok((Array::from(u), Array::from(s), Array::from(vt))), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + (Array::from(u), Array::from(s), Array::from(vt)) } } @@ -92,17 +90,15 @@ pub fn svd(input: &Array) -> Result<(Array, Array, Array), AfError> { /// /// The third Array is the output array containing V ^ H #[allow(unused_mut)] -pub fn svd_inplace(input: &mut Array) -> Result<(Array, Array, Array), AfError> { +pub fn svd_inplace(input: &mut Array) -> (Array, Array, Array) { unsafe { let mut u: i64 = 0; let mut s: i64 = 0; let mut vt: i64 = 0; let err_val = af_svd_inplace(&mut u as MutAfArray, &mut s as MutAfArray, &mut vt as MutAfArray, input.get() as AfArray); - match err_val { - 0 => Ok((Array::from(u), Array::from(s), Array::from(vt))), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + (Array::from(u), Array::from(s), Array::from(vt)) } } @@ -122,17 +118,15 @@ pub fn svd_inplace(input: &mut Array) -> Result<(Array, Array, Array), AfError> /// /// The third Array will contain the permutation indices to map the input to the decomposition. #[allow(unused_mut)] -pub fn lu(input: &Array) -> Result<(Array, Array, Array), AfError> { +pub fn lu(input: &Array) -> (Array, Array, Array) { unsafe { let mut lower: i64 = 0; let mut upper: i64 = 0; let mut pivot: i64 = 0; let err_val = af_lu(&mut lower as MutAfArray, &mut upper as MutAfArray, &mut pivot as MutAfArray, input.get() as AfArray); - match err_val { - 0 => Ok((Array::from(lower), Array::from(upper), Array::from(pivot))), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + (Array::from(lower), Array::from(upper), Array::from(pivot)) } } @@ -148,15 +142,13 @@ pub fn lu(input: &Array) -> Result<(Array, Array, Array), AfError> { /// An Array with permutation indices to map the input to the decomposition. Since, the input /// matrix is modified in place, only pivot values are returned. #[allow(unused_mut)] -pub fn lu_inplace(input: &mut Array, is_lapack_piv: bool) -> Result { +pub fn lu_inplace(input: &mut Array, is_lapack_piv: bool) -> Array { unsafe { let mut pivot: i64 = 0; let err_val = af_lu_inplace(&mut pivot as MutAfArray, input.get() as AfArray, is_lapack_piv as c_int); - match err_val { - 0 => Ok(Array::from(pivot)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(pivot) } } @@ -177,17 +169,15 @@ pub fn lu_inplace(input: &mut Array, is_lapack_piv: bool) -> Result Result<(Array, Array, Array), AfError> { +pub fn qr(input: &Array) -> (Array, Array, Array) { unsafe { let mut q: i64 = 0; let mut r: i64 = 0; let mut tau: i64 = 0; let err_val = af_qr(&mut q as MutAfArray, &mut r as MutAfArray, &mut tau as MutAfArray, input.get() as AfArray); - match err_val { - 0 => Ok((Array::from(q), Array::from(r), Array::from(tau))), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + (Array::from(q), Array::from(r), Array::from(tau)) } } @@ -201,14 +191,12 @@ pub fn qr(input: &Array) -> Result<(Array, Array, Array), AfError> { /// /// An Array with additional information needed for unpacking the data. #[allow(unused_mut)] -pub fn qr_inplace(input: &mut Array) -> Result { +pub fn qr_inplace(input: &mut Array) -> Array { unsafe { let mut tau: i64 = 0; let err_val = af_qr_inplace(&mut tau as MutAfArray, input.get() as AfArray); - match err_val { - 0 => Ok(Array::from(tau)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(tau) } } @@ -228,16 +216,14 @@ pub fn qr_inplace(input: &mut Array) -> Result { /// If the integer is 0, it means the cholesky decomposition passed. Otherwise, it will contain the rank at /// which the decomposition failed. #[allow(unused_mut)] -pub fn cholesky(input: &Array, is_upper: bool) -> Result<(Array, i32), AfError> { +pub fn cholesky(input: &Array, is_upper: bool) -> (Array, i32) { unsafe { let mut temp: i64 = 0; let mut info: i32 = 0; let err_val = af_cholesky(&mut temp as MutAfArray, &mut info as *mut c_int, input.get() as AfArray, is_upper as c_int); - match err_val { - 0 => Ok((Array::from(temp), info)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + (Array::from(temp), info) } } @@ -253,15 +239,13 @@ pub fn cholesky(input: &Array, is_upper: bool) -> Result<(Array, i32), AfError> /// A signed 32-bit integer. If the integer is 0, it means the cholesky decomposition passed. Otherwise, /// it will contain the rank at which the decomposition failed. #[allow(unused_mut)] -pub fn cholesky_inplace(input: &mut Array, is_upper: bool) -> Result { +pub fn cholesky_inplace(input: &mut Array, is_upper: bool) -> i32 { unsafe { let mut info: i32 = 0; let err_val = af_cholesky_inplace(&mut info as *mut c_int, input.get() as AfArray, is_upper as c_int); - match err_val { - 0 => Ok(info), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + info } } @@ -279,15 +263,13 @@ pub fn cholesky_inplace(input: &mut Array, is_upper: bool) -> Result Result { +pub fn solve(a: &Array, b: &Array, options: MatProp) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_solve(&mut temp as MutAfArray, a.get() as AfArray, b.get() as AfArray, to_u32(options) as c_uint); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -307,15 +289,13 @@ pub fn solve(a: &Array, b: &Array, options: MatProp) -> Result { /// An Array which is the matrix of unknown variables #[allow(unused_mut)] pub fn solve_lu(a: &Array, piv: &Array, b: &Array, - options: MatProp) -> Result { + options: MatProp) -> Array { unsafe { let mut temp: i64 = 0; let err_val = 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); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -332,14 +312,12 @@ pub fn solve_lu(a: &Array, piv: &Array, b: &Array, /// /// An Array with values of the inverse of input matrix. #[allow(unused_mut)] -pub fn inverse(input: &Array, options: MatProp) -> Result { +pub fn inverse(input: &Array, options: MatProp) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_inverse(&mut temp as MutAfArray, input.get() as AfArray, to_u32(options) as c_uint); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -354,14 +332,12 @@ pub fn inverse(input: &Array, options: MatProp) -> Result { /// /// An unsigned 32-bit integer which is the rank of the input matrix. #[allow(unused_mut)] -pub fn rank(input: &Array, tol: f64) -> Result { +pub fn rank(input: &Array, tol: f64) -> u32 { unsafe { let mut temp: u32 = 0; let err_val = af_rank(&mut temp as *mut c_uint, input.get() as AfArray, tol as c_double); - match err_val { - 0 => Ok(temp), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + temp } } @@ -377,15 +353,13 @@ pub fn rank(input: &Array, tol: f64) -> Result { /// /// If the input matrix is non-complex type, only first values of tuple contains the result. #[allow(unused_mut)] -pub fn det(input: &Array) -> Result<(f64, f64), AfError> { +pub fn det(input: &Array) -> (f64, f64) { unsafe { let mut real: f64 = 0.0; let mut imag: f64 = 0.0; let err_val = af_det(&mut real as MutDouble, &mut imag as MutDouble, input.get() as AfArray); - match err_val { - 0 => Ok((real, imag)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + (real, imag) } } @@ -404,15 +378,13 @@ pub fn det(input: &Array) -> Result<(f64, f64), AfError> { /// /// A 64-bit floating point value that contains the norm of input matrix. #[allow(unused_mut)] -pub fn norm(input: &Array, ntype: NormType, p: f64, q: f64) -> Result { +pub fn norm(input: &Array, ntype: NormType, p: f64, q: f64) -> f64 { unsafe { let mut out: f64 = 0.0; let err_val = af_norm(&mut out as MutDouble, input.get() as AfArray, ntype as uint8_t, p as c_double, q as c_double); - match err_val { - 0 => Ok(out), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + out } } @@ -431,4 +403,4 @@ pub fn is_lapack_available() -> bool { af_is_lapack_available(&mut temp as *mut c_int); temp > 0 // Return boolean fla } -} +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index c72da3459..a0658424e 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,7 +41,7 @@ pub use device::{get_version, info, init, device_count, is_double_available, set pub use device::{device_mem_info, print_mem_info, set_mem_step_size, get_mem_step_size, device_gc, sync}; mod device; -pub use defines::{Aftype, AfError, Backend, ColorMap, YCCStd, HomographyType}; +pub use defines::{DType, AfError, Backend, ColorMap, YCCStd, HomographyType}; pub use defines::{InterpType, BorderType, MatchType, NormType}; pub use defines::{Connectivity, ConvMode, ConvDomain, ColorSpace, MatProp}; pub use defines::{MarkerType}; @@ -50,6 +50,9 @@ mod defines; pub use dim4::Dim4; mod dim4; +pub use error::{register_error_handler,handle_error_general}; +mod error; + pub use index::{Indexer, index, row, rows, col, cols, slice, slices, set_row, set_rows, set_col, set_cols, set_slice, set_slices, lookup, assign_seq, index_gen, assign_gen}; diff --git a/src/macros.rs b/src/macros.rs index 213be2e6d..bc509379a 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -41,7 +41,7 @@ /// use arrayfire::{Dim4, device_mem_info, print, randu}; /// /// let dims = Dim4::new(&[5, 5, 1, 1]); -/// let a = randu::(dims).unwrap(); +/// let a = randu::(dims); /// print(&a); /// mem_info!("Hello!"); /// # } @@ -58,7 +58,7 @@ macro_rules! mem_info { [$msg: expr] => { { - let (abytes, abuffs, lbytes, lbuffs) = device_mem_info().unwrap(); + let (abytes, abuffs, lbytes, lbuffs) = device_mem_info(); println!("AF Memory: {:?}", $msg); println!("Allocated [Bytes | Buffers] = [ {} | {} ]", abytes, abuffs); println!("In Use [Bytes | Buffers] = [ {} | {} ]", lbytes, lbuffs); @@ -78,11 +78,11 @@ macro_rules! mem_info { /// # fn main() { /// use arrayfire::{Dim4, join_many, print, randu}; /// -/// let a = &randu::(Dim4::new(&[5, 3, 1, 1])).unwrap(); -/// let b = &randu::(Dim4::new(&[5, 3, 1, 1])).unwrap(); -/// let c = &randu::(Dim4::new(&[5, 3, 1, 1])).unwrap(); +/// let a = &randu::(Dim4::new(&[5, 3, 1, 1])); +/// let b = &randu::(Dim4::new(&[5, 3, 1, 1])); +/// let c = &randu::(Dim4::new(&[5, 3, 1, 1])); /// let d = join_many![2; a, b, c]; -/// print(&d.unwrap()); +/// print(&d); /// # } /// ``` /// @@ -114,10 +114,7 @@ macro_rules! join_many { /// # fn main() { /// use arrayfire::{Dim4, print, randu}; /// let dims = Dim4::new(&[3, 1, 1, 1]); -/// let a = match randu::(dims) { -/// Ok(value) => value, -/// Err(error) => panic!("{}", error), -/// }; +/// let a = randu::(dims); /// af_print!("Create a 5-by-3 matrix of random floats on the GPU", a); /// # } /// ``` @@ -127,7 +124,7 @@ macro_rules! af_print { [$msg: expr, $x: ident] => { { println!("{}", $msg); - print(&$x).unwrap(); + print(&$x); } }; } diff --git a/src/signal/mod.rs b/src/signal/mod.rs index 10e566a81..ac1c385c9 100644 --- a/src/signal/mod.rs +++ b/src/signal/mod.rs @@ -1,10 +1,8 @@ extern crate libc; use array::Array; -use defines::AfError; -use defines::InterpType; -use defines::ConvMode; -use defines::ConvDomain; +use defines::{AfError, ConvDomain, ConvMode, InterpType}; +use error::HANDLE_ERROR; use self::libc::{uint8_t, c_int, c_float, c_double, c_longlong}; type MutAfArray = *mut self::libc::c_longlong; @@ -80,15 +78,13 @@ extern { /// An Array with interpolated values #[allow(unused_mut)] pub fn approx1(input: &Array, pos: &Array, - method: InterpType, off_grid: f32) -> Result { + method: InterpType, off_grid: f32) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_approx1(&mut temp as MutAfArray, input.get() as AfArray, pos.get() as AfArray, method as c_int, off_grid as c_float); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -108,16 +104,14 @@ pub fn approx1(input: &Array, pos: &Array, /// /// An Array with interpolated values pub fn approx2(input: &Array, pos0: &Array, pos1: &Array, - method: InterpType, off_grid: f32) -> Result { + method: InterpType, off_grid: f32) -> Array { unsafe { let mut temp: i64 = 0; let err_val = 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); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -135,16 +129,14 @@ pub fn approx2(input: &Array, pos0: &Array, pos1: &Array, /// /// Transformed Array #[allow(unused_mut)] -pub fn fft(input: &Array, norm_factor: f64, odim0: i64) -> Result { +pub fn fft(input: &Array, norm_factor: f64, odim0: i64) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_fft(&mut temp as MutAfArray, input.get() as AfArray, norm_factor as c_double, odim0 as c_longlong); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -162,16 +154,14 @@ pub fn fft(input: &Array, norm_factor: f64, odim0: i64) -> Result Result { +pub fn fft2(input: &Array, norm_factor: f64, odim0: i64, odim1: i64) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_fft2(&mut temp as MutAfArray, input.get() as AfArray, norm_factor as c_double, odim0 as c_longlong, odim1 as c_longlong); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -191,16 +181,14 @@ pub fn fft2(input: &Array, norm_factor: f64, odim0: i64, odim1: i64) -> Result Result { + odim0: i64, odim1: i64, odim2: i64) -> Array { unsafe { let mut temp: i64 = 0; let err_val = 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); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -218,16 +206,14 @@ pub fn fft3(input: &Array, norm_factor: f64, /// /// Transformed Array #[allow(unused_mut)] -pub fn ifft(input: &Array, norm_factor: f64, odim0: i64) -> Result { +pub fn ifft(input: &Array, norm_factor: f64, odim0: i64) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_ifft(&mut temp as MutAfArray, input.get() as AfArray, norm_factor as c_double, odim0 as c_longlong); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -245,16 +231,14 @@ pub fn ifft(input: &Array, norm_factor: f64, odim0: i64) -> Result Result { +pub fn ifft2(input: &Array, norm_factor: f64, odim0: i64, odim1: i64) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_ifft2(&mut temp as MutAfArray, input.get() as AfArray, norm_factor as c_double, odim0 as c_longlong, odim1 as c_longlong); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -274,16 +258,14 @@ pub fn ifft2(input: &Array, norm_factor: f64, odim0: i64, odim1: i64) -> Result< /// Transformed Array #[allow(unused_mut)] pub fn ifft3(input: &Array, norm_factor: f64, - odim0: i64, odim1: i64, odim2: i64) -> Result { + odim0: i64, odim1: i64, odim2: i64) -> Array { unsafe { let mut temp: i64 = 0; let err_val = 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); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -312,16 +294,14 @@ macro_rules! conv_func_def { /// The convolved Array #[allow(unused_mut)] pub fn $fn_name(signal: &Array, filter: &Array, - mode: ConvMode, domain: ConvDomain) -> Result { + mode: ConvMode, domain: ConvDomain) -> Array { unsafe { let mut temp: i64 = 0; let err_val = $ffi_name(&mut temp as MutAfArray, signal.get() as AfArray, filter.get() as AfArray, mode as uint8_t, domain as uint8_t); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } ) @@ -345,16 +325,14 @@ conv_func_def!(convolve3, af_convolve3); /// The convolved Array #[allow(unused_mut)] pub fn convolve2_sep(cfilt: &Array, rfilt: &Array, signal: &Array, - mode: ConvMode) -> Result { + mode: ConvMode) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_convolve2_sep(&mut temp as MutAfArray, cfilt.get() as AfArray, rfilt.get() as AfArray, signal.get() as AfArray, mode as uint8_t); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -381,15 +359,13 @@ macro_rules! fft_conv_func_def { /// The convolved Array #[allow(unused_mut)] pub fn $fn_name(signal: &Array, filter: &Array, - mode: ConvMode) -> Result { + mode: ConvMode) -> Array { unsafe { let mut temp: i64 = 0; let err_val = $ffi_name(&mut temp as MutAfArray, signal.get() as AfArray, filter.get() as AfArray, mode as uint8_t); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } ) @@ -410,14 +386,12 @@ fft_conv_func_def!(fft_convolve3, af_fft_convolve3); /// /// Filtered Array #[allow(unused_mut)] -pub fn fir(b: &Array, x: &Array) -> Result { +pub fn fir(b: &Array, x: &Array) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_fir(&mut temp as MutAfArray, b.get() as AfArray, x.get() as AfArray); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -433,15 +407,13 @@ pub fn fir(b: &Array, x: &Array) -> Result { /// /// Filtered Array #[allow(unused_mut)] -pub fn iir(b: &Array, a: &Array, x: &Array) -> Result { +pub fn iir(b: &Array, a: &Array, x: &Array) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_iir(&mut temp as MutAfArray, b.get() as AfArray, a.get() as AfArray, x.get() as AfArray); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -451,13 +423,10 @@ pub fn iir(b: &Array, a: &Array, x: &Array) -> Result { /// /// - `input` is the input Array /// - `norm_factor` is the normalization factor -pub fn fft_inplace(input: &Array, norm_factor: f64) -> Result<(), AfError> { +pub fn fft_inplace(input: &Array, norm_factor: f64) { unsafe { let err_val = af_fft_inplace(input.get() as AfArray, norm_factor as c_double); - match err_val { - 0 => Ok(()), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); } } @@ -467,13 +436,10 @@ pub fn fft_inplace(input: &Array, norm_factor: f64) -> Result<(), AfError> { /// /// - `input` is the input Array /// - `norm_factor` is the normalization factor -pub fn fft2_inplace(input: &Array, norm_factor: f64) -> Result<(), AfError> { +pub fn fft2_inplace(input: &Array, norm_factor: f64) { unsafe { let err_val = af_fft2_inplace(input.get() as AfArray, norm_factor as c_double); - match err_val { - 0 => Ok(()), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); } } @@ -483,13 +449,10 @@ pub fn fft2_inplace(input: &Array, norm_factor: f64) -> Result<(), AfError> { /// /// - `input` is the input Array /// - `norm_factor` is the normalization factor -pub fn fft3_inplace(input: &Array, norm_factor: f64) -> Result<(), AfError> { +pub fn fft3_inplace(input: &Array, norm_factor: f64) { unsafe { let err_val = af_fft3_inplace(input.get() as AfArray, norm_factor as c_double); - match err_val { - 0 => Ok(()), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); } } @@ -499,13 +462,10 @@ pub fn fft3_inplace(input: &Array, norm_factor: f64) -> Result<(), AfError> { /// /// - `input` is the input Array /// - `norm_factor` is the normalization factor -pub fn ifft_inplace(input: &Array, norm_factor: f64) -> Result<(), AfError> { +pub fn ifft_inplace(input: &Array, norm_factor: f64) { unsafe { let err_val = af_ifft_inplace(input.get() as AfArray, norm_factor as c_double); - match err_val { - 0 => Ok(()), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); } } @@ -515,13 +475,10 @@ pub fn ifft_inplace(input: &Array, norm_factor: f64) -> Result<(), AfError> { /// /// - `input` is the input Array /// - `norm_factor` is the normalization factor -pub fn ifft2_inplace(input: &Array, norm_factor: f64) -> Result<(), AfError> { +pub fn ifft2_inplace(input: &Array, norm_factor: f64) { unsafe { let err_val = af_ifft2_inplace(input.get() as AfArray, norm_factor as c_double); - match err_val { - 0 => Ok(()), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); } } @@ -531,13 +488,10 @@ pub fn ifft2_inplace(input: &Array, norm_factor: f64) -> Result<(), AfError> { /// /// - `input` is the input Array /// - `norm_factor` is the normalization factor -pub fn ifft3_inplace(input: &Array, norm_factor: f64) -> Result<(), AfError> { +pub fn ifft3_inplace(input: &Array, norm_factor: f64) { unsafe { let err_val = af_ifft3_inplace(input.get() as AfArray, norm_factor as c_double); - match err_val { - 0 => Ok(()), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); } } @@ -552,15 +506,13 @@ pub fn ifft3_inplace(input: &Array, norm_factor: f64) -> Result<(), AfError> { /// # Return Values /// /// Complex Array -pub fn fft_r2c(input: &Array, norm_factor: f64, pad0: i64) -> Result { +pub fn fft_r2c(input: &Array, norm_factor: f64, pad0: i64) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_fft_r2c(&mut temp as MutAfArray, input.get() as AfArray, norm_factor as c_double, pad0 as c_longlong); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -576,15 +528,13 @@ pub fn fft_r2c(input: &Array, norm_factor: f64, pad0: i64) -> Result Result { +pub fn fft2_r2c(input: &Array, norm_factor: f64, pad0: i64, pad1: i64) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_fft2_r2c(&mut temp as MutAfArray, input.get() as AfArray, norm_factor as c_double, pad0 as c_longlong, pad1 as c_longlong); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -601,16 +551,14 @@ pub fn fft2_r2c(input: &Array, norm_factor: f64, pad0: i64, pad1: i64) -> Result /// # Return Values /// /// Complex Array -pub fn fft3_r2c(input: &Array, norm_factor: f64, pad0: i64, pad1: i64, pad2: i64) -> Result { +pub fn fft3_r2c(input: &Array, norm_factor: f64, pad0: i64, pad1: i64, pad2: i64) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_fft3_r2c(&mut temp as MutAfArray, input.get() as AfArray, norm_factor as c_double, pad0 as c_longlong, pad1 as c_longlong, pad2 as c_longlong); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -625,15 +573,13 @@ pub fn fft3_r2c(input: &Array, norm_factor: f64, pad0: i64, pad1: i64, pad2: i64 /// # Return Values /// /// Complex Array -pub fn fft_c2r(input: &Array, norm_factor: f64, is_odd: bool) -> Result { +pub fn fft_c2r(input: &Array, norm_factor: f64, is_odd: bool) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_fft_c2r(&mut temp as MutAfArray, input.get() as AfArray, norm_factor as c_double, is_odd as c_int); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -648,15 +594,13 @@ pub fn fft_c2r(input: &Array, norm_factor: f64, is_odd: bool) -> Result Result { +pub fn fft2_c2r(input: &Array, norm_factor: f64, is_odd: bool) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_fft2_c2r(&mut temp as MutAfArray, input.get() as AfArray, norm_factor as c_double, is_odd as c_int); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -671,14 +615,12 @@ pub fn fft2_c2r(input: &Array, norm_factor: f64, is_odd: bool) -> Result Result { +pub fn fft3_c2r(input: &Array, norm_factor: f64, is_odd: bool) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_fft3_c2r(&mut temp as MutAfArray, input.get() as AfArray, norm_factor as c_double, is_odd as c_int); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } -} +} \ No newline at end of file diff --git a/src/statistics/mod.rs b/src/statistics/mod.rs index b01327006..12ccea02f 100644 --- a/src/statistics/mod.rs +++ b/src/statistics/mod.rs @@ -2,6 +2,7 @@ extern crate libc; use array::Array; use defines::AfError; +use error::HANDLE_ERROR; use self::libc::{c_int}; type MutAfArray = *mut self::libc::c_longlong; @@ -46,14 +47,12 @@ macro_rules! stat_func_def { /// An Array whose size is equal to input except along the dimension which the stat /// operation is performed. Array size along `dim` will be reduced to one. #[allow(unused_mut)] - pub fn $fn_name(input: &Array, dim: i64) -> Result { + pub fn $fn_name(input: &Array, dim: i64) -> Array { unsafe { let mut temp: i64 = 0; let err_val = $ffi_fn(&mut temp as MutAfArray, input.get() as AfArray, dim as DimT); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } ) @@ -78,15 +77,13 @@ macro_rules! stat_wtd_func_def { /// An Array whose size is equal to input except along the dimension which the stat /// operation is performed. Array size along `dim` will be reduced to one. #[allow(unused_mut)] - pub fn $fn_name(input: &Array, weights: &Array, dim: i64) -> Result { + pub fn $fn_name(input: &Array, weights: &Array, dim: i64) -> Array { unsafe { let mut temp: i64 = 0; let err_val = $ffi_fn(&mut temp as MutAfArray, input.get() as AfArray, weights.get() as AfArray, dim as DimT); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } ) @@ -107,15 +104,13 @@ stat_wtd_func_def!(var_weighted, af_var_weighted); /// /// Array with variance of input Array `arr` along dimension `dim`. #[allow(unused_mut)] -pub fn var(arr: &Array, isbiased: bool, dim: i64) -> Result { +pub fn var(arr: &Array, isbiased: bool, dim: i64) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_var(&mut temp as MutAfArray, arr.get() as AfArray, isbiased as c_int, dim as DimT); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -131,15 +126,13 @@ pub fn var(arr: &Array, isbiased: bool, dim: i64) -> Result { /// /// An Array with Covariance values #[allow(unused_mut)] -pub fn cov(x: &Array, y: &Array, isbiased: bool) -> Result { +pub fn cov(x: &Array, y: &Array, isbiased: bool) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_cov(&mut temp as MutAfArray, x.get() as AfArray, y.get() as AfArray, isbiased as c_int); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -154,16 +147,14 @@ pub fn cov(x: &Array, y: &Array, isbiased: bool) -> Result { /// /// A tuple of 64-bit floating point values that has the variance of `input` Array. #[allow(unused_mut)] -pub fn var_all(input: &Array, isbiased: bool) -> Result<(f64, f64), AfError> { +pub fn var_all(input: &Array, isbiased: bool) -> (f64, f64) { unsafe { let mut real: f64 = 0.0; let mut imag: f64 = 0.0; let err_val = af_var_all(&mut real as MutDouble, &mut imag as MutDouble, input.get() as AfArray, isbiased as c_int); - match err_val { - 0 => Ok((real, imag)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + (real, imag) } } @@ -179,16 +170,14 @@ macro_rules! stat_all_func_def { /// /// A tuple of 64-bit floating point values with the stat values. #[allow(unused_mut)] - pub fn $fn_name(input: &Array) -> Result<(f64, f64), AfError> { + pub fn $fn_name(input: &Array) -> (f64, f64) { unsafe { let mut real: f64 = 0.0; let mut imag: f64 = 0.0; let err_val = $ffi_fn(&mut real as MutDouble, &mut imag as MutDouble, input.get() as AfArray); - match err_val { - 0 => Ok((real, imag)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + (real, imag) } } ) @@ -211,16 +200,14 @@ macro_rules! stat_wtd_all_func_def { /// /// A tuple of 64-bit floating point values with the stat values. #[allow(unused_mut)] - pub fn $fn_name(input: &Array, weights: &Array) -> Result<(f64, f64), AfError> { + pub fn $fn_name(input: &Array, weights: &Array) -> (f64, f64) { unsafe { let mut real: f64 = 0.0; let mut imag: f64 = 0.0; let err_val = $ffi_fn(&mut real as MutDouble, &mut imag as MutDouble, input.get() as AfArray, weights.get() as AfArray); - match err_val { - 0 => Ok((real, imag)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + (real, imag) } } ) @@ -239,15 +226,13 @@ stat_wtd_all_func_def!(var_all_weighted, af_var_all_weighted); /// # Return Values /// A tuple of 64-bit floating point values with the coefficients. #[allow(unused_mut)] -pub fn corrcoef(x: &Array, y: &Array) -> Result<(f64, f64), AfError> { +pub fn corrcoef(x: &Array, y: &Array) -> (f64, f64) { unsafe { let mut real: f64 = 0.0; let mut imag: f64 = 0.0; let err_val = af_corrcoef(&mut real as MutDouble, &mut imag as MutDouble, x.get() as AfArray, y.get() as AfArray); - match err_val { - 0 => Ok((real, imag)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + (real, imag) } -} +} \ No newline at end of file diff --git a/src/util.rs b/src/util.rs index 201a543bc..8fa568aa9 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,13 +1,6 @@ extern crate num; -use defines::AfError; -use defines::Aftype; -use defines::InterpType; -use defines::ConvMode; -use defines::ConvDomain; -use defines::MatProp; -use defines::MatchType; -use defines::ColorMap; +use defines::{AfError, ColorMap, ConvDomain, ConvMode, DType, InterpType, MatProp, MatchType}; use std::mem; use self::num::Complex; @@ -18,9 +11,9 @@ impl From for AfError { } } -impl From for Aftype { - fn from(t: u8) -> Aftype { - assert!(Aftype::F32 as u8 <= t && t <= Aftype::U64 as u8); +impl From for DType { + fn from(t: u8) -> DType { + assert!(DType::F32 as u8 <= t && t <= DType::U64 as u8); unsafe { mem::transmute(t) } } } @@ -97,30 +90,30 @@ impl From for ColorMap { /// - u16 /// pub trait HasAfEnum { - fn get_af_dtype() -> Aftype; + fn get_af_dtype() -> DType; } macro_rules! impl_has_af_enum { ($rust_t: ty, $af_dtype: expr) => ( impl HasAfEnum for $rust_t { - fn get_af_dtype() -> Aftype { + fn get_af_dtype() -> DType { $af_dtype } } ) } -impl_has_af_enum!(f32, Aftype::F32); -impl_has_af_enum!(Complex, Aftype::C32); -impl_has_af_enum!(f64, Aftype::F64); -impl_has_af_enum!(Complex, Aftype::C64); +impl_has_af_enum!(f32, DType::F32); +impl_has_af_enum!(Complex, DType::C32); +impl_has_af_enum!(f64, DType::F64); +impl_has_af_enum!(Complex, DType::C64); // FIXME: Rust bool may become incompatible in memory layout with C-ABI // Currently, it is of size 1-byte -impl_has_af_enum!(bool, Aftype::B8); -impl_has_af_enum!(i32, Aftype::S32); -impl_has_af_enum!(u32, Aftype::U32); -impl_has_af_enum!(u8, Aftype::U8); -impl_has_af_enum!(i64, Aftype::S64); -impl_has_af_enum!(u64, Aftype::U64); -impl_has_af_enum!(i16, Aftype::S16); -impl_has_af_enum!(u16, Aftype::U16); +impl_has_af_enum!(bool, DType::B8); +impl_has_af_enum!(i32, DType::S32); +impl_has_af_enum!(u32, DType::U32); +impl_has_af_enum!(u8, DType::U8); +impl_has_af_enum!(i64, DType::S64); +impl_has_af_enum!(u64, DType::U64); +impl_has_af_enum!(i16, DType::S16); +impl_has_af_enum!(u16, DType::U16); diff --git a/src/vision/mod.rs b/src/vision/mod.rs index 30148d4d8..48791a458 100644 --- a/src/vision/mod.rs +++ b/src/vision/mod.rs @@ -3,6 +3,7 @@ extern crate libc; use std::mem; use array::Array; use defines::{AfError, HomographyType, MatchType}; +use error::HANDLE_ERROR; use util::HasAfEnum; use self::libc::{c_void, uint8_t, c_uint, c_int, c_float, c_double, c_longlong}; @@ -75,19 +76,17 @@ pub struct Features { macro_rules! feat_func_def { ($fn_name: ident, $ffi_name: ident) => ( - pub fn $fn_name(&self) -> Result { + pub fn $fn_name(&self) -> Array { unsafe { let mut temp: i64 = 0; let err_val = $ffi_name(&mut temp as MutAfArray, self.feat as Feat); let temp_array = Array::from(temp); let retained = temp_array.clone(); - unsafe { mem::forget(temp_array); } - - match err_val { - 0 => Ok(retained), - _ => Err(AfError::from(err_val)), - } + mem::forget(temp_array); + + HANDLE_ERROR(AfError::from(err_val)); + retained } } ) @@ -95,28 +94,24 @@ macro_rules! feat_func_def { impl Features { #[allow(unused_mut)] - pub fn new(n: u64) -> Result { + pub fn new(n: u64) -> Features { unsafe { let mut temp: i64 = 0; let err_val = af_create_features(&mut temp as *mut c_longlong as MutFeat, n as DimT); - match err_val { - 0 => Ok(Features {feat: temp}), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Features {feat: temp} } } /// Get total number of features found - pub fn num_features(&self) -> Result { + pub fn num_features(&self) -> i64 { unsafe { let mut temp: i64 = 0; let err_val = af_get_features_num(&mut temp as *mut DimT, self.feat as *const c_longlong as Feat); - match err_val { - 0 => Ok(temp), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + temp } } @@ -137,10 +132,8 @@ impl Clone for Features { let mut temp: i64 = 0; let ret_val = af_retain_features(&mut temp as *mut c_longlong as MutFeat, self.feat as *const c_longlong as Feat); - match ret_val { - 0 => Features {feat: temp}, - _ => panic!("Weak copy of Features failed with error code: {}", ret_val), - } + HANDLE_ERROR(AfError::from(ret_val)); + Features {feat: temp} } } } @@ -149,10 +142,7 @@ impl Drop for Features { fn drop(&mut self) { unsafe { let ret_val = af_release_features(self.feat as *mut c_longlong as *mut c_void); - match ret_val { - 0 => (), - _ => panic!("Weak copy of Features failed with error code: {}", ret_val), - } + HANDLE_ERROR(AfError::from(ret_val)); } } } @@ -187,16 +177,14 @@ impl Drop for Features { /// compute orientation. Size is set to 1 as FAST does not compute multiple scales. #[allow(unused_mut)] pub fn fast(input: &Array, thr: f32, arc_len: u32, - non_max: bool, feat_ratio: f32, edge: u32) -> Result { + non_max: bool, feat_ratio: f32, edge: u32) -> Features { unsafe { let mut temp: i64 = 0; let err_val = 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); - match err_val { - 0 => Ok(Features {feat: temp}), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Features {feat: temp} } } @@ -222,17 +210,15 @@ pub fn fast(input: &Array, thr: f32, arc_len: u32, /// for x and y coordinates and score, while array oreientation & size are set to 0 & 1, /// respectively, since harris doesn't compute that information #[allow(unused_mut)] -pub fn harris(input: &Array, max_corners: u32, min_response: f32, sigma: f32, block_size: u32, k_thr: f32) -> Result { +pub fn harris(input: &Array, max_corners: u32, min_response: f32, sigma: f32, block_size: u32, k_thr: f32) -> Features { unsafe { let mut temp: i64 = 0; let err_val = af_harris(&mut temp as *mut c_longlong as MutFeat, input.get() as AfArray, max_corners as c_uint, min_response as c_float, sigma as c_float, block_size as c_uint, k_thr as c_float); - match err_val { - 0 => Ok(Features {feat: temp}), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Features {feat: temp} } } @@ -260,17 +246,15 @@ pub fn harris(input: &Array, max_corners: u32, min_response: f32, sigma: f32, bl /// This function returns a tuple of [`Features`](./struct.Features.html) and [`Array`](./struct.Array.html). The features objects composed of Arrays for x and y coordinates, score, orientation and size of selected features. The Array object is a two dimensional Array of size Nx8 where N is number of selected features. #[allow(unused_mut)] pub fn orb(input: &Array, fast_thr: f32, max_feat: u32, - scl_fctr: f32, levels: u32, blur_img: bool) -> Result<(Features, Array), AfError> { + scl_fctr: f32, levels: u32, blur_img: bool) -> (Features, Array) { unsafe { let mut f: i64 = 0; let mut d: i64 = 0; let err_val = 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); - match err_val { - 0 => Ok((Features {feat: f}, Array::from(d))), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + (Features {feat: f}, Array::from(d)) } } @@ -308,17 +292,15 @@ pub fn orb(input: &Array, fast_thr: f32, max_feat: u32, /// distance to the Ith query value in the train data array. #[allow(unused_mut)] pub fn hamming_matcher(query: &Array, train: &Array, - dist_dims: i64, n_dist: u32) -> Result<(Array, Array), AfError> { + dist_dims: i64, n_dist: u32) -> (Array, Array) { unsafe { let mut idx: i64 = 0; let mut dist:i64 = 0; let err_val = 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); - match err_val { - 0 => Ok((Array::from(idx), Array::from(dist))), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + (Array::from(idx), Array::from(dist)) } } @@ -355,17 +337,15 @@ pub fn hamming_matcher(query: &Array, train: &Array, /// and N is equal to `n_dist`. The value at position IxJ indicates the distance of the Jth smallest /// distance to the Ith query value in the train data array based on the `dist_type` chosen. #[allow(unused_mut)] -pub fn nearest_neighbour(query: &Array, train: &Array, dist_dim: i64, n_dist: u32, dist_type: MatchType) -> Result<(Array, Array), AfError> { +pub fn nearest_neighbour(query: &Array, train: &Array, dist_dim: i64, n_dist: u32, dist_type: MatchType) -> (Array, Array) { unsafe { let mut idx: i64 = 0; let mut dist: i64 = 0; let err_val = af_nearest_neighbour(&mut idx as MutAfArray, &mut dist as MutAfArray, query.get() as AfArray, train.get() as AfArray, dist_dim as DimT, n_dist as c_uint, dist_type as c_int); - match err_val { - 0 => Ok((Array::from(idx), Array::from(dist))), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + (Array::from(idx), Array::from(dist)) } } @@ -385,16 +365,14 @@ pub fn nearest_neighbour(query: &Array, train: &Array, dist_dim: i64, n_dist: u3 /// This function returns an Array with disparity values for the window starting at corresponding pixel position. #[allow(unused_mut)] pub fn match_template(search_img: &Array, template_img: &Array, - mtype: MatchType) -> Result { + mtype: MatchType) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_match_template(&mut temp as MutAfArray, search_img.get() as AfArray, template_img.get() as AfArray, mtype as uint8_t); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -438,17 +416,15 @@ pub fn match_template(search_img: &Array, template_img: &Array, /// # Return Values /// An object of type [Features](./struct.Features.html) composed of arrays for x and y coordinates, score, orientation and size of selected features. #[allow(unused_mut)] -pub fn susan(input: &Array, radius: u32, diff_thr: f32, geom_thr: f32, feature_ratio: f32, edge: u32) -> Result { +pub fn susan(input: &Array, radius: u32, diff_thr: f32, geom_thr: f32, feature_ratio: f32, edge: u32) -> Features { unsafe { let mut temp: i64 = 0; let err_val = af_susan(&mut temp as *mut c_longlong as MutFeat, input.get() as AfArray, radius as c_uint, diff_thr as c_float, geom_thr as c_float, feature_ratio as c_float, edge as c_uint); - match err_val { - 0 => Ok(Features {feat: temp}), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Features {feat: temp} } } @@ -467,15 +443,13 @@ pub fn susan(input: &Array, radius: u32, diff_thr: f32, geom_thr: f32, feature_r /// /// Difference of smoothed inputs - An Array. #[allow(unused_mut)] -pub fn dog(input: &Array, radius1: i32, radius2: i32) -> Result { +pub fn dog(input: &Array, radius1: i32, radius2: i32) -> Array { unsafe { let mut temp: i64 = 0; let err_val = af_dog(&mut temp as MutAfArray, input.get() as AfArray, radius1 as c_int, radius2 as c_int); - match err_val { - 0 => Ok(Array::from(temp)), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) } } @@ -513,7 +487,7 @@ pub fn dog(input: &Array, radius1: i32, radius2: i32) -> Result pub fn homography(x_src: &Array, y_src: &Array, x_dst: &Array, y_dst: &Array, htype: HomographyType, inlier_thr: f32, - iterations: u32) -> Result<(Array, i32), AfError> { + iterations: u32) -> (Array, i32) { unsafe { let otype = OutType::get_af_dtype(); let mut inliers: i32 = 0; @@ -523,9 +497,7 @@ pub fn homography(x_src: &Array, y_src: &Array, x_dst.get() as AfArray, y_dst.get() as AfArray, htype as c_int, inlier_thr as c_float, iterations as c_uint, otype as c_int); - match err_val { - 0 => Ok( (Array::from(temp), inliers) ), - _ => Err(AfError::from(err_val)), - } + HANDLE_ERROR(AfError::from(err_val)); + (Array::from(temp), inliers) } -} +} \ No newline at end of file From 0e191702779416eecb842cf6210c07ea2f14560c Mon Sep 17 00:00:00 2001 From: pradeep Date: Thu, 28 Apr 2016 16:56:17 +0530 Subject: [PATCH 21/37] Replace error strings with Error trait descriptions --- src/defines.rs | 32 ++++++++++++++++---------------- src/error.rs | 22 ++++------------------ src/index.rs | 4 ++-- 3 files changed, 22 insertions(+), 36 deletions(-) diff --git a/src/defines.rs b/src/defines.rs index d33a9fe2b..60cf76350 100644 --- a/src/defines.rs +++ b/src/defines.rs @@ -84,23 +84,23 @@ impl Display for AfError { impl Error for AfError { fn description(&self) -> &str { match *self { - AfError::SUCCESS => "Function returned successfully", - AfError::ERR_NO_MEM => "The system or device ran out of memory", - AfError::ERR_DRIVER => "Device driver error", - AfError::ERR_RUNTIME => "Error in runtime environment", - AfError::ERR_INVALID_ARRAY => "Input is not a valid Array Object", - AfError::ERR_ARG => "One of the function arguments is incorrect", - AfError::ERR_SIZE => "The size is incorrect", - AfError::ERR_TYPE => "The type is not supported by this function", - AfError::ERR_DIFF_TYPE => "The type of input arrays are not compatible", - AfError::ERR_BATCH => "Function does not support GFOR / batch mode", - AfError::ERR_DEVICE => "Array does not belong to device", - AfError::ERR_NOT_SUPPORTED => "The option is not supported", + AfError::SUCCESS => "Function returned successfully", + AfError::ERR_NO_MEM => "System or Device ran out of memory", + AfError::ERR_DRIVER => "Error in the device driver", + AfError::ERR_RUNTIME => "Error with the runtime environment", + AfError::ERR_INVALID_ARRAY => "Iput Array is not a valid object", + AfError::ERR_ARG => "One of the function arguments is incorrect", + AfError::ERR_SIZE => "Size is incorrect", + AfError::ERR_TYPE => "Type is not suppported by this function", + AfError::ERR_DIFF_TYPE => "Type of the input arrays are not compatible", + AfError::ERR_BATCH => "Function does not support GFOR / batch mode", + AfError::ERR_DEVICE => "Input does not belong to the current device", + AfError::ERR_NOT_SUPPORTED => "Unsupported operation/parameter option", AfError::ERR_NOT_CONFIGURED => "This build of ArrayFire does not support this feature", - AfError::ERR_NO_DBL => "This device does not support double", - AfError::ERR_NO_GFX => "This build of ArrayFire was not built with graphics or this device does not support graphics", - AfError::ERR_INTERNAL => "There was an internal error in either ArrayFire or upstream project", - AfError::ERR_UNKNOWN => "Unkown Error", + AfError::ERR_NO_DBL => "This device does not support double", + AfError::ERR_NO_GFX => "This build of ArrayFire has no graphics support", + AfError::ERR_INTERNAL => "Eror either in ArrayFire or in a project upstream", + AfError::ERR_UNKNOWN => "Unknown Error", } } } diff --git a/src/error.rs b/src/error.rs index 875b46d34..eef4a7ff1 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,4 +1,5 @@ use defines::AfError; +use std::error::Error; pub type ErrorCallback = Fn(AfError); @@ -12,22 +13,7 @@ pub fn register_error_handler(callback: &'static ErrorCallback) { pub fn handle_error_general(error_code: AfError) { match error_code { - AfError::SUCCESS => {}, /* No-op */ - AfError::ERR_NO_MEM => panic!("The system or device ran out of memory"), - AfError::ERR_DRIVER => panic!("There was an error in the device driver"), - AfError::ERR_RUNTIME => panic!("There was an error with the runtime environment"), - AfError::ERR_INVALID_ARRAY => panic!("The input array is not a valid Array object"), - AfError::ERR_ARG => panic!("One of the function arguments is incorrect"), - AfError::ERR_SIZE => panic!("The size is incorrect"), - AfError::ERR_TYPE => panic!("The type is not suppported by this function"), - AfError::ERR_DIFF_TYPE => panic!("The type of the input arrays are not compatible"), - AfError::ERR_BATCH => panic!("Function does not support GFOR / batch mode"), - AfError::ERR_DEVICE => panic!("Input does not belong to the current device"), - AfError::ERR_NOT_SUPPORTED => panic!("Unsupported operation/parameter option"), - AfError::ERR_NOT_CONFIGURED => panic!("This build of ArrayFire does not support this feature"), - AfError::ERR_NO_DBL => panic!("This device does not support double"), - AfError::ERR_NO_GFX => panic!("This build of ArrayFire was not built with graphics or this device does not support graphics"), - AfError::ERR_INTERNAL => panic!("There was an internal error either in ArrayFire or in a project upstream"), - AfError::ERR_UNKNOWN => panic!("Unknown Error"), + AfError::SUCCESS => {}, /* No-op */ + _ => panic!("Error message: {}", error_code.description()), } -} \ No newline at end of file +} diff --git a/src/index.rs b/src/index.rs index ba7cdf05b..2da3ed4dc 100644 --- a/src/index.rs +++ b/src/index.rs @@ -187,8 +187,8 @@ pub fn set_rows(input: &Array, new_rows: &Array, first: u64, last: u64) -> Array /// use arrayfire::{Dim4, randu, col, print}; /// let dims = Dim4::new(&[5, 5, 1, 1]); /// let a = randu::(dims); -/// println!("Grab last col of the random matrix"); /// print(&a); +/// println!("Grab last col of the random matrix"); /// print(&col(&a, 4)); /// ``` #[allow(dead_code)] @@ -406,4 +406,4 @@ impl SeqInternal { step: From::from(s.step()), } } -} \ No newline at end of file +} From 81df62d015247e3cbe99bf582223cdb8598c7963 Mon Sep 17 00:00:00 2001 From: pradeep Date: Tue, 3 May 2016 18:34:34 +0530 Subject: [PATCH 22/37] Add static mutex lock for mutable error handler fn handle Add tests directory with a function to check the function `register_error_handler` --- Cargo.toml | 1 + src/error.rs | 8 ++++++++ src/lib.rs | 5 ++++- tests/lib.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 tests/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 3aab53cc5..b6ba1fedd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ build = "build.rs" libc = "0.1.10" num = "0.1.27" time = "0.1.32" +lazy_static = "0.1.*" [build-dependencies] rustc-serialize = "0.3.16" diff --git a/src/error.rs b/src/error.rs index eef4a7ff1..10dcd9f4f 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,11 +1,19 @@ + use defines::AfError; use std::error::Error; +use std::sync::Mutex; pub type ErrorCallback = Fn(AfError); pub static mut HANDLE_ERROR: &'static ErrorCallback = &handle_error_general; +lazy_static! { + static ref HANDLE_ERROR_LOCK: Mutex = Mutex::new(0); +} + +#[allow(unused_must_use)] pub fn register_error_handler(callback: &'static ErrorCallback) { + HANDLE_ERROR_LOCK.lock().unwrap(); unsafe { HANDLE_ERROR = callback; } diff --git a/src/lib.rs b/src/lib.rs index a0658424e..cda800281 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,9 @@ html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://arrayfire.com/docs/rust")] +#[macro_use] +extern crate lazy_static; + pub use array::Array; pub use array::{print}; mod array; @@ -50,7 +53,7 @@ mod defines; pub use dim4::Dim4; mod dim4; -pub use error::{register_error_handler,handle_error_general}; +pub use error::{ErrorCallback, register_error_handler,handle_error_general}; mod error; pub use index::{Indexer, index, row, rows, col, cols, slice, slices, diff --git a/tests/lib.rs b/tests/lib.rs new file mode 100644 index 000000000..ea5851a57 --- /dev/null +++ b/tests/lib.rs @@ -0,0 +1,42 @@ +extern crate arrayfire as af; + +use std::error::Error; +use std::thread; +use std::time::Duration; +use af::*; + +pub fn handler_sample1(error_code: AfError) { + println!("Error handler sample1"); + match error_code { + AfError::SUCCESS => {}, /* No-op */ + _ => panic!("Error message: {}", error_code.description()), + } +} + +pub fn handler_sample2(error_code: AfError) { + println!("Error handler sample2"); + match error_code { + AfError::SUCCESS => {}, /* No-op */ + _ => panic!("Error message: {}", error_code.description()), + } +} + +pub static HANDLE1: &'static ErrorCallback = &handler_sample1; +pub static HANDLE2: &'static ErrorCallback = &handler_sample2; + +#[test] +fn check_error_handler_mutation() { + + for i in 0..4 { + thread::spawn(move || { + if i%2==0 { + register_error_handler(HANDLE2); + } else { + register_error_handler(HANDLE1); + } + }); + } + + thread::sleep(Duration::from_millis(50)); + +} From c1ebe050e2b0db037bb920a8c267b7a52495ce83 Mon Sep 17 00:00:00 2001 From: pradeep Date: Wed, 4 May 2016 16:08:49 +0530 Subject: [PATCH 23/37] Revert mutex related commit # f48af77q Removed an incorrect implementation to provide thread safety for the function register_error_handler. --- Cargo.toml | 1 - src/error.rs | 7 ------- src/lib.rs | 3 --- 3 files changed, 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b6ba1fedd..3aab53cc5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,6 @@ build = "build.rs" libc = "0.1.10" num = "0.1.27" time = "0.1.32" -lazy_static = "0.1.*" [build-dependencies] rustc-serialize = "0.3.16" diff --git a/src/error.rs b/src/error.rs index 10dcd9f4f..0718cb7eb 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,19 +1,12 @@ - use defines::AfError; use std::error::Error; -use std::sync::Mutex; pub type ErrorCallback = Fn(AfError); pub static mut HANDLE_ERROR: &'static ErrorCallback = &handle_error_general; -lazy_static! { - static ref HANDLE_ERROR_LOCK: Mutex = Mutex::new(0); -} - #[allow(unused_must_use)] pub fn register_error_handler(callback: &'static ErrorCallback) { - HANDLE_ERROR_LOCK.lock().unwrap(); unsafe { HANDLE_ERROR = callback; } diff --git a/src/lib.rs b/src/lib.rs index cda800281..0345a1e49 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,9 +2,6 @@ html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://arrayfire.com/docs/rust")] -#[macro_use] -extern crate lazy_static; - pub use array::Array; pub use array::{print}; mod array; From af483c4db3be9b817b02343f2df27313496d76b5 Mon Sep 17 00:00:00 2001 From: pradeep Date: Wed, 4 May 2016 18:49:42 +0530 Subject: [PATCH 24/37] FEATURE: Compound assignment operators Also, modifies binary operators to use Array objects instead of borrowed references. --- examples/helloworld.rs | 4 +-- examples/unified.rs | 6 ++++- src/arith/mod.rs | 56 +++++++++++++++++++++++++++++++++++++++--- 3 files changed, 60 insertions(+), 6 deletions(-) diff --git a/examples/helloworld.rs b/examples/helloworld.rs index ed79171e7..92c4f3633 100644 --- a/examples/helloworld.rs +++ b/examples/helloworld.rs @@ -28,7 +28,7 @@ fn main() { af_print!("sin(a) + cos(a) => ", b2); af_print!("!a => ", b3); - let test = &a + &b; + let test = a.clone() + b.clone(); af_print!("a + b", test); // Index array using sequences @@ -82,4 +82,4 @@ fn main() { let u8_cnst = &constant(1 as u8, dims); af_print!("u8 constant array", u8_cnst); println!("Is u8_cnst array float precision type ? {}", u8_cnst.is_single()); -} \ No newline at end of file +} diff --git a/examples/unified.rs b/examples/unified.rs index bb617caa1..e737bd10a 100644 --- a/examples/unified.rs +++ b/examples/unified.rs @@ -11,7 +11,11 @@ fn test_backend(){ let dims = Dim4::new(&[num_rows, num_cols, 1, 1]); println!("Create a 10-by-10 matrix of random floats on the compute device"); - let a = randu::(dims); + let mut a = randu::(dims); + let b = randu::(dims); + print(&a); + print(&b); + a += b; print(&a); } diff --git a/src/arith/mod.rs b/src/arith/mod.rs index 5c2066ece..86d0a57f7 100644 --- a/src/arith/mod.rs +++ b/src/arith/mod.rs @@ -8,6 +8,9 @@ use error::HANDLE_ERROR; use self::libc::{c_int}; use data::{constant, tile}; use self::num::Complex; +use index::{Indexer, assign_gen}; +use seq::Seq; +use std::mem; type MutAfArray = *mut self::libc::c_longlong; type MutDouble = *mut self::libc::c_double; @@ -15,6 +18,8 @@ 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}; +use std::ops::{AddAssign, SubAssign, DivAssign, MulAssign, BitAndAssign, BitOrAssign, BitXorAssign, +RemAssign, ShlAssign, ShrAssign}; #[allow(dead_code)] extern { @@ -311,10 +316,10 @@ 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 { + impl $op_name for Array { type Output = Array; - fn $fn_name(self, rhs:&'f Array) -> Array { + fn $fn_name(self, rhs: Array) -> Array { unsafe { let mut temp: i64 = 0; let err_val = $ffi_fn(&mut temp as MutAfArray, @@ -336,4 +341,49 @@ 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); \ No newline at end of file +arith_func!(Shr, shr, af_bitshiftr); + +macro_rules! arith_assign_func { + ($op_name:ident, $fn_name:ident, $func: ident) => ( + impl $op_name for Array { + + #[allow(unused_variables)] + fn $fn_name(&mut self, rhs: Array) { + let mut idxrs = Indexer::new(); + idxrs.set_index(&Seq::::default(), 0, Some(false)); + idxrs.set_index(&Seq::::default(), 1, Some(false)); + let tmp = assign_gen(self as &Array, &idxrs, + & $func(self as &Array, &rhs, false)); + mem::replace(self, tmp); + } + } + ) +} + +arith_assign_func!(AddAssign, add_assign, add); +arith_assign_func!(SubAssign, sub_assign, sub); +arith_assign_func!(MulAssign, mul_assign, mul); +arith_assign_func!(DivAssign, div_assign, div); +arith_assign_func!(RemAssign, rem_assign, rem); +arith_assign_func!(ShlAssign, shl_assign, shiftl); +arith_assign_func!(ShrAssign, shr_assign, shiftr); + +macro_rules! bit_assign_func { + ($op_name:ident, $fn_name:ident, $func: ident) => ( + impl $op_name for Array { + + #[allow(unused_variables)] + fn $fn_name(&mut self, rhs: Array) { + let mut idxrs = Indexer::new(); + idxrs.set_index(&Seq::::default(), 0, Some(false)); + idxrs.set_index(&Seq::::default(), 1, Some(false)); + let tmp = assign_gen(self as &Array, &idxrs, & $func(self as &Array, &rhs)); + mem::replace(self, tmp); + } + } + ) +} + +bit_assign_func!(BitAndAssign, bitand_assign, bitand); +bit_assign_func!(BitOrAssign, bitor_assign, bitor); +bit_assign_func!(BitXorAssign, bitxor_assign, bitxor); From df8c153482a9b24f8b6f2217ea85ac67410b7aaa Mon Sep 17 00:00:00 2001 From: pradeep Date: Tue, 17 May 2016 17:01:47 +0530 Subject: [PATCH 25/37] Thread safety for error handler function pointer --- Cargo.toml | 1 + src/error.rs | 51 ++++++++++++++++++++++++++++++++++++++++++++++----- src/lib.rs | 5 ++++- tests/lib.rs | 52 ++++++++++++++++++++++++++++++++++------------------ 4 files changed, 85 insertions(+), 24 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3aab53cc5..1cee85ff5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ build = "build.rs" libc = "0.1.10" num = "0.1.27" time = "0.1.32" +lazy_static = "0.2.1" [build-dependencies] rustc-serialize = "0.3.16" diff --git a/src/error.rs b/src/error.rs index 0718cb7eb..296627d19 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,15 +1,44 @@ +use std::ops::{Deref, DerefMut}; use defines::AfError; use std::error::Error; +use std::marker::{Send, Sync}; +use std::sync::RwLock; + pub type ErrorCallback = Fn(AfError); -pub static mut HANDLE_ERROR: &'static ErrorCallback = &handle_error_general; + +/// Wrap ErrorCallback function pointer inside a structure +/// to enable implementing Send, Sync traits on it. +pub struct Callback<'cblifetime> { + pub cb: &'cblifetime ErrorCallback, +} + + +// Implement Send, Sync traits for Callback structure to +// enable the user of Callback function pointer in conjunction +// with threads using a mutex. +unsafe impl<'cblifetime> Send for Callback<'cblifetime> {} +unsafe impl<'cblifetime> Sync for Callback<'cblifetime> {} + + +pub static DEFAULT_HANDLE_ERROR: &'static ErrorCallback = &handle_error_general; + + +lazy_static! { + static ref ERROR_HANDLER_LOCK: RwLock< Callback<'static> > = + RwLock::new(Callback{cb: DEFAULT_HANDLE_ERROR}); +} + #[allow(unused_must_use)] -pub fn register_error_handler(callback: &'static ErrorCallback) { - unsafe { - HANDLE_ERROR = callback; - } +pub fn register_error_handler(cb_value: &'static ErrorCallback) { + let mut gaurd = match ERROR_HANDLER_LOCK.write() { + Ok(g) => g, + Err(_)=> panic!("Failed to acquire lock to register error handler"), + }; + + *gaurd.deref_mut() = Callback{cb:cb_value}; } pub fn handle_error_general(error_code: AfError) { @@ -18,3 +47,15 @@ pub fn handle_error_general(error_code: AfError) { _ => panic!("Error message: {}", error_code.description()), } } + +#[allow(non_snake_case)] +pub fn HANDLE_ERROR(error_code: AfError) { + let gaurd = match ERROR_HANDLER_LOCK.read() { + Ok(g) => g, + Err(_)=> panic!("Failed to acquire lock while handling FFI return value"), + }; + + let func = gaurd.deref().cb; + + func(error_code); +} diff --git a/src/lib.rs b/src/lib.rs index 0345a1e49..81915aff5 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,9 @@ html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://arrayfire.com/docs/rust")] +#[macro_use] +extern crate lazy_static; + pub use array::Array; pub use array::{print}; mod array; @@ -50,7 +53,7 @@ mod defines; pub use dim4::Dim4; mod dim4; -pub use error::{ErrorCallback, register_error_handler,handle_error_general}; +pub use error::{ErrorCallback, register_error_handler, handle_error_general}; mod error; pub use index::{Indexer, index, row, rows, col, cols, slice, slices, diff --git a/tests/lib.rs b/tests/lib.rs index ea5851a57..21f84762d 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -1,3 +1,4 @@ +#[macro_use] extern crate arrayfire as af; use std::error::Error; @@ -5,38 +6,53 @@ use std::thread; use std::time::Duration; use af::*; -pub fn handler_sample1(error_code: AfError) { - println!("Error handler sample1"); - match error_code { - AfError::SUCCESS => {}, /* No-op */ - _ => panic!("Error message: {}", error_code.description()), - } -} +macro_rules! implement_handler { + ($fn_name:ident, $msg: expr) => ( -pub fn handler_sample2(error_code: AfError) { - println!("Error handler sample2"); - match error_code { - AfError::SUCCESS => {}, /* No-op */ - _ => panic!("Error message: {}", error_code.description()), - } + pub fn $fn_name(error_code: AfError) { + println!("{:?}", $msg); + match error_code { + AfError::SUCCESS => {}, /* No-op */ + _ => panic!("Error message: {}", error_code.description()), + } + } + + ) } +implement_handler!(handler_sample1, "Error Handler Sample1"); +implement_handler!(handler_sample2, "Error Handler Sample2"); +implement_handler!(handler_sample3, "Error Handler Sample3"); +implement_handler!(handler_sample4, "Error Handler Sample4"); + pub static HANDLE1: &'static ErrorCallback = &handler_sample1; pub static HANDLE2: &'static ErrorCallback = &handler_sample2; +pub static HANDLE3: &'static ErrorCallback = &handler_sample3; +pub static HANDLE4: &'static ErrorCallback = &handler_sample4; +#[allow(unused_must_use)] #[test] fn check_error_handler_mutation() { for i in 0..4 { - thread::spawn(move || { - if i%2==0 { - register_error_handler(HANDLE2); - } else { - register_error_handler(HANDLE1); + thread::Builder::new().name(format!("child {}",i+1).to_string()).spawn(move || { + println!("{:?}", thread::current()); + match i { + 0 => register_error_handler(HANDLE1.clone()), + 1 => register_error_handler(HANDLE2.clone()), + 2 => register_error_handler(HANDLE3.clone()), + 3 => register_error_handler(HANDLE4.clone()), + _ => panic!("Impossible scenario"), } + //match i { + // 1 => thread::sleep(Duration::from_millis(20)), + // 2 => thread::sleep(Duration::from_millis(10)), + // _ => (), + //} }); } + af::info(); thread::sleep(Duration::from_millis(50)); } From 8b688824be0a0d89bcf9a987f927a49b32dc4f63 Mon Sep 17 00:00:00 2001 From: pradeep Date: Wed, 18 May 2016 14:54:28 +0530 Subject: [PATCH 26/37] Remove dead code --- tests/lib.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/lib.rs b/tests/lib.rs index 21f84762d..e0f90aac6 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -44,11 +44,6 @@ fn check_error_handler_mutation() { 3 => register_error_handler(HANDLE4.clone()), _ => panic!("Impossible scenario"), } - //match i { - // 1 => thread::sleep(Duration::from_millis(20)), - // 2 => thread::sleep(Duration::from_millis(10)), - // _ => (), - //} }); } From 4a3ad4680bfede8f41b959eb01d486ed02663ff8 Mon Sep 17 00:00:00 2001 From: pradeep Date: Wed, 18 May 2016 23:15:56 +0530 Subject: [PATCH 27/37] Add version check for compound assignment operator traits Fixes #71 Compound operator traits are made stable in Rust 1.8, hence the version check is required --- Cargo.toml | 1 + build.rs | 5 +++++ examples/unified.rs | 25 ++++++++++++++++++------- src/arith/mod.rs | 19 ++++++++++++++----- 4 files changed, 38 insertions(+), 12 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1cee85ff5..5f6ddb98d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ lazy_static = "0.2.1" [build-dependencies] rustc-serialize = "0.3.16" +rustc_version = "0.1.7" [lib] name = "arrayfire" diff --git a/build.rs b/build.rs index b45c5e5ad..3a4df9cca 100644 --- a/build.rs +++ b/build.rs @@ -1,5 +1,6 @@ /* -- Lots of reuse from: https://github.com/alexcrichton/git2-rs/blob/master/libgit2-sys/build.rs */ extern crate rustc_serialize; +extern crate rustc_version; use std::env; use std::fs; @@ -450,4 +451,8 @@ fn main() { for backend_dir in backend_dirs.iter() { println!("cargo:rustc-link-search=native={}", backend_dir); } + // Directly check a semver version requirment + if rustc_version::version_matches(">= 1.8.0") { + println!("cargo:rustc-cfg=op_assign"); + } } diff --git a/examples/unified.rs b/examples/unified.rs index e737bd10a..6ed0e0b77 100644 --- a/examples/unified.rs +++ b/examples/unified.rs @@ -2,21 +2,32 @@ extern crate arrayfire as af; use af::*; +#[cfg(op_assign)] +fn helper(dims: Dim4) { + let mut a = randu::(dims); + let b = randu::(dims); + print(&a); + print(&b); + a += b; + print(&a); +} + +#[cfg(not(op_assign))] +fn helper(dims: Dim4) { + let b = randu::(dims); + print(&b); +} + #[allow(unused_must_use)] fn test_backend(){ info(); + println!("Create a 10-by-10 matrix of random floats on the compute device"); let num_rows: u64 = 10; let num_cols: u64 = 10; let dims = Dim4::new(&[num_rows, num_cols, 1, 1]); - println!("Create a 10-by-10 matrix of random floats on the compute device"); - let mut a = randu::(dims); - let b = randu::(dims); - print(&a); - print(&b); - a += b; - print(&a); + helper(dims) } diff --git a/src/arith/mod.rs b/src/arith/mod.rs index 86d0a57f7..95d710cdd 100644 --- a/src/arith/mod.rs +++ b/src/arith/mod.rs @@ -8,9 +8,6 @@ use error::HANDLE_ERROR; use self::libc::{c_int}; use data::{constant, tile}; use self::num::Complex; -use index::{Indexer, assign_gen}; -use seq::Seq; -use std::mem; type MutAfArray = *mut self::libc::c_longlong; type MutDouble = *mut self::libc::c_double; @@ -18,8 +15,6 @@ 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}; -use std::ops::{AddAssign, SubAssign, DivAssign, MulAssign, BitAndAssign, BitOrAssign, BitXorAssign, -RemAssign, ShlAssign, ShrAssign}; #[allow(dead_code)] extern { @@ -343,6 +338,18 @@ arith_func!(BitXor, bitxor, af_bitxor); arith_func!(Shl, shl, af_bitshiftl); arith_func!(Shr, shr, af_bitshiftr); +#[cfg(op_assign)] +mod op_assign { + +use array::Array; +use super::*; +use index::{Indexer, assign_gen}; +use seq::Seq; +use std::mem; +use std::ops::{AddAssign, SubAssign, DivAssign, MulAssign, RemAssign}; +use std::ops::{BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssign}; + + macro_rules! arith_assign_func { ($op_name:ident, $fn_name:ident, $func: ident) => ( impl $op_name for Array { @@ -387,3 +394,5 @@ macro_rules! bit_assign_func { bit_assign_func!(BitAndAssign, bitand_assign, bitand); bit_assign_func!(BitOrAssign, bitor_assign, bitor); bit_assign_func!(BitXorAssign, bitxor_assign, bitxor); + +} From 96337695c3da8e436aa5ef7820fa76c8501b7db5 Mon Sep 17 00:00:00 2001 From: pradeep Date: Fri, 20 May 2016 21:11:12 +0530 Subject: [PATCH 28/37] Fix for OSX platform w.r.t static arrays For some reason, directly passing a `&[]` to function that is using OpenCL backend is causing a SEGFAULT. This problem is however is not happening with CPU or CUDA backend. Moving the slice to a independent variable and then borrowing a reference is executing as expected on OSX. This may have to do with slices and the memory they are pointing to, but it is quite puzzling why it only happens on one of three backends. --- examples/helloworld.rs | 6 +++--- src/array.rs | 6 +++--- src/index.rs | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/helloworld.rs b/examples/helloworld.rs index 92c4f3633..be21558cd 100644 --- a/examples/helloworld.rs +++ b/examples/helloworld.rs @@ -10,8 +10,8 @@ fn main() { let num_rows: u64 = 5; let num_cols: u64 = 3; - let values: &[f32] = &[1.0, 2.0, 3.0]; - let indices = Array::new(values, Dim4::new(&[3, 1, 1, 1])); + let values: [f32; 3] = [1.0, 2.0, 3.0]; + let indices = Array::new(&values, Dim4::new(&[3, 1, 1, 1])); let dims = Dim4::new(&[num_rows, num_cols, 1, 1]); @@ -19,7 +19,7 @@ fn main() { af_print!("Create a 5-by-3 matrix of random floats on the GPU", a); println!("Element-wise arithmetic"); - let b = add(&sin(&a), &1.5, false); + let b = add(&sin(&a), &1.5f32, false); let b2 = add(&sin(&a), &cos(&a), false); diff --git a/src/array.rs b/src/array.rs index 906d19cd3..890fd9422 100644 --- a/src/array.rs +++ b/src/array.rs @@ -119,8 +119,8 @@ impl Array { /// /// ``` /// use arrayfire::{Array, Dim4, print}; - /// let values: &[f32] = &[1.0, 2.0, 3.0]; - /// let indices = Array::new(values, Dim4::new(&[3, 1, 1, 1])); + /// let values: [f32; 3] = [1.0, 2.0, 3.0]; + /// let indices = Array::new(&values, Dim4::new(&[3, 1, 1, 1])); /// print(&indices); /// ``` #[allow(unused_mut)] @@ -384,4 +384,4 @@ pub fn print(input: &Array) { let err_val = af_print_array(input.get() as AfArray); HANDLE_ERROR(AfError::from(err_val)); } -} \ No newline at end of file +} diff --git a/src/index.rs b/src/index.rs index 2da3ed4dc..d45a93b5e 100644 --- a/src/index.rs +++ b/src/index.rs @@ -315,8 +315,8 @@ pub fn assign_seq(lhs: &Array, seqs: &[Seq], rhs: &Array) -> Array /// /// ``` /// use arrayfire::{Array, Dim4, Seq, print, randu, index_gen, Indexer}; -/// let values: &[f32] = &[1.0, 2.0, 3.0]; -/// let indices = Array::new(values, Dim4::new(&[3, 1, 1, 1])); +/// let values: [f32; 3] = [1.0, 2.0, 3.0]; +/// let indices = Array::new(&values, Dim4::new(&[3, 1, 1, 1])); /// let seq4gen = Seq::new(0.0, 2.0, 1.0); /// let a = randu::(Dim4::new(&[5, 3, 1, 1])); /// // [5 3 1 1] @@ -354,8 +354,8 @@ pub fn index_gen(input: &Array, indices: Indexer) -> Array { /// /// ``` /// use arrayfire::{Array, Dim4, Seq, print, randu, constant, Indexer, assign_gen}; -/// let values: &[f32] = &[1.0, 2.0, 3.0]; -/// let indices = Array::new(values, Dim4::new(&[3, 1, 1, 1])); +/// let values: [f32; 3] = [1.0, 2.0, 3.0]; +/// let indices = Array::new(&values, Dim4::new(&[3, 1, 1, 1])); /// let seq4gen = Seq::new(0.0, 2.0, 1.0); /// let a = randu::(Dim4::new(&[5, 3, 1, 1])); /// // [5 3 1 1] From 8c7385ab35de0ac27f35dc8664e2cfa1db2ce860 Mon Sep 17 00:00:00 2001 From: pradeep Date: Fri, 20 May 2016 22:17:40 +0530 Subject: [PATCH 29/37] Exclude arrayfire submodule from crate package --- Cargo.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 5f6ddb98d..39b661d74 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,9 @@ readme = "./README.md" keywords = ["CUDA", "OpenCL", "ArrayFire", "Compute"] license = "BSD-3-Clause" build = "build.rs" +exclude = [ + "arrayfire/*", +] [dependencies] libc = "0.1.10" From 895e4e5e11e93a5e54a6fb20069fe0f810c8d951 Mon Sep 17 00:00:00 2001 From: pradeep Date: Fri, 20 May 2016 22:18:15 +0530 Subject: [PATCH 30/37] Update README with v3.3.0 release information --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3944d55ed..a0f205f23 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ |:-------:|:-------:|:---:| | [![Build Status](http://ci.arrayfire.org/buildStatus/icon?job=arrayfire-wrappers/rust-linux)](http://ci.arrayfire.org/view/All/job/arrayfire-wrappers/job/rust-linux/) | [![Build Status](http://ci.arrayfire.org/buildStatus/icon?job=arrayfire-wrappers/rust-windows)](http://ci.arrayfire.org/view/All/job/arrayfire-wrappers/job/rust-windows/) | [![Build Status](http://ci.arrayfire.org/buildStatus/icon?job=arrayfire-wrappers/rust-osx)](http://ci.arrayfire.org/view/All/job/arrayfire-wrappers/job/rust-osx/) | -[ArrayFire](https://github.com/arrayfire/arrayfire) is a high performance library for parallel computing with an easy-to-use API. It enables users to write scientific computing code that is portable across CUDA, OpenCL and CPU devices. This project provides Rust bindings for the ArrayFire library. The wrapper is currently compliant with ArrayFire 3.2 API. If you find any bugs, please report them [here](https://github.com/arrayfire/arrayfire-rust/issues). +[ArrayFire](https://github.com/arrayfire/arrayfire) is a high performance library for parallel computing with an easy-to-use API. It enables users to write scientific computing code that is portable across CUDA, OpenCL and CPU devices. This project provides Rust bindings for the ArrayFire library. The wrapper is currently compliant with ArrayFire 3.3 API. If you find any bugs, please report them [here](https://github.com/arrayfire/arrayfire-rust/issues). ## Documentation @@ -16,6 +16,9 @@ You can find the most recent updated documentation [here](http://arrayfire.githu We recommend using Rust 1.5 and higher. +Rust 1.8 stabilized the traits for compound assignment operations. These are automatically enabled +based on the rust version you are using. + ## Use from Crates.io [![](http://meritbadge.herokuapp.com/arrayfire)](https://crates.io/crates/arrayfire) To use the rust bindings for ArrayFire from crates.io, the following requirements are to be met @@ -27,7 +30,7 @@ first. 3. Make sure you add the path to library files to your path environment variables. - On Linux & OSX: do `export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$AF_PATH/lib` - On Windows: Add `%AF_PATH%\lib` to your PATH environment variable. -4. Add `arrayfire = "3.2.0"` to the dependencies section of your project's Cargo.toml file. +4. Add `arrayfire = "3.3.0"` to the dependencies section of your project's Cargo.toml file. Once step (4) is over, you should be able to use ArrayFire in your Rust project. If you find any bugs, please report them [here](https://github.com/arrayfire/arrayfire-rust/issues). From a46e59bdb229522dada3db4ca69298684fb708ff Mon Sep 17 00:00:00 2001 From: Demur Rumed Date: Sun, 5 Jun 2016 13:27:48 +0000 Subject: [PATCH 31/37] Remove time dependency & try bump libc I'm not on a system capable of testing, but currently our own dependency causes cargo to pull down both libc 0.1 & 0.2. We should update to libc 0.2 to combine dependencies. time is deprecated in favor of std::time --- Cargo.toml | 3 +-- examples/pi.rs | 9 +++------ 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 39b661d74..cbed52650 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,9 +15,8 @@ exclude = [ ] [dependencies] -libc = "0.1.10" +libc = "0.2" num = "0.1.27" -time = "0.1.32" lazy_static = "0.2.1" [build-dependencies] diff --git a/examples/pi.rs b/examples/pi.rs index a32b94c63..5fe1c79e4 100644 --- a/examples/pi.rs +++ b/examples/pi.rs @@ -1,8 +1,7 @@ #[macro_use(mem_info)] extern crate arrayfire as af; -extern crate time; -use time::PreciseTime; +use std::time::Instant; use af::*; #[allow(unused_must_use)] @@ -16,7 +15,7 @@ fn main() { let x = &randu::(dims); let y = &randu::(dims); - let start = PreciseTime::now(); + let start = Instant::now(); mem_info!("Before benchmark"); @@ -30,9 +29,7 @@ fn main() { let pi_val = real*4.0/(samples as f64); } - let end = PreciseTime::now(); - - println!("Estimated Pi Value in {} seconds", start.to(end) / 100); + println!("Estimated Pi Value in {:?}", start.elapsed()); mem_info!("After benchmark"); } From a781bffb1b8d3dfb3d7ba3fe2f8315a80c73cd73 Mon Sep 17 00:00:00 2001 From: pradeep Date: Mon, 6 Jun 2016 09:53:55 +0530 Subject: [PATCH 32/37] Replace u64 with usize type in device module fns --- src/device/mod.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/device/mod.rs b/src/device/mod.rs index f8dfd57ea..250b2fbb5 100644 --- a/src/device/mod.rs +++ b/src/device/mod.rs @@ -131,12 +131,12 @@ pub fn get_device() -> i32 { /// * Number of buffers allocated /// * Number of bytes locked /// * Number of buffers locked -pub fn device_mem_info() -> (u64, u64, u64, u64) { +pub fn device_mem_info() -> (usize, usize, usize, usize) { unsafe { - let mut o0: u64 = 0; - let mut o1: u64 = 0; - let mut o2: u64 = 0; - let mut o3: u64 = 0; + let mut o0: usize = 0; + let mut o1: usize = 0; + let mut o2: usize = 0; + let mut o3: usize = 0; let err_val = af_device_mem_info(&mut o0 as *mut size_t, &mut o1 as *mut size_t, &mut o2 as *mut size_t, @@ -181,7 +181,7 @@ pub fn print_mem_info(msg: String, device: i32) { /// # Return Values /// /// None -pub fn set_mem_step_size(step_bytes: u64) { +pub fn set_mem_step_size(step_bytes: usize) { unsafe { let err_val = af_set_mem_step_size(step_bytes as size_t); HANDLE_ERROR(AfError::from(err_val)); @@ -197,9 +197,9 @@ pub fn set_mem_step_size(step_bytes: u64) { /// # Return Values /// /// Returns is the size of minimum memory chunk in bytes -pub fn get_mem_step_size() -> u64 { +pub fn get_mem_step_size() -> usize { unsafe { - let mut temp: u64 = 0; + let mut temp: usize = 0; let err_val = af_get_mem_step_size(&mut temp as *mut size_t); HANDLE_ERROR(AfError::from(err_val)); temp @@ -228,4 +228,4 @@ pub fn sync(device: i32) { let err_val = af_sync(device as c_int); HANDLE_ERROR(AfError::from(err_val)); } -} \ No newline at end of file +} From 84b6c5938883f8a08eafaaf6869fd2066d87712b Mon Sep 17 00:00:00 2001 From: pradeep Date: Mon, 6 Jun 2016 13:48:33 +0530 Subject: [PATCH 33/37] Bump up dependencies(crates) versions --- Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index cbed52650..a6ac2f81d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,12 +15,12 @@ exclude = [ ] [dependencies] -libc = "0.2" -num = "0.1.27" +libc = "0.2.11" +num = "0.1.32" lazy_static = "0.2.1" [build-dependencies] -rustc-serialize = "0.3.16" +rustc-serialize = "0.3.19" rustc_version = "0.1.7" [lib] From cb7a6f4f70e42e38e324417fac277bb5e85bacc8 Mon Sep 17 00:00:00 2001 From: pradeep Date: Wed, 8 Jun 2016 11:24:54 +0530 Subject: [PATCH 34/37] BUGFIX: variable size discrepancy with FFI for Rust enums Rust enums use 8-bit number for representation of values where as c uses 32-bit number. This caused the issue in release mode. The compiler optimized these variables in release mode which must have caused over-bound writes thus causing the program crash. Fixes #73 --- src/array.rs | 6 +++--- src/defines.rs | 10 ++++++++++ src/util.rs | 30 +++++++++++++++--------------- 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/src/array.rs b/src/array.rs index 890fd9422..a47851d29 100644 --- a/src/array.rs +++ b/src/array.rs @@ -26,7 +26,7 @@ extern { 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_type(out: *mut c_int, 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; @@ -206,8 +206,8 @@ impl Array { /// Returns the Array data type pub fn get_type(&self) -> DType { unsafe { - let mut ret_val: u8 = 0; - let err_val = af_get_type(&mut ret_val as *mut uint8_t, self.handle as AfArray); + let mut ret_val: i32 = 0; + let err_val = af_get_type(&mut ret_val as *mut c_int, self.handle as AfArray); HANDLE_ERROR(AfError::from(err_val)); DType::from(ret_val) } diff --git a/src/defines.rs b/src/defines.rs index 60cf76350..669f2e053 100644 --- a/src/defines.rs +++ b/src/defines.rs @@ -106,6 +106,7 @@ impl Error for AfError { } /// Types of Array data type +#[repr(C)] #[derive(Clone, Copy, Debug, PartialEq)] pub enum DType { /// 32 bit float @@ -135,6 +136,7 @@ pub enum DType { } /// Dictates the interpolation method to be used by a function +#[repr(C)] #[derive(Clone, Copy, Debug, PartialEq)] pub enum InterpType { /// Nearest Neighbor interpolation method @@ -148,6 +150,7 @@ pub enum InterpType { } /// Helps determine how to pad kernels along borders +#[repr(C)] #[derive(Clone, Copy, Debug, PartialEq)] pub enum BorderType { /// Pad using zeros @@ -157,6 +160,7 @@ pub enum BorderType { } /// Used by `regions` function to identify type of connectivity +#[repr(C)] #[derive(Clone, Copy, Debug, PartialEq)] pub enum Connectivity { /// North-East-South-West (N-E-S-W) connectivity from given pixel/point @@ -166,6 +170,7 @@ pub enum Connectivity { } /// Helps determine the size of output of convolution +#[repr(C)] #[derive(Clone, Copy, Debug, PartialEq)] pub enum ConvMode { /// Default convolution mode where output size is same as input size @@ -175,6 +180,7 @@ pub enum ConvMode { } /// Helps determine if convolution is in Spatial or Frequency domain +#[repr(C)] #[derive(Clone, Copy, Debug, PartialEq)] pub enum ConvDomain { /// ArrayFire chooses whether the convolution will be in spatial domain or frequency domain @@ -186,6 +192,7 @@ pub enum ConvDomain { } /// Error metric used by `matchTemplate` function +#[repr(C)] #[derive(Clone, Copy, Debug, PartialEq)] pub enum MatchType { /// Sum of Absolute Differences @@ -209,6 +216,7 @@ pub enum MatchType { } /// Identify the color space of given image(Array) +#[repr(C)] #[derive(Clone, Copy, Debug, PartialEq)] pub enum ColorSpace { /// Grayscale color space @@ -220,6 +228,7 @@ pub enum ColorSpace { } /// Helps determine the type of a Matrix +#[repr(C)] #[derive(Clone, Copy, Debug, PartialEq)] pub enum MatProp { /// Default (no-op) @@ -248,6 +257,7 @@ pub enum MatProp { /// Norm type #[allow(non_camel_case_types)] +#[repr(C)] #[derive(Clone, Copy, Debug, PartialEq)] pub enum NormType { /// Treats input as a vector and return sum of absolute values diff --git a/src/util.rs b/src/util.rs index 8fa568aa9..ba1726453 100644 --- a/src/util.rs +++ b/src/util.rs @@ -11,37 +11,37 @@ impl From for AfError { } } -impl From for DType { - fn from(t: u8) -> DType { - assert!(DType::F32 as u8 <= t && t <= DType::U64 as u8); +impl From for DType { + fn from(t: i32) -> DType { + assert!(DType::F32 as i32 <= t && t <= DType::U64 as i32); unsafe { mem::transmute(t) } } } -impl From for InterpType { - fn from(t: u8) -> InterpType { - assert!(InterpType::NEAREST as u8 <= t && t <= InterpType::CUBIC as u8); +impl From for InterpType { + fn from(t: i32) -> InterpType { + assert!(InterpType::NEAREST as i32 <= t && t <= InterpType::CUBIC as i32); unsafe { mem::transmute(t) } } } -impl From for ConvMode { - fn from(t: u8) -> ConvMode { - assert!(ConvMode::DEFAULT as u8 <= t && t <= ConvMode::EXPAND as u8); +impl From for ConvMode { + fn from(t: i32) -> ConvMode { + assert!(ConvMode::DEFAULT as i32 <= t && t <= ConvMode::EXPAND as i32); unsafe { mem::transmute(t) } } } -impl From for ConvDomain { - fn from(t: u8) -> ConvDomain { - assert!(ConvDomain::AUTO as u8 <= t && t <= ConvDomain::FREQUENCY as u8); +impl From for ConvDomain { + fn from(t: i32) -> ConvDomain { + assert!(ConvDomain::AUTO as i32 <= t && t <= ConvDomain::FREQUENCY as i32); unsafe { mem::transmute(t) } } } -impl From for MatchType { - fn from(t: u8) -> MatchType { - assert!(MatchType::SAD as u8 <= t && t <= MatchType::SHD as u8); +impl From for MatchType { + fn from(t: i32) -> MatchType { + assert!(MatchType::SAD as i32 <= t && t <= MatchType::SHD as i32); unsafe { mem::transmute(t) } } } From 7a7d453aafa22ffeef75ef052b94d42fc94b637f Mon Sep 17 00:00:00 2001 From: pradeep Date: Wed, 8 Jun 2016 11:55:16 +0530 Subject: [PATCH 35/37] v3.3.1 Release --- Cargo.toml | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a6ac2f81d..6d05bf6dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "arrayfire" description = "ArrayFire is a high performance software library for parallel computing with an easy-to-use API. Its array based function set makes parallel programming simple. ArrayFire's multiple backends (CUDA, OpenCL and native CPU) make it platform independent and highly portable. A few lines of code in ArrayFire can replace dozens of lines of parallel computing code, saving you valuable time and lowering development costs. This crate provides Rust bindings for ArrayFire library." -version = "3.3.0" +version = "3.3.1" documentation = "http://arrayfire.github.io/arrayfire-rust/arrayfire/index.html" homepage = "https://github.com/arrayfire/arrayfire" repository = "https://github.com/arrayfire/arrayfire-rust" diff --git a/README.md b/README.md index a0f205f23..90d21eb3b 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ first. 3. Make sure you add the path to library files to your path environment variables. - On Linux & OSX: do `export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$AF_PATH/lib` - On Windows: Add `%AF_PATH%\lib` to your PATH environment variable. -4. Add `arrayfire = "3.3.0"` to the dependencies section of your project's Cargo.toml file. +4. Add `arrayfire = "3.3.1"` to the dependencies section of your project's Cargo.toml file. Once step (4) is over, you should be able to use ArrayFire in your Rust project. If you find any bugs, please report them [here](https://github.com/arrayfire/arrayfire-rust/issues). From 5e16c77409ec4cebb28bb7d2f5cf833c40e00f7b Mon Sep 17 00:00:00 2001 From: pradeep Date: Fri, 29 Jul 2016 17:48:14 +0530 Subject: [PATCH 36/37] Fix compilation issue with rustc 1.10.0 After the fix, error module compiles fine with both 1.9.0 and 1.10.0 versions. --- src/error.rs | 33 +++++++++++++++++++++++++++++---- src/lib.rs | 2 +- tests/lib.rs | 16 ++++++++-------- 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/src/error.rs b/src/error.rs index 296627d19..0c1b371b3 100644 --- a/src/error.rs +++ b/src/error.rs @@ -22,23 +22,48 @@ unsafe impl<'cblifetime> Send for Callback<'cblifetime> {} unsafe impl<'cblifetime> Sync for Callback<'cblifetime> {} -pub static DEFAULT_HANDLE_ERROR: &'static ErrorCallback = &handle_error_general; +pub const DEFAULT_HANDLE_ERROR: Callback<'static> = Callback{cb: &handle_error_general}; lazy_static! { static ref ERROR_HANDLER_LOCK: RwLock< Callback<'static> > = - RwLock::new(Callback{cb: DEFAULT_HANDLE_ERROR}); + RwLock::new(DEFAULT_HANDLE_ERROR); } +/// Register user provided error handler +/// +/// # Examples +/// ``` +/// #[macro_use] +/// extern crate arrayfire; +/// +/// use arrayfire::{AfError, Callback, info, register_error_handler}; +/// use std::error::Error; +/// +/// fn handleError(error_code: AfError) { +/// match error_code { +/// AfError::SUCCESS => {}, /* No-op */ +/// _ => panic!("Error message: {}", error_code.description()), +/// } +/// } +/// +/// pub const ERR_HANDLE: Callback<'static> = Callback{ cb: &handleError}; +/// +/// fn main() { +/// register_error_handler(ERR_HANDLE); +/// +/// info(); +/// } +/// ``` #[allow(unused_must_use)] -pub fn register_error_handler(cb_value: &'static ErrorCallback) { +pub fn register_error_handler(cb_value: Callback<'static>) { let mut gaurd = match ERROR_HANDLER_LOCK.write() { Ok(g) => g, Err(_)=> panic!("Failed to acquire lock to register error handler"), }; - *gaurd.deref_mut() = Callback{cb:cb_value}; + *gaurd.deref_mut() = cb_value; } pub fn handle_error_general(error_code: AfError) { diff --git a/src/lib.rs b/src/lib.rs index 81915aff5..18c0ce186 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -53,7 +53,7 @@ mod defines; pub use dim4::Dim4; mod dim4; -pub use error::{ErrorCallback, register_error_handler, handle_error_general}; +pub use error::{Callback, ErrorCallback, register_error_handler, handle_error_general}; mod error; pub use index::{Indexer, index, row, rows, col, cols, slice, slices, diff --git a/tests/lib.rs b/tests/lib.rs index e0f90aac6..fa0ce65f2 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -25,10 +25,10 @@ implement_handler!(handler_sample2, "Error Handler Sample2"); implement_handler!(handler_sample3, "Error Handler Sample3"); implement_handler!(handler_sample4, "Error Handler Sample4"); -pub static HANDLE1: &'static ErrorCallback = &handler_sample1; -pub static HANDLE2: &'static ErrorCallback = &handler_sample2; -pub static HANDLE3: &'static ErrorCallback = &handler_sample3; -pub static HANDLE4: &'static ErrorCallback = &handler_sample4; +pub const HANDLE1: Callback<'static> = Callback{ cb: &handler_sample1}; +pub const HANDLE2: Callback<'static> = Callback{ cb: &handler_sample2}; +pub const HANDLE3: Callback<'static> = Callback{ cb: &handler_sample3}; +pub const HANDLE4: Callback<'static> = Callback{ cb: &handler_sample4}; #[allow(unused_must_use)] #[test] @@ -38,10 +38,10 @@ fn check_error_handler_mutation() { thread::Builder::new().name(format!("child {}",i+1).to_string()).spawn(move || { println!("{:?}", thread::current()); match i { - 0 => register_error_handler(HANDLE1.clone()), - 1 => register_error_handler(HANDLE2.clone()), - 2 => register_error_handler(HANDLE3.clone()), - 3 => register_error_handler(HANDLE4.clone()), + 0 => register_error_handler(HANDLE1), + 1 => register_error_handler(HANDLE2), + 2 => register_error_handler(HANDLE3), + 3 => register_error_handler(HANDLE4), _ => panic!("Impossible scenario"), } }); From 142b44f8e89ec1fe93835e04e96e4b71dda998a7 Mon Sep 17 00:00:00 2001 From: pradeep Date: Fri, 29 Jul 2016 18:03:00 +0530 Subject: [PATCH 37/37] v3.3.2 Release --- Cargo.toml | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6d05bf6dd..3950700d7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "arrayfire" description = "ArrayFire is a high performance software library for parallel computing with an easy-to-use API. Its array based function set makes parallel programming simple. ArrayFire's multiple backends (CUDA, OpenCL and native CPU) make it platform independent and highly portable. A few lines of code in ArrayFire can replace dozens of lines of parallel computing code, saving you valuable time and lowering development costs. This crate provides Rust bindings for ArrayFire library." -version = "3.3.1" +version = "3.3.2" documentation = "http://arrayfire.github.io/arrayfire-rust/arrayfire/index.html" homepage = "https://github.com/arrayfire/arrayfire" repository = "https://github.com/arrayfire/arrayfire-rust" diff --git a/README.md b/README.md index 90d21eb3b..a55cf2315 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ first. 3. Make sure you add the path to library files to your path environment variables. - On Linux & OSX: do `export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$AF_PATH/lib` - On Windows: Add `%AF_PATH%\lib` to your PATH environment variable. -4. Add `arrayfire = "3.3.1"` to the dependencies section of your project's Cargo.toml file. +4. Add `arrayfire = "3.3.2"` to the dependencies section of your project's Cargo.toml file. Once step (4) is over, you should be able to use ArrayFire in your Rust project. If you find any bugs, please report them [here](https://github.com/arrayfire/arrayfire-rust/issues).