From 9997c9a846733fa7a5d3ba61351d8a9ff5689f35 Mon Sep 17 00:00:00 2001 From: pradeep Date: Tue, 31 May 2016 11:58:24 +0530 Subject: [PATCH 01/36] Bump up wrapper version to 3.4 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 39b661d74..8d4f4f74a 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.4.0" documentation = "http://arrayfire.github.io/arrayfire-rust/arrayfire/index.html" homepage = "https://github.com/arrayfire/arrayfire" repository = "https://github.com/arrayfire/arrayfire-rust" From 6d5ab72cec7bfe51caf2a5f8ac8760fd141e2e23 Mon Sep 17 00:00:00 2001 From: pradeep Date: Tue, 31 May 2016 11:59:01 +0530 Subject: [PATCH 02/36] Add new function get_size(DType) --- src/lib.rs | 2 +- src/util.rs | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 81915aff5..33ac66788 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -98,7 +98,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}; +pub use util::{HasAfEnum, get_size}; mod util; pub use vision::Features; diff --git a/src/util.rs b/src/util.rs index 8fa568aa9..e1d03da2c 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,8 +1,26 @@ +extern crate libc; extern crate num; use defines::{AfError, ColorMap, ConvDomain, ConvMode, DType, InterpType, MatProp, MatchType}; +use error::HANDLE_ERROR; use std::mem; use self::num::Complex; +use self::libc::{uint8_t, c_int, size_t}; + +#[allow(dead_code)] +extern { + fn af_get_size_of(size: *mut size_t, aftype: uint8_t) -> c_int; +} + +/// Get size, in bytes, of the arrayfire native type +pub fn get_size(value: DType) -> u64 { + unsafe { + let mut ret_val: u64 = 0; + let err_val = af_get_size_of(&mut ret_val as *mut size_t, value as uint8_t); + HANDLE_ERROR(AfError::from(err_val)); + ret_val + } +} impl From for AfError { fn from(t: i32) -> AfError { From 5ffea671fe46d971c25958e3186223a0152ad18d Mon Sep 17 00:00:00 2001 From: pradeep Date: Tue, 31 May 2016 13:35:52 +0530 Subject: [PATCH 03/36] Correct Array::print doc test --- src/array.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/array.rs b/src/array.rs index 890fd9422..ea85c00e8 100644 --- a/src/array.rs +++ b/src/array.rs @@ -364,7 +364,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 dims = Dim4::new(&[5, 3, 1, 1]); /// let a = randu::(dims); /// print(&a); /// ``` From 6a5b08d79417c91a69de179362e7969cdcf14d0e Mon Sep 17 00:00:00 2001 From: pradeep Date: Tue, 31 May 2016 22:04:57 +0530 Subject: [PATCH 04/36] Update documentation for functions in algorithm module --- src/algorithm/mod.rs | 573 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 490 insertions(+), 83 deletions(-) diff --git a/src/algorithm/mod.rs b/src/algorithm/mod.rs index 98284daed..8b90b285f 100644 --- a/src/algorithm/mod.rs +++ b/src/algorithm/mod.rs @@ -49,17 +49,8 @@ extern { } macro_rules! dim_reduce_func_def { - ($fn_name: ident, $ffi_name: ident) => ( - /// Reduction operation along specific dimension - /// - /// # Parameters - /// - /// - `input` - Input Array - /// - `dim` - Dimension along which the input Array will be reduced - /// - /// # Return Values - /// - /// Reduced Array + ($doc_str: expr, $fn_name: ident, $ffi_name: ident) => ( + #[doc=$doc_str] #[allow(unused_mut)] pub fn $fn_name(input: &Array, dim: i32) -> Array { unsafe { @@ -73,21 +64,263 @@ macro_rules! dim_reduce_func_def { ) } -dim_reduce_func_def!(sum, af_sum); -dim_reduce_func_def!(product, af_product); -dim_reduce_func_def!(min, af_min); -dim_reduce_func_def!(max, af_max); -dim_reduce_func_def!(all_true, af_all_true); -dim_reduce_func_def!(any_true, af_any_true); -dim_reduce_func_def!(count, af_count); -dim_reduce_func_def!(accum, af_accum); -dim_reduce_func_def!(diff1, af_diff1); -dim_reduce_func_def!(diff2, af_diff2); +dim_reduce_func_def!(" + Sum elements along a given dimension -/// Reduction operation along specific dimension + # Parameters + + - `input` - Input Array + - `dim` - Dimension along which the input Array will be reduced + + # Return Values + + Result Array after summing all elements along given dimension + + # Examples + + ``` + use arrayfire::{Dim4, print, randu, sum}; + let dims = Dim4::new(&[5, 3, 1, 1]); + let a = randu::(dims); + print(&a); + let b = sum(&a, 0); + print(&b); + let c = sum(&a, 1); + print(&c); + ``` + ", + sum, af_sum); + +dim_reduce_func_def!(" + Compute product of elements along a given dimension + + # Parameters + + - `input` - Input Array + - `dim` - Dimension along which the input Array will be reduced + + # Return Values + + Result Array after multiplying all elements along given dimension + + # Examples + + ``` + use arrayfire::{Dim4, print, randu, product}; + let dims = Dim4::new(&[5, 3, 1, 1]); + let a = randu::(dims); + print(&a); + let b = product(&a, 0); + print(&b); + let c = product(&a, 1); + print(&c); + ``` + ", product, af_product); + +dim_reduce_func_def!(" + Find minimum among elements of given dimension + + # Parameters + + - `input` - Input Array + - `dim` - Dimension along which the input Array will be reduced + + # Return Values + + Result Array after finding minimum among elements along a given dimension + + # Examples + + ``` + use arrayfire::{Dim4, print, randu, min}; + let dims = Dim4::new(&[5, 3, 1, 1]); + let a = randu::(dims); + print(&a); + let b = min(&a, 0); + print(&b); + let c = min(&a, 1); + print(&c); + ", min, af_min); + +dim_reduce_func_def!(" + Find maximum among elements of given dimension + + # Parameters + + - `input` - Input Array + - `dim` - Dimension along which the input Array will be reduced + + # Return Values + + Result Array after finding maximum among elements along a given dimension + + # Examples + + ``` + use arrayfire::{Dim4, print, randu, max}; + let dims = Dim4::new(&[5, 3, 1, 1]); + let a = randu::(dims); + print(&a); + let b = max(&a, 0); + print(&b); + let c = max(&a, 1); + print(&c); + ", max, af_max); + +dim_reduce_func_def!(" + Find if all of the values along a given dimension in the Array are true + + # Parameters + + - `input` - Input Array + - `dim` - Dimension along which the predicate is evaluated + + # Return Values + + Result Array that contains the result of `AND` operation of all elements along given dimension + + # Examples + + ``` + use arrayfire::{Dim4, print, randu, all_true}; + let dims = Dim4::new(&[5, 3, 1, 1]); + let a = randu::(dims); + print(&a); + let b = all_true(&a, 0); + print(&b); + let c = all_true(&a, 1); + print(&c); + ", all_true, af_all_true); + +dim_reduce_func_def!(" + Find if any of the values along a given dimension in the Array are true + + # Parameters + + - `input` - Input Array + - `dim` - Dimension along which the predicate is evaluated + + # Return Values + + Result Array that contains the result of `OR` operation of all elements along given dimension + + # Examples + + ``` + use arrayfire::{Dim4, print, randu, any_true}; + let dims = Dim4::new(&[5, 3, 1, 1]); + let a = randu::(dims); + print(&a); + let b = any_true(&a, 0); + print(&b); + let c = any_true(&a, 1); + print(&c); + ", any_true, af_any_true); + +dim_reduce_func_def!(" + Count number of non-zero elements along a given dimension + + # Parameters + + - `input` - Input Array + - `dim` - Dimension along which the non-zero elements are counted + + # Return Values + + Result Array with number of non-zero elements along a given dimension + + # Examples + + ``` + use arrayfire::{Dim4, gt, print, randu, count}; + let dims = Dim4::new(&[5, 3, 1, 1]); + let a = gt(&randu::(dims), &0.5, false); + print(&a); + let b = count(&a, 0); + print(&b); + let c = count(&a, 1); + print(&c); + ", count, af_count); + +dim_reduce_func_def!(" + Perform exclusive sum of elements along a given dimension + + # Parameters + + - `input` - Input Array + - `dim` - Dimension along which the exclusive scan operation is carried out + + # Return Values + + Result Array with exclusive sums of input Array elements along a given dimension + + # Examples + + ``` + use arrayfire::{Dim4, print, randu, accum}; + let dims = Dim4::new(&[5, 3, 1, 1]); + let a = randu::(dims); + print(&a); + let b = accum(&a, 0); + print(&b); + let c = accum(&a, 1); + print(&c); + ", accum, af_accum); + +dim_reduce_func_def!(" + Calculate first order numerical difference along a given dimension + + # Parameters + + - `input` - Input Array + - `dim` - Dimension along which first order difference is calculated + + # Return Values + + Result Array with first order difference values + + # Examples + + ``` + use arrayfire::{Dim4, print, randu, diff1}; + let dims = Dim4::new(&[5, 3, 1, 1]); + let a = randu::(dims); + print(&a); + let b = diff1(&a, 0); + print(&b); + let c = diff1(&a, 1); + print(&c); + ", diff1, af_diff1); + +dim_reduce_func_def!(" + Calculate second order numerical difference along a given dimension + + # Parameters + + - `input` - Input Array + - `dim` - Dimension along which second order difference is calculated + + # Return Values + + Result Array with second order difference values + + # Examples + + ``` + use arrayfire::{Dim4, print, randu, diff2}; + let dims = Dim4::new(&[5, 3, 1, 1]); + let a = randu::(dims); + print(&a); + let b = diff2(&a, 0); + print(&b); + let c = diff2(&a, 1); + print(&c); + ", diff2, af_diff2); + +/// Sum along specific dimension using user specified value instead of `NAN` values /// /// Sum values of the `input` Array along `dim` dimension after replacing any `NAN` values in the -/// Array with `nanval` value. +/// Array with the value of the parameter `nanval`. /// /// # Parameters /// @@ -97,7 +330,7 @@ dim_reduce_func_def!(diff2, af_diff2); /// /// # Return Values /// -/// Reduced Array +/// Array that is reduced along given dimension via addition operation pub fn sum_nan(input: &Array, dim: i32, nanval: f64) -> Array { unsafe { let mut temp: i64 = 0; @@ -108,7 +341,7 @@ pub fn sum_nan(input: &Array, dim: i32, nanval: f64) -> Array { } } -/// Reduction operation along specific dimension +/// Product of elements along specific dimension using user specified value instead of `NAN` values /// /// Compute product of the values of the `input` Array along `dim` dimension after replacing any `NAN` values in the Array with `nanval` value. /// @@ -120,7 +353,7 @@ pub fn sum_nan(input: &Array, dim: i32, nanval: f64) -> Array { /// /// # Return Values /// -/// Reduced Array +/// Array that is reduced along given dimension via multiplication operation pub fn product_nan(input: &Array, dim: i32, nanval: f64) -> Array { unsafe { let mut temp: i64 = 0; @@ -132,17 +365,8 @@ pub fn product_nan(input: &Array, dim: i32, nanval: f64) -> Array { } macro_rules! all_reduce_func_def { - ($fn_name: ident, $ffi_name: ident) => ( - /// Reduction operation of all values - /// - /// # Parameters - /// - /// - `input` is the input Array - /// - /// # Return Values - /// - /// A tuple of reduction result. For non-complex data type Arrays, second value of tuple is - /// zero. + ($doc_str: expr, $fn_name: ident, $ffi_name: ident) => ( + #[doc=$doc_str] #[allow(unused_mut)] pub fn $fn_name(input: &Array) -> (f64, f64) { unsafe { @@ -157,15 +381,168 @@ macro_rules! all_reduce_func_def { ) } -all_reduce_func_def!(sum_all, af_sum_all); -all_reduce_func_def!(product_all, af_product_all); -all_reduce_func_def!(min_all, af_min_all); -all_reduce_func_def!(max_all, af_max_all); -all_reduce_func_def!(all_true_all, af_all_true_all); -all_reduce_func_def!(any_true_all, af_any_true_all); -all_reduce_func_def!(count_all, af_count_all); +all_reduce_func_def!(" + Sum all values of the Array + + # Parameters + + - `input` is the input Array + + # Return Values -/// Reduction operation of all values + A tuple containing the summation result. + + Note: For non-complex data type Arrays, second value of tuple is zero. + + # Examples + + ``` + use arrayfire::{Dim4, print, randu, sum_all}; + let dims = Dim4::new(&[5, 5, 1, 1]); + let a = randu::(dims); + print(&a); + println!(\"Result : {:?}\", sum_all(&a)); + ``` + ", sum_all, af_sum_all); + +all_reduce_func_def!(" + Product of all values of the Array + + # Parameters + + - `input` is the input Array + + # Return Values + + A tuple containing the product result. + + Note: For non-complex data type Arrays, second value of tuple is zero. + + # Examples + + ``` + use arrayfire::{Dim4, print, randu, product_all}; + let dims = Dim4::new(&[5, 5, 1, 1]); + let a = randu::(dims); + print(&a); + println!(\"Result : {:?}\", product_all(&a)); + ``` + ", product_all, af_product_all); + +all_reduce_func_def!(" + Find minimum among all values of the Array + + # Parameters + + - `input` is the input Array + + # Return Values + + A tuple containing the minimum value. + + Note: For non-complex data type Arrays, second value of tuple is zero. + + # Examples + + ``` + use arrayfire::{Dim4, print, randu, min_all}; + let dims = Dim4::new(&[5, 5, 1, 1]); + let a = randu::(dims); + print(&a); + println!(\"Result : {:?}\", min_all(&a)); + ``` + ", min_all, af_min_all); + +all_reduce_func_def!(" + Find maximum among all values of the Array + + # Parameters + + - `input` is the input Array + + # Return Values + + A tuple containing the maximum value. + + Note: For non-complex data type Arrays, second value of tuple is zero. + + # Examples + + ``` + use arrayfire::{Dim4, print, randu, max_all}; + let dims = Dim4::new(&[5, 5, 1, 1]); + let a = randu::(dims); + print(&a); + println!(\"Result : {:?}\", max_all(&a)); + ``` + ", max_all, af_max_all); + +all_reduce_func_def!(" + Find if all values of Array are non-zero + + # Parameters + + - `input` is the input Array + + # Return Values + + A tuple containing the result of `AND` operation on all values of Array. + + # Examples + + ``` + use arrayfire::{Dim4, print, randu, all_true_all}; + let dims = Dim4::new(&[5, 5, 1, 1]); + let a = randu::(dims); + print(&a); + println!(\"Result : {:?}\", all_true_all(&a)); + ``` + ", all_true_all, af_all_true_all); + +all_reduce_func_def!(" + Find if any value of Array is non-zero + + # Parameters + + - `input` is the input Array + + # Return Values + + A tuple containing the result of `OR` operation on all values of Array. + + # Examples + + ``` + use arrayfire::{Dim4, print, randu, any_true_all}; + let dims = Dim4::new(&[5, 5, 1, 1]); + let a = randu::(dims); + print(&a); + println!(\"Result : {:?}\", any_true_all(&a)); + ", any_true_all, af_any_true_all); + +all_reduce_func_def!(" + Count number of non-zero values in the Array + + # Parameters + + - `input` is the input Array + + # Return Values + + A tuple containing the count of non-zero values in the Array. + + # Examples + + ``` + use arrayfire::{Dim4, print, randu, count_all}; + let dims = Dim4::new(&[5, 5, 1, 1]); + let a = randu::(dims); + print(&a); + println!(\"Result : {:?}\", count_all(&a)); + ``` + ", count_all, af_count_all); + +/// Sum all values using user provided value for `NAN` /// /// Sum all the values of the `input` Array after replacing any `NAN` values with `val`. /// @@ -177,8 +554,9 @@ all_reduce_func_def!(count_all, af_count_all); /// /// # Return Values /// -/// A tuple of reduction result. For non-complex data type Arrays, second value of tuple is -/// zero. +/// A tuple of summation result. +/// +/// Note: For non-complex data type Arrays, second value of tuple is zero. pub fn sum_nan_all(input: &Array, val: f64) -> (f64, f64) { unsafe { let mut real: f64 = 0.0; @@ -190,9 +568,9 @@ pub fn sum_nan_all(input: &Array, val: f64) -> (f64, f64) { } } -/// Reduction operation of all values +/// Product of all values using user provided value for `NAN` /// -/// Compute the product of all the values of the `input` Array after replacing any `NAN` values with `val`. +/// Compute the product of all the values of the `input` Array after replacing any `NAN` values with `val` /// /// # Parameters /// @@ -202,8 +580,9 @@ pub fn sum_nan_all(input: &Array, val: f64) -> (f64, f64) { /// /// # Return Values /// -/// A tuple of reduction result. For non-complex data type Arrays, second value of tuple is -/// zero. +/// A tuple of product result. +/// +/// Note: For non-complex data type Arrays, second value of tuple is zero. pub fn product_nan_all(input: &Array, val: f64) -> (f64, f64) { unsafe { let mut real: f64 = 0.0; @@ -216,19 +595,8 @@ pub fn product_nan_all(input: &Array, val: f64) -> (f64, f64) { } macro_rules! dim_ireduce_func_def { - ($fn_name: ident, $ffi_name: ident) => ( - /// Reduction operation along specific dimension - /// - /// # Parameters - /// - /// - `input` - Input Array - /// - `dim` - Dimension along which the input Array will be reduced - /// - /// # Return Values - /// - /// A tuple of Arrays: Reduced Array and Indices Array. - /// - /// The indices Array has the index of the result element along the reduction dimension. + ($doc_str: expr, $fn_name: ident, $ffi_name: ident) => ( + #[doc=$doc_str] #[allow(unused_mut)] pub fn $fn_name(input: &Array, dim: i32) -> (Array, Array) { unsafe { @@ -243,24 +611,35 @@ macro_rules! dim_ireduce_func_def { ) } -dim_ireduce_func_def!(imin, af_imin); -dim_ireduce_func_def!(imax, af_imax); +dim_ireduce_func_def!(" + Find minimum value along given dimension and their corresponding indices + + # Parameters + + - `input` - Input Array + - `dim` - Dimension along which the input Array will be reduced + + # Return Values + + A tuple of Arrays: Array minimum values and Array containing their index along the reduced dimension. + ", imin, af_imin); + +dim_ireduce_func_def!(" + Find maximum value along given dimension and their corresponding indices + + # Parameters + + - `input` - Input Array + - `dim` - Dimension along which the input Array will be reduced + + # Return Values + + A tuple of Arrays: Array maximum values and Array containing their index along the reduced dimension. + ", imax, af_imax); macro_rules! all_ireduce_func_def { - ($fn_name: ident, $ffi_name: ident) => ( - /// Reduction operation of all values - /// - /// # Parameters - /// - /// `input` - Input Array - /// - /// # Return Values - /// - /// A triplet of reduction result. - /// - /// The second value of the tuple is zero for non-complex data type Arrays. - /// - /// The third value of triplet is the index of result element from reduction operation. + ($doc_str: expr, $fn_name: ident, $ffi_name: ident) => ( + #[doc=$doc_str] #[allow(unused_mut)] pub fn $fn_name(input: &Array) -> (f64, f64, u32) { unsafe { @@ -276,8 +655,36 @@ macro_rules! all_ireduce_func_def { ) } -all_ireduce_func_def!(imin_all, af_imin_all); -all_ireduce_func_def!(imax_all, af_imax_all); +all_ireduce_func_def!(" + Find minimum and it's index in the whole Array + + # Parameters + + `input` - Input Array + + # Return Values + + A triplet with + + * minimum element of Array in the first component. + * second component of value zero if Array is of non-complex type. + * index of minimum element in the third component. + ", imin_all, af_imin_all); +all_ireduce_func_def!(" + Find maximum and it's index in the whole Array + + # Parameters + + `input` - Input Array + + # Return Values + + A triplet with + + - maximum element of Array in the first component. + - second component of value zero if Array is of non-complex type. + - index of maximum element in the third component. + ", imax_all, af_imax_all); /// Locate the indices of non-zero elements. /// @@ -447,4 +854,4 @@ pub fn set_intersect(first: &Array, second: &Array, is_unique: bool) -> Array { HANDLE_ERROR(AfError::from(err_val)); Array::from(temp) } -} \ No newline at end of file +} From d9663e7a7cf0d58503deb26ce3e4808b49b9120b Mon Sep 17 00:00:00 2001 From: pradeep Date: Tue, 31 May 2016 23:46:33 +0530 Subject: [PATCH 05/36] Update documentation for functions in arith module --- src/arith/mod.rs | 162 +++++++++++++++++++++++++++-------------------- 1 file changed, 92 insertions(+), 70 deletions(-) diff --git a/src/arith/mod.rs b/src/arith/mod.rs index 95d710cdd..8d7223ab2 100644 --- a/src/arith/mod.rs +++ b/src/arith/mod.rs @@ -111,7 +111,10 @@ impl<'f> Not for &'f Array { } macro_rules! unary_func { - ($fn_name: ident, $ffi_fn: ident) => ( + ($doc_str: expr, $fn_name: ident, $ffi_fn: ident) => ( + #[doc=$doc_str] + /// + /// This is an element wise unary operation. #[allow(unused_mut)] pub fn $fn_name(input: &Array) -> Array { unsafe { @@ -124,50 +127,53 @@ macro_rules! unary_func { ) } -unary_func!(abs, af_abs); -unary_func!(arg, af_arg); -unary_func!(sign, af_sign); -unary_func!(round, af_round); -unary_func!(trunc, af_trunc); -unary_func!(floor, af_floor); -unary_func!(ceil, af_ceil); -unary_func!(sin, af_sin); -unary_func!(cos, af_cos); -unary_func!(tan, af_tan); -unary_func!(asin, af_asin); -unary_func!(acos, af_acos); -unary_func!(atan, af_atan); -unary_func!(cplx, af_cplx); -unary_func!(real, af_real); -unary_func!(imag, af_imag); -unary_func!(conjg, af_conjg); -unary_func!(sinh, af_sinh); -unary_func!(cosh, af_cosh); -unary_func!(tanh, af_tanh); -unary_func!(asinh, af_asinh); -unary_func!(acosh, af_acosh); -unary_func!(atanh, af_atanh); -unary_func!(pow2, af_pow2); -unary_func!(exp, af_exp); -unary_func!(sigmoid, af_sigmoid); -unary_func!(expm1, af_expm1); -unary_func!(erf, af_erf); -unary_func!(erfc, af_erfc); -unary_func!(log, af_log); -unary_func!(log1p, af_log1p); -unary_func!(log10, af_log10); -unary_func!(log2, af_log2); -unary_func!(sqrt, af_sqrt); -unary_func!(cbrt, af_cbrt); -unary_func!(factorial, af_factorial); -unary_func!(tgamma, af_tgamma); -unary_func!(lgamma, af_lgamma); -unary_func!(iszero, af_iszero); -unary_func!(isinf, af_isinf); -unary_func!(isnan, af_isnan); +unary_func!("Computes absolute value", abs, af_abs); +unary_func!("Computes phase value", arg, af_arg); +unary_func!("Computes the sign of input Array values", sign, af_sign); +unary_func!("Round the values in an Array", round, af_round); +unary_func!("Truncate the values in an Array", trunc, af_trunc); +unary_func!("Floor the values in an Array", floor, af_floor); +unary_func!("Ceil the values in an Array", ceil, af_ceil); +unary_func!("Compute sin", sin, af_sin); +unary_func!("Compute cos", cos, af_cos); +unary_func!("Compute tan", tan, af_tan); +unary_func!("Compute asin", asin, af_asin); +unary_func!("Compute acos", acos, af_acos); +unary_func!("Compute atan", atan, af_atan); +unary_func!("Create a complex Array from real Array", cplx, af_cplx); +unary_func!("Extract real values from a complex Array", real, af_real); +unary_func!("Extract imaginary values from a complex Array", imag, af_imag); +unary_func!("Compute the complex conjugate", conjg, af_conjg); +unary_func!("Compute sinh", sinh, af_sinh); +unary_func!("Compute cosh", cosh, af_cosh); +unary_func!("Compute tanh", tanh, af_tanh); +unary_func!("Compute asinh", asinh, af_asinh); +unary_func!("Compute acosh", acosh, af_acosh); +unary_func!("Compute atanh", atanh, af_atanh); +unary_func!("Compute two raised to the power of value", pow2, af_pow2); +unary_func!("Compute e raised to the power of value", exp, af_exp); +unary_func!("Compute sigmoid function", sigmoid, af_sigmoid); +unary_func!("Compute e raised to the power of value -1", expm1, af_expm1); +unary_func!("Compute error function value", erf, af_erf); +unary_func!("Compute the complementary error function value", erfc, af_erfc); +unary_func!("Compute the natural logarithm", log, af_log); +unary_func!("Compute the logarithm of input Array + 1", log1p, af_log1p); +unary_func!("Compute logarithm base 10", log10, af_log10); +unary_func!("Compute logarithm base 2", log2, af_log2); +unary_func!("Compute the square root", sqrt, af_sqrt); +unary_func!("Compute the cube root", cbrt, af_cbrt); +unary_func!("Compute the factorial", factorial, af_factorial); +unary_func!("Compute gamma function", tgamma, af_tgamma); +unary_func!("Compute the logarithm of absolute values of gamma function", lgamma, af_lgamma); +unary_func!("Check if values are zero", iszero, af_iszero); +unary_func!("Check if values are infinity", isinf, af_isinf); +unary_func!("Check if values are NaN", isnan, af_isnan); macro_rules! binary_func { - ($fn_name: ident, $ffi_fn: ident) => ( + ($doc_str: expr, $fn_name: ident, $ffi_fn: ident) => ( + #[doc=$doc_str] + /// + /// This is an element wise binary operation. #[allow(unused_mut)] pub fn $fn_name(lhs: &Array, rhs: &Array) -> Array { unsafe { @@ -182,15 +188,15 @@ macro_rules! binary_func { ) } -binary_func!(bitand, af_bitand); -binary_func!(bitor, af_bitor); -binary_func!(bitxor, af_bitxor); -binary_func!(neq, af_neq); -binary_func!(and, af_and); -binary_func!(or, af_or); -binary_func!(minof, af_minof); -binary_func!(maxof, af_maxof); -binary_func!(hypot, af_hypot); +binary_func!("Elementwise AND(bit) operation of two Arrays", bitand, af_bitand); +binary_func!("Elementwise OR(bit) operation of two Arrays", bitor, af_bitor); +binary_func!("Elementwise XOR(bit) operation of two Arrays", bitxor, af_bitxor); +binary_func!("Elementwise not equals comparison of two Arrays", neq, af_neq); +binary_func!("Elementwise logical and operation of two Arrays", and, af_and); +binary_func!("Elementwise logical or operation of two Arrays", or, af_or); +binary_func!("Elementwise minimum operation of two Arrays", minof, af_minof); +binary_func!("Elementwise maximum operation of two Arrays", maxof, af_maxof); +binary_func!("Compute length of hypotenuse of two Arrays", hypot, af_hypot); pub trait Convertable { fn convert(&self) -> Array; @@ -221,7 +227,7 @@ impl Convertable for Array { } macro_rules! overloaded_binary_func { - ($fn_name: ident, $help_name: ident, $ffi_name: ident) => ( + ($doc_str: expr, $fn_name: ident, $help_name: ident, $ffi_name: ident) => ( fn $help_name(lhs: &Array, rhs: &Array, batch: bool) -> Array { unsafe { let mut temp: i64 = 0; @@ -233,6 +239,22 @@ macro_rules! overloaded_binary_func { } } + #[doc=$doc_str] + /// + /// This is a binary elementwise operation. + /// + ///# Parameters + /// + /// - `arg1`is an argument that implements an internal trait `Convertable`. + /// - `arg2`is an argument that implements an internal trait `Convertable`. + /// - `batch` is an boolean that indicates if the current operation is an batch operation. + /// + /// Both parameters `arg1` and `arg2` can be either an Array or a value of rust integral + /// type. + /// + ///# Return Values + /// + /// An Array with results of the binary operation. pub fn $fn_name (arg1: &T, arg2: &U, batch: bool) -> Array where T: Convertable, U: Convertable { let lhs = arg1.convert(); let rhs = arg2.convert(); @@ -253,23 +275,23 @@ macro_rules! overloaded_binary_func { // thanks to Umar Arshad for the idea on how to // implement overloaded function -overloaded_binary_func!(add, add_helper, af_add); -overloaded_binary_func!(sub, sub_helper, af_sub); -overloaded_binary_func!(mul, mul_helper, af_mul); -overloaded_binary_func!(div, div_helper, af_div); -overloaded_binary_func!(rem, rem_helper, af_rem); -overloaded_binary_func!(shiftl, shiftl_helper, af_bitshiftl); -overloaded_binary_func!(shiftr, shiftr_helper, af_bitshiftr); -overloaded_binary_func!(lt, lt_helper, af_lt); -overloaded_binary_func!(gt, gt_helper, af_gt); -overloaded_binary_func!(le, le_helper, af_le); -overloaded_binary_func!(ge, ge_helper, af_ge); -overloaded_binary_func!(eq, eq_helper, af_eq); -overloaded_binary_func!(modulo, modulo_helper, af_mod); -overloaded_binary_func!(atan2, atan2_helper, af_atan2); -overloaded_binary_func!(cplx2, cplx2_helper, af_cplx2); -overloaded_binary_func!(root, root_helper, af_root); -overloaded_binary_func!(pow, pow_helper, af_pow); +overloaded_binary_func!("Addition of two Arrays", add, add_helper, af_add); +overloaded_binary_func!("Subtraction of two Arrays", sub, sub_helper, af_sub); +overloaded_binary_func!("Multiplication of two Arrays", mul, mul_helper, af_mul); +overloaded_binary_func!("Division of two Arrays", div, div_helper, af_div); +overloaded_binary_func!("Compute remainder from two Arrays", rem, rem_helper, af_rem); +overloaded_binary_func!("Compute left shift", shiftl, shiftl_helper, af_bitshiftl); +overloaded_binary_func!("Compute right shift", shiftr, shiftr_helper, af_bitshiftr); +overloaded_binary_func!("Perform `less than` comparison operation", lt, lt_helper, af_lt); +overloaded_binary_func!("Perform `greater than` comparison operation", gt, gt_helper, af_gt); +overloaded_binary_func!("Perform `less than equals` comparison operation", le, le_helper, af_le); +overloaded_binary_func!("Perform `greater than equals` comparison operation", ge, ge_helper, af_ge); +overloaded_binary_func!("Perform `equals` comparison operation", eq, eq_helper, af_eq); +overloaded_binary_func!("Compute modulo of two Arrays", modulo, modulo_helper, af_mod); +overloaded_binary_func!("Calculate atan2 of two Arrays", atan2, atan2_helper, af_atan2); +overloaded_binary_func!("Create complex array from two Arrays", cplx2, cplx2_helper, af_cplx2); +overloaded_binary_func!("Compute root", root, root_helper, af_root); +overloaded_binary_func!("Computer power", pow, pow_helper, af_pow); macro_rules! arith_scalar_func { ($rust_type: ty, $op_name:ident, $fn_name: ident, $ffi_fn: ident) => ( From 7c3b533b2a42a2c1107acc55b865d051f2cf0016 Mon Sep 17 00:00:00 2001 From: pradeep Date: Wed, 1 Jun 2016 00:03:57 +0530 Subject: [PATCH 06/36] Additional Documentation for Array Object --- src/array.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/array.rs b/src/array.rs index ea85c00e8..35d26feab 100644 --- a/src/array.rs +++ b/src/array.rs @@ -99,8 +99,8 @@ pub struct Array { } macro_rules! is_func { - ($fn_name: ident, $ffi_fn: ident) => ( - /// Checks if the Array is of specific format/data type. + ($doc_str: expr, $fn_name: ident, $ffi_fn: ident) => ( + #[doc=$doc_str] pub fn $fn_name(&self) -> bool { unsafe { let mut ret_val: i32 = 0; @@ -296,20 +296,20 @@ impl Array { } } - is_func!(is_empty, af_is_empty); - is_func!(is_scalar, af_is_scalar); - is_func!(is_row, af_is_row); - is_func!(is_column, af_is_column); - is_func!(is_vector, af_is_vector); - is_func!(is_complex, af_is_complex); - is_func!(is_double, af_is_double); - is_func!(is_single, af_is_single); - is_func!(is_real, af_is_real); - is_func!(is_floating, af_is_floating); - is_func!(is_integer, af_is_integer); - is_func!(is_bool, af_is_bool); - is_func!(is_linear, af_is_linear); - is_func!(is_owner, af_is_owner); + is_func!("Check if Array is empty", is_empty, af_is_empty); + is_func!("Check if Array is scalar", is_scalar, af_is_scalar); + is_func!("Check if Array is a row", is_row, af_is_row); + is_func!("Check if Array is a column", is_column, af_is_column); + is_func!("Check if Array is a vector", is_vector, af_is_vector); + is_func!("Check if Array is of complex type", is_complex, af_is_complex); + is_func!("Check if Array's numerical type is of double precision", is_double, af_is_double); + is_func!("Check if Array's numerical type is of single precision", is_single, af_is_single); + is_func!("Check if Array is of real type", is_real, af_is_real); + is_func!("Check if Array is of single precision", is_floating, af_is_floating); + is_func!("Check if Array is of integral type", is_integer, af_is_integer); + is_func!("Check if Array is of boolean type", is_bool, af_is_bool); + is_func!("Check if Array's memory layout is continuous and one dimensional", is_linear, af_is_linear); + is_func!("Check if Array's memory is owned by it and not a view of another Array", is_owner, af_is_owner); /// Cast the Array data type to `target_type` pub fn cast(&self) -> Array { From 4477f5928bac1e123cce1a154e92a87837feffdd Mon Sep 17 00:00:00 2001 From: pradeep Date: Wed, 1 Jun 2016 00:09:36 +0530 Subject: [PATCH 07/36] Style corrections --- src/backend.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/backend.rs b/src/backend.rs index 26d5b2ba0..df434e1b8 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -42,12 +42,12 @@ pub fn get_available_backends() -> Vec { let mut temp: i32 = 0; let err_val = af_get_available_backends(&mut temp as *mut c_int); 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 } } @@ -67,4 +67,4 @@ pub fn get_active_backend() -> Backend { _ => panic!("Invalid backend retrieved, undefined behavior."), } } -} \ No newline at end of file +} From 81c50f7dc51a14ade480b362f07396854bf5b520 Mon Sep 17 00:00:00 2001 From: pradeep Date: Mon, 6 Jun 2016 15:38:33 +0530 Subject: [PATCH 08/36] Documentation update --- src/data/mod.rs | 37 +++++++++++++++++++------- src/image/mod.rs | 44 ++++++++++++++++++++---------- src/index.rs | 12 ++++----- src/signal/mod.rs | 54 ++++++++++++++----------------------- src/statistics/mod.rs | 62 +++++++++++++++++++++---------------------- src/vision/mod.rs | 21 +++++++++------ 6 files changed, 128 insertions(+), 102 deletions(-) diff --git a/src/data/mod.rs b/src/data/mod.rs index 6c8b6509b..7edad1665 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -270,7 +270,16 @@ pub fn get_seed() -> u64 { } macro_rules! data_gen_def { - ($fn_name:ident, $ffi_name: ident) => ( + ($doc_str: expr, $fn_name:ident, $ffi_name: ident) => ( + #[doc=$doc_str] + /// + ///# Parameters + /// + /// - `dims` is the output dimensions + /// + ///# Return Values + /// + /// An Array with modified data. #[allow(unused_mut)] pub fn $fn_name(dims: Dim4) -> Array { unsafe { @@ -286,9 +295,9 @@ macro_rules! data_gen_def { ) } -data_gen_def!(randu, af_randu); -data_gen_def!(randn, af_randn); -data_gen_def!(identity, af_identity); +data_gen_def!("Create random numbers from uniform distribution", randu, af_randu); +data_gen_def!("Create random numbers from normal distribution", randn, af_randn); +data_gen_def!("Create an identity array with 1's in diagonal", identity, af_identity); /// Create a diagonal matrix /// @@ -380,7 +389,17 @@ pub fn join_many(dim: i32, inputs: Vec<&Array>) -> Array { } macro_rules! data_func_def { - ($fn_name:ident, $ffi_name: ident) => ( + ($doc_str: expr, $fn_name:ident, $ffi_name: ident) => ( + #[doc=$doc_str] + /// + ///# Parameters + /// + /// - `input` is the input Array + /// - `dims` is the target(output) dimensions + /// + ///# Return Values + /// + /// An Array with modified data. #[allow(unused_mut)] pub fn $fn_name(input: &Array, dims: Dim4) -> Array { unsafe { @@ -395,9 +414,9 @@ macro_rules! data_func_def { ) } -data_func_def!(tile, af_tile); -data_func_def!(reorder, af_reorder); -data_func_def!(shift, af_shift); +data_func_def!("Tile the input array along specified dimension", tile, af_tile); +data_func_def!("Reorder the array in specified order", reorder, af_reorder); +data_func_def!("Circular shift of values along specified dimension", shift, af_shift); /// Change the shape of the Array /// @@ -635,4 +654,4 @@ pub fn replace_scalar(a: &mut Array, cond: &Array, b: f64) { let err_val = af_replace_scalar(a.get() as AfArray, cond.get() as AfArray, b as c_double); 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 19bbc9639..be0efe011 100644 --- a/src/image/mod.rs +++ b/src/image/mod.rs @@ -652,7 +652,19 @@ pub fn mean_shift(input: &Array, spatial_sigma: f32, chromatic_sigma: f32, } macro_rules! filt_func_def { - ($fn_name: ident, $ffi_name: ident) => ( + ($doc_str: expr, $fn_name: ident, $ffi_name: ident) => ( + #[doc=$doc_str] + /// + ///# Parameters + /// + /// - `input` is the input image(Array) + /// - `wlen` is the horizontal length of the filter + /// - `hlen` is the vertical length of the filter + /// - `etype` is enum of type [BorderType](./enum.BorderType.html) + /// + ///# Return Values + /// + /// An Array with filtered image data. #[allow(unused_mut)] pub fn $fn_name(input: &Array, wlen: u64, wwid: u64, etype: BorderType) -> Array { @@ -667,9 +679,9 @@ macro_rules! filt_func_def { ) } -filt_func_def!(medfilt, af_medfilt); -filt_func_def!(minfilt, af_minfilt); -filt_func_def!(maxfilt, af_maxfilt); +filt_func_def!("Median filter", medfilt, af_medfilt); +filt_func_def!("Box filter with minimum as box operation", minfilt, af_minfilt); +filt_func_def!("Box filter with maximum as box operation", maxfilt, af_maxfilt); /// Creates a Gaussian Kernel. /// @@ -830,14 +842,18 @@ pub fn hist_equal(input: &Array, hist: &Array) -> Array { } macro_rules! grayrgb_func_def { - ($fn_name: ident, $ffi_name: ident) => ( - /// Color space conversion functions + ($doc_str: expr, $fn_name: ident, $ffi_name: ident) => ( + #[doc=$doc_str] /// - /// # Parameters + ///# Parameters /// /// - `r` is fraction of red channel to appear in output /// - `g` is fraction of green channel to appear in output /// - `b` is fraction of blue channel to appear in output + /// + ///#Return Values + /// + ///An Array with image data in target color space #[allow(unused_mut)] pub fn $fn_name(input: &Array, r: f32, g: f32, b: f32) -> Array { unsafe { @@ -851,12 +867,12 @@ macro_rules! grayrgb_func_def { ) } -grayrgb_func_def!(rgb2gray, af_rgb2gray); -grayrgb_func_def!(gray2rgb, af_gray2rgb); +grayrgb_func_def!("Color(RGB) to Grayscale conversion", rgb2gray, af_rgb2gray); +grayrgb_func_def!("Grayscale to Color(RGB) conversion", gray2rgb, af_gray2rgb); macro_rules! hsvrgb_func_def { - ($fn_name: ident, $ffi_name: ident) => ( - /// Color space conversion functions + ($doc_str: expr, $fn_name: ident, $ffi_name: ident) => ( + #[doc=$doc_str] #[allow(unused_mut)] pub fn $fn_name(input: &Array) -> Array { unsafe { @@ -869,8 +885,8 @@ macro_rules! hsvrgb_func_def { ) } -hsvrgb_func_def!(hsv2rgb, af_hsv2rgb); -hsvrgb_func_def!(rgb2hsv, af_rgb2hsv); +hsvrgb_func_def!("HSV to RGB color space conversion", hsv2rgb, af_hsv2rgb); +hsvrgb_func_def!("RGB to HSV color space conversion", rgb2hsv, af_rgb2hsv); /// Generate an array with image windows as columns /// @@ -1119,4 +1135,4 @@ pub fn transform_coords(tf: &Array, d0: f32, d1: f32) -> Array { 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 d45a93b5e..f520578cd 100644 --- a/src/index.rs +++ b/src/index.rs @@ -160,7 +160,7 @@ pub fn row(input: &Array, row_num: u64) -> Array { } #[allow(dead_code)] -/// Set row `row_num` in `input` Array to a new Array `new_row` +/// Set `row_num`^th row in `input` Array to a new Array `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()], @@ -168,7 +168,7 @@ pub fn set_row(input: &Array, new_row: &Array, row_num: u64) -> Array { } #[allow(dead_code)] -/// Get all rows from `first` to `last` in the `input` Array +/// Get an Array with all rows from `first` to `last` in the `input` Array pub fn rows(input: &Array, first: u64, last: u64) -> Array { index(input, &[Seq::new(first as f64, last as f64, 1.0), Seq::default()]) } @@ -197,7 +197,7 @@ pub fn col(input: &Array, col_num: u64) -> Array { } #[allow(dead_code)] -/// Set col `col_num` in `input` Array to a new Array `new_col` +/// Set `col_num`^th col in `input` Array to a new Array `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)], @@ -217,11 +217,11 @@ pub fn set_cols(input: &Array, new_cols: &Array, first: u64, last: u64) -> Array } #[allow(dead_code)] -/// Get slice `slice_num` from `input` Array +/// Get `slice_num`^th slice from `input` Array /// -/// Slices indicate that the indexing is along 3rd dimension +/// Note. Slices indicate that the indexing is along 3rd dimension pub fn slice(input: &Array, slice_num: u64) -> Array { - index(input, + index(input, &[Seq::default(), Seq::default(), Seq::new(slice_num as f64, slice_num as f64, 1.0)]) } diff --git a/src/signal/mod.rs b/src/signal/mod.rs index ac1c385c9..aa385a071 100644 --- a/src/signal/mod.rs +++ b/src/signal/mod.rs @@ -270,28 +270,21 @@ pub fn ifft3(input: &Array, norm_factor: f64, } macro_rules! conv_func_def { - ($fn_name:ident, $ffi_name: ident) => ( - /// Convolution + ($doc_str: expr, $fn_name:ident, $ffi_name: ident) => ( + #[doc=$doc_str] /// - /// The numeric suffix to the function name indicates the dimension in which the - /// convolution operation is going to take place. - /// - /// - 1 - Indicates 1d convolution - /// - 2 - Indicates 2d convolution - /// - 3 - Indicates 3d convolution - /// - /// # Parameters + ///# Parameters /// /// - `signal` is the input signal /// - `filter` is the signal that shall be flipped for convolution operation /// - `mode` indicates if the convolution should be expanded or not(where output size - /// equals input) + /// equals input). It takes a value of type [ConvMode](./enum.ConvMode.html) /// - `domain` indicates if the convolution should be performed in frequencey or spatial - /// domain + /// domain. It takes a value of type [ConvDomain](./enum.ConvDomain.html) /// - /// # Return Values + ///# Return Values /// - /// The convolved Array + /// Convolved Array #[allow(unused_mut)] pub fn $fn_name(signal: &Array, filter: &Array, mode: ConvMode, domain: ConvDomain) -> Array { @@ -307,9 +300,9 @@ macro_rules! conv_func_def { ) } -conv_func_def!(convolve1, af_convolve1); -conv_func_def!(convolve2, af_convolve2); -conv_func_def!(convolve3, af_convolve3); +conv_func_def!("1d convolution", convolve1, af_convolve1); +conv_func_def!("2d convolution", convolve2, af_convolve2); +conv_func_def!("3d convolution", convolve3, af_convolve3); /// Separable convolution for 2d signals /// @@ -337,26 +330,19 @@ pub fn convolve2_sep(cfilt: &Array, rfilt: &Array, signal: &Array, } macro_rules! fft_conv_func_def { - ($fn_name:ident, $ffi_name: ident) => ( - /// Convolution using Fast-fourier transform - /// - /// The numeric suffix to the function name indicates the dimension in which the - /// convolution operation is going to take place. + ($doc_str: expr, $fn_name:ident, $ffi_name: ident) => ( + #[doc=$doc_str] /// - /// - 1 - Indicates 1d convolution - /// - 2 - Indicates 2d convolution - /// - 3 - Indicates 3d convolution - /// - /// # Parameters + ///# Parameters /// /// - `signal` is the input signal /// - `filter` is the signal that shall be used for convolution operation /// - `mode` indicates if the convolution should be expanded or not(where output size - /// equals input) + /// equals input). It takes values of type [ConvMode](./enum.ConvMode.html) /// - /// # Return Values + ///# Return Values /// - /// The convolved Array + /// Convolved Array #[allow(unused_mut)] pub fn $fn_name(signal: &Array, filter: &Array, mode: ConvMode) -> Array { @@ -371,9 +357,9 @@ macro_rules! fft_conv_func_def { ) } -fft_conv_func_def!(fft_convolve1, af_fft_convolve1); -fft_conv_func_def!(fft_convolve2, af_fft_convolve2); -fft_conv_func_def!(fft_convolve3, af_fft_convolve3); +fft_conv_func_def!("1d convolution using fast-fourier transform", fft_convolve1, af_fft_convolve1); +fft_conv_func_def!("2d convolution using fast-fourier transform", fft_convolve2, af_fft_convolve2); +fft_conv_func_def!("3d convolution using fast-fourier transform", fft_convolve3, af_fft_convolve3); /// Finite impulse filter /// @@ -623,4 +609,4 @@ pub fn fft3_c2r(input: &Array, norm_factor: f64, is_odd: bool) -> Array { 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 12ccea02f..cb1269a5c 100644 --- a/src/statistics/mod.rs +++ b/src/statistics/mod.rs @@ -34,18 +34,18 @@ extern { } macro_rules! stat_func_def { - ($fn_name: ident, $ffi_fn: ident) => ( - /// Compute a statistic along given dimension for an Array + ($doc_str: expr, $fn_name: ident, $ffi_fn: ident) => ( + #[doc=$doc_str] /// - /// # Parameters + ///# Parameters /// /// - `input` is the input Array /// - `dim` is dimension along which the current stat has to be computed /// - /// # Return Values + ///# Return Values /// - /// 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. + /// 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) -> Array { unsafe { @@ -58,24 +58,24 @@ macro_rules! stat_func_def { ) } -stat_func_def!(mean, af_mean); -stat_func_def!(stdev, af_stdev); -stat_func_def!(median, af_median); +stat_func_def!("Mean along specified dimension", mean, af_mean); +stat_func_def!("Standard deviation along specified dimension", stdev, af_stdev); +stat_func_def!("Median along specified dimension", median, af_median); macro_rules! stat_wtd_func_def { - ($fn_name: ident, $ffi_fn: ident) => ( - /// Compute a weighted statistic along given dimension for an Array + ($doc_str: expr, $fn_name: ident, $ffi_fn: ident) => ( + #[doc=$doc_str] /// - /// # Parameters + ///# Parameters /// /// - `input` is the input Array /// - `weights` Array has the weights to be used during the stat computation /// - `dim` is dimension along which the current stat has to be computed /// - /// # Return Values + ///# Return Values /// - /// 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. + /// 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) -> Array { unsafe { @@ -89,8 +89,8 @@ macro_rules! stat_wtd_func_def { ) } -stat_wtd_func_def!(mean_weighted, af_mean_weighted); -stat_wtd_func_def!(var_weighted, af_var_weighted); +stat_wtd_func_def!("Weighted mean along specified dimension", mean_weighted, af_mean_weighted); +stat_wtd_func_def!("Weight variance along specified dimension", var_weighted, af_var_weighted); /// Compute Variance along a specific dimension /// @@ -159,14 +159,14 @@ pub fn var_all(input: &Array, isbiased: bool) -> (f64, f64) { } macro_rules! stat_all_func_def { - ($fn_name: ident, $ffi_fn: ident) => ( - /// Compute statistic for all elements of Array + ($doc_str: expr, $fn_name: ident, $ffi_fn: ident) => ( + #[doc=$doc_str] /// - /// # Parameters + ///# Parameters /// /// - `input` is the input Array /// - /// # Return Values + ///# Return Values /// /// A tuple of 64-bit floating point values with the stat values. #[allow(unused_mut)] @@ -183,20 +183,20 @@ macro_rules! stat_all_func_def { ) } -stat_all_func_def!(mean_all, af_mean_all); -stat_all_func_def!(stdev_all, af_stdev_all); -stat_all_func_def!(median_all, af_median_all); +stat_all_func_def!("Compute mean of all data", mean_all, af_mean_all); +stat_all_func_def!("Compute standard deviation of all data", stdev_all, af_stdev_all); +stat_all_func_def!("Compute median of all data", median_all, af_median_all); macro_rules! stat_wtd_all_func_def { - ($fn_name: ident, $ffi_fn: ident) => ( - /// Compute weighted statistic for all elements of Array + ($doc_str: expr, $fn_name: ident, $ffi_fn: ident) => ( + #[doc=$doc_str] /// - /// # Parameters + ///# Parameters /// /// - `input` is the input Array /// - `weights` Array has the weights /// - /// # Return Values + ///# Return Values /// /// A tuple of 64-bit floating point values with the stat values. #[allow(unused_mut)] @@ -213,8 +213,8 @@ macro_rules! stat_wtd_all_func_def { ) } -stat_wtd_all_func_def!(mean_all_weighted, af_mean_all_weighted); -stat_wtd_all_func_def!(var_all_weighted, af_var_all_weighted); +stat_wtd_all_func_def!("Compute weighted mean of all data", mean_all_weighted, af_mean_all_weighted); +stat_wtd_all_func_def!("Compute weighted variance of all data", var_all_weighted, af_var_all_weighted); /// Compute correlation coefficient /// @@ -235,4 +235,4 @@ pub fn corrcoef(x: &Array, y: &Array) -> (f64, f64) { HANDLE_ERROR(AfError::from(err_val)); (real, imag) } -} \ No newline at end of file +} diff --git a/src/vision/mod.rs b/src/vision/mod.rs index 48791a458..ab88a6004 100644 --- a/src/vision/mod.rs +++ b/src/vision/mod.rs @@ -75,7 +75,8 @@ pub struct Features { } macro_rules! feat_func_def { - ($fn_name: ident, $ffi_name: ident) => ( + ($doc_str: expr, $fn_name: ident, $ffi_name: ident) => ( + #[doc=$doc_str] pub fn $fn_name(&self) -> Array { unsafe { let mut temp: i64 = 0; @@ -84,7 +85,7 @@ macro_rules! feat_func_def { let temp_array = Array::from(temp); let retained = temp_array.clone(); mem::forget(temp_array); - + HANDLE_ERROR(AfError::from(err_val)); retained } @@ -93,6 +94,9 @@ macro_rules! feat_func_def { } impl Features { + /// Create and return an object of type Features + /// + /// This object is basically a bunch of Arrays. #[allow(unused_mut)] pub fn new(n: u64) -> Features { unsafe { @@ -115,12 +119,13 @@ impl Features { } } - feat_func_def!(xpos, af_get_features_xpos); - feat_func_def!(ypos, af_get_features_ypos); - feat_func_def!(score, af_get_features_score); - feat_func_def!(orientation, af_get_features_orientation); - feat_func_def!(size, af_get_features_size); + feat_func_def!("Get x coordinates Array", xpos, af_get_features_xpos); + feat_func_def!("Get y coordinates Array", ypos, af_get_features_ypos); + feat_func_def!("Get score Array", score, af_get_features_score); + feat_func_def!("Get orientation Array", orientation, af_get_features_orientation); + feat_func_def!("Get features size Array", size, af_get_features_size); + /// Get the internal handle for [Features](./struct.Features.html) object pub fn get(&self) -> i64 { self.feat } @@ -500,4 +505,4 @@ pub fn homography(x_src: &Array, y_src: &Array, HANDLE_ERROR(AfError::from(err_val)); (Array::from(temp), inliers) } -} \ No newline at end of file +} From bcdc406064bf4fc94f1c829b6d9dfd71fe3d445a Mon Sep 17 00:00:00 2001 From: pradeep Date: Tue, 14 Jun 2016 12:13:46 +0530 Subject: [PATCH 09/36] Update arrayfire submodule to latest --- arrayfire | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arrayfire b/arrayfire index 5842ed251..a4fa33844 160000 --- a/arrayfire +++ b/arrayfire @@ -1 +1 @@ -Subproject commit 5842ed25195848653148fa9b3a8270255d83f5b8 +Subproject commit a4fa33844fbd19286f57f12e06268d8ce855bbea From 5aa5bbd3943411b779b89fba742c307a84f2be61 Mon Sep 17 00:00:00 2001 From: pradeep Date: Tue, 14 Jun 2016 12:51:00 +0530 Subject: [PATCH 10/36] fn to change fft plan cache size used by ArrayFire fft fns --- src/lib.rs | 2 +- src/signal/mod.rs | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 33ac66788..717133cf4 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -82,7 +82,7 @@ mod lapack; mod macros; mod num; -pub use signal::{approx1, approx2}; +pub use signal::{approx1, approx2, set_fft_plan_cache_size}; pub use signal::{fft, fft2, fft3, ifft, ifft2, ifft3}; pub use signal::{fft_r2c, fft2_r2c, fft3_r2c, fft_c2r, fft2_c2r, fft3_c2r}; pub use signal::{fft_inplace, fft2_inplace, fft3_inplace}; diff --git a/src/signal/mod.rs b/src/signal/mod.rs index aa385a071..cf404cbf3 100644 --- a/src/signal/mod.rs +++ b/src/signal/mod.rs @@ -3,7 +3,7 @@ extern crate libc; use array::Array; use defines::{AfError, ConvDomain, ConvMode, InterpType}; use error::HANDLE_ERROR; -use self::libc::{uint8_t, c_int, c_float, c_double, c_longlong}; +use self::libc::{uint8_t, c_int, c_float, c_double, c_longlong, size_t}; type MutAfArray = *mut self::libc::c_longlong; type AfArray = self::libc::c_longlong; @@ -16,6 +16,8 @@ extern { fn af_approx2(out: MutAfArray, inp: AfArray, pos0: AfArray, pos1: AfArray, method: c_int, off_grid: c_float) -> c_int; + fn af_set_fft_plan_cache_size(cache_size: size_t) -> c_int; + fn af_fft(out: MutAfArray, arr: AfArray, nfac: c_double, odim0: c_longlong) -> c_int; @@ -115,6 +117,18 @@ pub fn approx2(input: &Array, pos0: &Array, pos1: &Array, } } +/// Set fft plan cache size +/// +/// Though this is a low overhead function, it is advised not to change +/// the fft plan cache size a mid program execution unless that is what +/// you intend to do. +pub fn set_fft_plan_cache_size(cache_size: usize) { + unsafe { + let err_val = af_set_fft_plan_cache_size(cache_size as size_t); + HANDLE_ERROR(AfError::from(err_val)); + } +} + /// Fast fourier transform for 1d signals /// /// # Parameters From 3aaa5b2dea8abf90535bafbb7f3c8e0b7ac3c582 Mon Sep 17 00:00:00 2001 From: pradeep Date: Fri, 29 Jul 2016 12:00:00 +0530 Subject: [PATCH 11/36] Update upstream project, ArrayFire, submodule to latest commit --- arrayfire | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arrayfire b/arrayfire index a4fa33844..71da292bc 160000 --- a/arrayfire +++ b/arrayfire @@ -1 +1 @@ -Subproject commit a4fa33844fbd19286f57f12e06268d8ce855bbea +Subproject commit 71da292bc42e29639443b6873a5de364fa7a45b9 From 8564b2d2e5b9aa4d4852d512a0a60d7d7d8ab706 Mon Sep 17 00:00:00 2001 From: pradeep Date: Fri, 29 Jul 2016 17:48:14 +0530 Subject: [PATCH 12/36] 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 717133cf4..e517c1349 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 f77d4ae23c4ccaf028477365e510766054b9cba0 Mon Sep 17 00:00:00 2001 From: pradeep Date: Fri, 29 Jul 2016 21:21:31 +0530 Subject: [PATCH 13/36] Add Image Moments functions --- src/defines.rs | 11 +++++++++++ src/image/mod.rs | 49 +++++++++++++++++++++++++++++++++++++++++++++++- src/lib.rs | 3 ++- 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/src/defines.rs b/src/defines.rs index 669f2e053..e75ebaa2a 100644 --- a/src/defines.rs +++ b/src/defines.rs @@ -333,3 +333,14 @@ pub enum MarkerType { PLUS = 6, STAR = 7 } + +/// Image moment types +#[repr(C)] +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum MomentType { + M00 = 1, // 1<<0 + M01 = 2, // 1<<1 + M10 = 4, // 1<<2 + M11 = 8, // 1<<3 + FIRST_ORDER = 1<<0 | 1<<1 | 1<<2 | 1<<3 +} diff --git a/src/image/mod.rs b/src/image/mod.rs index be0efe011..7b5bdb3cb 100644 --- a/src/image/mod.rs +++ b/src/image/mod.rs @@ -1,7 +1,7 @@ extern crate libc; use array::Array; -use defines::{AfError, BorderType, ColorSpace, Connectivity, InterpType, YCCStd}; +use defines::{AfError, BorderType, ColorSpace, Connectivity, InterpType, YCCStd, MomentType}; use error::HANDLE_ERROR; use util::HasAfEnum; use self::libc::{uint8_t, c_uint, c_int, c_float, c_double}; @@ -93,6 +93,9 @@ extern { 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; + + fn af_moments(out: MutAfArray, input: AfArray, moment: c_int) ->c_int; + fn af_moments_all(out: *mut c_double, input: AfArray, moment: c_int) ->c_int; } /// Calculate the gradients @@ -1136,3 +1139,47 @@ pub fn transform_coords(tf: &Array, d0: f32, d1: f32) -> Array { Array::from(temp) } } + +/// Find Image moments +/// +/// # Parameters +/// +/// - `input` is the input image +/// - `moment` is the type of moment to be computed, takes a value of +/// [enum](./enum.MomentType.html) +/// +/// # Return Values +/// +/// Moments Array +pub fn moments(input: &Array, moment: MomentType) -> Array { + unsafe { + let mut temp: i64 = 0; + let err_val = af_moments(&mut temp as MutAfArray, + input.get() as AfArray, + moment as c_int); + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) + } +} + +/// Find Image moment for whole image +/// +/// # Parameters +/// +/// - `input` is the input image +/// - `moment` is the type of moment to be computed, takes a value of +/// [enum](./enum.MomentType.html) +/// +/// # Return Values +/// +/// Moment value of the whole image +pub fn moments_all(input: &Array, moment: MomentType) -> f64 { + unsafe { + let mut temp: f64 = 0.0; + let err_val = af_moments_all(&mut temp as *mut c_double, + input.get() as AfArray, + moment as c_int); + HANDLE_ERROR(AfError::from(err_val)); + temp + } +} diff --git a/src/lib.rs b/src/lib.rs index e517c1349..3081335da 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,7 +47,7 @@ mod device; 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}; +pub use defines::{MarkerType, MomentType}; mod defines; pub use dim4::Dim4; @@ -74,6 +74,7 @@ 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, is_imageio_available, transform_coords}; +pub use image::{moments, moments_all}; mod image; pub use lapack::{svd, lu, qr, cholesky, solve, solve_lu, inverse, det, rank, norm}; From e63eb0c1943d98084407d168af7c18b1add069d3 Mon Sep 17 00:00:00 2001 From: pradeep Date: Mon, 12 Sep 2016 14:06:15 +0530 Subject: [PATCH 14/36] update ArrayFire upstream to latest commit of devel --- arrayfire | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arrayfire b/arrayfire index 71da292bc..2f474a804 160000 --- a/arrayfire +++ b/arrayfire @@ -1 +1 @@ -Subproject commit 71da292bc42e29639443b6873a5de364fa7a45b9 +Subproject commit 2f474a804a381915770981f518493204bb53d3c1 From 551d05462c5d930497f1c0531c7061054577e89c Mon Sep 17 00:00:00 2001 From: pradeep Date: Mon, 12 Sep 2016 14:55:36 +0530 Subject: [PATCH 15/36] FEATURE: clamp function in arith module --- src/arith/mod.rs | 30 ++++++++++++++++++++++++++++++ src/lib.rs | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/arith/mod.rs b/src/arith/mod.rs index 8d7223ab2..af0faf0ac 100644 --- a/src/arith/mod.rs +++ b/src/arith/mod.rs @@ -42,6 +42,7 @@ extern { fn af_bitshiftr(out: MutAfArray, lhs: AfArray, rhs: AfArray, batch: c_int) -> c_int; fn af_minof(out: MutAfArray, lhs: AfArray, rhs: AfArray, batch: c_int) -> c_int; fn af_maxof(out: MutAfArray, lhs: AfArray, rhs: AfArray, batch: c_int) -> c_int; + fn af_clamp(out: MutAfArray, inp: AfArray, lo: AfArray, hi: AfArray, batch: c_int) -> c_int; fn af_not(out: MutAfArray, arr: AfArray) -> c_int; fn af_abs(out: MutAfArray, arr: AfArray) -> c_int; @@ -293,6 +294,35 @@ overloaded_binary_func!("Create complex array from two Arrays", cplx2, cplx2_hel overloaded_binary_func!("Compute root", root, root_helper, af_root); overloaded_binary_func!("Computer power", pow, pow_helper, af_pow); +pub fn clamp (input: &Array, arg1: &T, arg2: &U, batch: bool) -> Array + where T: Convertable, U: Convertable +{ + let clamp_helper = |lo: &Array, hi: &Array| { + unsafe { + let mut temp: i64 = 0; + let err_val = af_clamp(&mut temp as MutAfArray, input.get() as AfArray, + lo.get() as AfArray, hi.get() as AfArray, + batch as c_int); + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) + } + }; + + let lo = arg1.convert(); + let hi = arg2.convert(); + match (lo.is_scalar(), hi.is_scalar()) { + ( true, false) => { + let l = tile(&lo, hi.dims()); + clamp_helper(&l, &hi) + }, + (false, true) => { + let r = tile(&hi, lo.dims()); + clamp_helper(&lo, &r) + }, + _ => clamp_helper(&lo, &hi), + } +} + macro_rules! arith_scalar_func { ($rust_type: ty, $op_name:ident, $fn_name: ident, $ffi_fn: ident) => ( impl<'f> $op_name<$rust_type> for &'f Array { diff --git a/src/lib.rs b/src/lib.rs index 3081335da..e97074695 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,7 +19,7 @@ mod algorithm; pub use arith::{add, sub, div, mul, lt, gt, le, ge, eq, neq, and, or, minof, maxof, rem}; pub use arith::{bitand, bitor, bitxor, shiftl, shiftr}; -pub use arith::{abs, sign, round, trunc, floor, ceil, modulo, sigmoid}; +pub use arith::{abs, sign, round, trunc, floor, ceil, modulo, sigmoid, clamp}; pub use arith::{sin, cos, tan, asin, acos, atan, sinh, cosh, tanh, asinh, acosh, atanh}; pub use arith::{atan2, cplx2, arg, cplx, real, imag, conjg, hypot}; pub use arith::{sqrt, log, log1p, log10, log2, pow2, exp, expm1, erf, erfc, root, pow}; From 8cb8a3fe450cd6306d32a05b0d84bc3b84f48f53 Mon Sep 17 00:00:00 2001 From: pradeep Date: Mon, 12 Sep 2016 15:46:57 +0530 Subject: [PATCH 16/36] FEATURE: multiple array evaluation * function to set manual evaluation setting * function to check manual evaluation setting * multiple array evaluation macro `eval!` --- src/array.rs | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 +- src/macros.rs | 14 +++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/array.rs b/src/array.rs index bce78cb2f..29a3494bc 100644 --- a/src/array.rs +++ b/src/array.rs @@ -63,6 +63,12 @@ extern { fn af_eval(arr: AfArray) -> c_int; + fn af_eval_multiple(num: c_int, arrays: *const AfArray) -> c_int; + + fn af_set_manual_eval_flag(flag: c_int) -> c_int; + + fn af_get_manual_eval_flag(flag: *mut c_int) -> c_int; + fn af_retain_array(out: MutAfArray, arr: AfArray) -> c_int; fn af_copy_array(out: MutAfArray, arr: AfArray) -> c_int; @@ -385,3 +391,53 @@ pub fn print(input: &Array) { HANDLE_ERROR(AfError::from(err_val)); } } + +/// evaluate multiple arrays +/// +/// Use this function to evaluate multiple arrays in single call +/// +/// # Parameters +/// +/// - `inputs` are the list of arrays to be evaluated +pub fn eval_multiple(inputs: Vec<&Array>) { + unsafe { + let mut v = Vec::new(); + for i in inputs { + v.push(i.get()); + } + + let err_val = af_eval_multiple(v.len() as c_int, v.as_ptr() as *const AfArray); + HANDLE_ERROR(AfError::from(err_val)); + } +} + +/// Set eval flag value +/// +/// This function can be used to toggle on/off the manual evaluation of arrays. +/// +/// # Parameters +/// +/// - `flag` is a boolean value indicating manual evaluation setting +pub fn set_manual_eval(flag: bool) { + unsafe { + let err_val = af_set_manual_eval_flag(flag as c_int); + HANDLE_ERROR(AfError::from(err_val)); + } +} + +/// Get eval flag value +/// +/// This function can be used to find out if manual evaluation of arrays is +/// turned on or off. +/// +/// # Return Values +/// +/// A boolean indicating manual evaluation setting. +pub fn is_eval_manual() -> bool { + unsafe { + let mut ret_val: i32 = 0; + let err_val = af_get_manual_eval_flag(&mut ret_val as *mut c_int); + HANDLE_ERROR(AfError::from(err_val)); + ret_val > 0 + } +} diff --git a/src/lib.rs b/src/lib.rs index e97074695..9a09e403d 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,7 +6,7 @@ extern crate lazy_static; pub use array::Array; -pub use array::{print}; +pub use array::{print, eval_multiple, is_eval_manual, set_manual_eval}; mod array; //pub use algorithm::{sum_nan, product_nan, sum_nan_all, product_nan_all}; diff --git a/src/macros.rs b/src/macros.rs index bc509379a..5ceb4ca8d 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -128,3 +128,17 @@ macro_rules! af_print { } }; } + +/// Evaluate arbitrary number of arrays +#[macro_export] +macro_rules! eval { + [$($x:ident),+] => { + { + let mut temp_vec = Vec::new(); + $( + temp_vec.push($x); + )* + eval_multiple(temp_vec) + } + }; +} From 95458f71dc5c1592d4e89f1d24cf80299daf618c Mon Sep 17 00:00:00 2001 From: pradeep Date: Mon, 12 Sep 2016 17:36:44 +0530 Subject: [PATCH 17/36] FEATURE: vector field rendering functions * broke API for plot/scatter rendering functions. * Added a more comprehensive and better API for plot/scatter functions. * Added API for setting 2d/3d chart axes limits and titles --- src/graphics.rs | 264 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 238 insertions(+), 26 deletions(-) diff --git a/src/graphics.rs b/src/graphics.rs index 42a2dbd18..b15f3e95a 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -4,7 +4,7 @@ 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 self::libc::{c_int, c_uint, c_float, c_double, c_char}; use std::ffi::CString; type MutWndHandle = *mut self::libc::c_ulonglong; @@ -15,19 +15,49 @@ type CellPtr = *const self::libc::c_void; #[allow(dead_code)] extern { fn af_create_window(out: MutWndHandle, w: c_int, h: c_int, title: *const c_char) -> c_int; + 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_set_axes_titles(wnd: WndHandle, + xtitle: *const c_char, ytitle: *const c_char, ztitle: *const c_char, + props: CellPtr) -> c_int; + fn af_set_axes_limits_compute(wnd: WndHandle, x: AfArray, y: AfArray, z: AfArray, + exact: c_int, props: CellPtr) -> c_int; + fn af_set_axes_limits_2d(wnd: WndHandle, xmin: c_float, xmax: c_float, + ymin: c_float, ymax: c_float, + exact: c_int, props: CellPtr) -> c_int; + fn af_set_axes_limits_3d(wnd: WndHandle, xmin: c_float, xmax: c_float, + ymin: c_float, ymax: c_float, + zmin: c_float, zmax: c_float, + exact: c_int, props: CellPtr) -> 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; fn af_draw_hist(wnd: WndHandle, x: AfArray, 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_draw_plot_2d(wnd: WndHandle, x: AfArray, y: AfArray, props: CellPtr) -> c_int; + fn af_draw_plot_3d(wnd: WndHandle, x: AfArray, y: AfArray, z: AfArray, props: CellPtr) -> c_int; + fn af_draw_plot_nd(wnd: WndHandle, P: AfArray, props: CellPtr) -> c_int; + + fn af_draw_scatter_2d(wnd: WndHandle, x: AfArray, y: AfArray, + marker: c_int, props: CellPtr) -> c_int; + fn af_draw_scatter_3d(wnd: WndHandle, x: AfArray, y: AfArray, z: AfArray, + marker: c_int, props: CellPtr) -> c_int; + fn af_draw_scatter_nd(wnd: WndHandle, P: AfArray, + marker: c_int, props: CellPtr) -> c_int; + + fn af_draw_vector_field_2d(wnd: WndHandle, xpnts: AfArray, ypnts: AfArray, + xdirs: AfArray, ydirs: AfArray, props: CellPtr) -> c_int; + fn af_draw_vector_field_3d(wnd: WndHandle, xpnts: AfArray, ypnts: AfArray, + xdirs: AfArray, ydirs: AfArray, zdirs: AfArray, zdirs: AfArray, + props: CellPtr) -> c_int; + fn af_draw_vector_field_nd(wnd: WndHandle, pnts: AfArray, dirs: AfArray, 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; @@ -216,6 +246,110 @@ impl Window { self.col = c; } + /// Set chart axes titles + /// + /// # Parameters + /// + /// - `xlabel` is x axis title + /// - `ylabel` is y axis title + /// - `zlabel` is z axis title + pub fn set_axes_titles(&mut self, xlabel: String, ylabel: String, zlabel: String) { + let cprops = &Cell {row: self.row, col: self.col, title: String::from(""), cmap: self.cmap}; + let xstr = CString::new(xlabel.as_bytes()).unwrap(); + let ystr = CString::new(ylabel.as_bytes()).unwrap(); + let zstr = CString::new(zlabel.as_bytes()).unwrap(); + unsafe { + let err_val = af_set_axes_titles(self.handle as WndHandle, + xstr.to_bytes_with_nul().as_ptr() as *const c_char, + ystr.to_bytes_with_nul().as_ptr() as *const c_char, + zstr.to_bytes_with_nul().as_ptr() as *const c_char, + cprops as *const Cell as CellPtr); + HANDLE_ERROR(AfError::from(err_val)); + } + } + + /// Set chart axes limits by computing limits from data + /// + /// In multiple view (grid) mode, setting limits will effect the chart that is currently + /// active via set_view call + /// + /// # Parameters + /// + /// - `xrange` is set of all x values to compute min/max for x axis + /// - `yrange` is set of all y values to compute min/max for y axis + /// - `zrange` is set of all z values to compute min/max for z axis. If None is passed to + /// this paramter, 2d chart limits are set. + /// - `exact` indicates if the exact min/max values from `xrange`, `yrange` and `zrange` + /// are to extracted. If exact is false then the most significant digit is rounded up + /// to next power of 2 and the magnitude remains the same. + pub fn set_axes_limits_compute(&mut self, xrange: &Array, yrange: &Array, + zrange: Option<&Array>, exact: bool) { + let cprops = &Cell {row: self.row, col: self.col, title: String::from(""), cmap: self.cmap}; + unsafe { + let err_val = af_set_axes_limits_compute(self.handle as WndHandle, + xrange.get() as AfArray, + yrange.get() as AfArray, + match zrange { + Some(z) => z.get() as AfArray, + None => 0, + }, exact as c_int, + cprops as *const Cell as CellPtr); + HANDLE_ERROR(AfError::from(err_val)); + } + } + + /// Set 2d chart axes limits + /// + /// In multiple view (grid) mode, setting limits will effect the chart that is currently + /// active via set_view call + /// + /// # Parameters + /// + /// - `xmin` is minimum value on x axis + /// - `xmax` is maximum value on x axis + /// - `ymin` is minimum value on y axis + /// - `ymax` is maximum value on y axis + /// - `exact` indicates if the exact min/max values from `xrange`, `yrange` and `zrange` + /// are to extracted. If exact is false then the most significant digit is rounded up + /// to next power of 2 and the magnitude remains the same. + pub fn set_axes_limits_2d(&mut self, xmin: f32, xmax: f32, ymin: f32, ymax: f32, exact: bool) { + let cprops = &Cell {row: self.row, col: self.col, title: String::from(""), cmap: self.cmap}; + unsafe { + let err_val = af_set_axes_limits_2d(self.handle as WndHandle, xmin as c_float, + xmax as c_float, ymin as c_float, ymax as c_float, + exact as c_int, cprops as *const Cell as CellPtr); + HANDLE_ERROR(AfError::from(err_val)); + } + } + + /// Set 3d chart axes limits + /// + /// In multiple view (grid) mode, setting limits will effect the chart that is currently + /// active via set_view call + /// + /// # Parameters + /// + /// - `xmin` is minimum value on x axis + /// - `xmax` is maximum value on x axis + /// - `ymin` is minimum value on y axis + /// - `ymax` is maximum value on y axis + /// - `zmin` is minimum value on z axis + /// - `zmax` is maximum value on z axis + /// - `exact` indicates if the exact min/max values from `xrange`, `yrange` and `zrange` + /// are to extracted. If exact is false then the most significant digit is rounded up + /// to next power of 2 and the magnitude remains the same. + pub fn set_axes_limits_3d(&mut self, xmin: f32, xmax: f32, ymin: f32, ymax: f32, + zmin: f32, zmax: f32, exact: bool) { + let cprops = &Cell {row: self.row, col: self.col, title: String::from(""), cmap: self.cmap}; + unsafe { + let err_val = af_set_axes_limits_3d(self.handle as WndHandle, xmin as c_float, + xmax as c_float, ymin as c_float, ymax as c_float, + zmin as c_float, zmax as c_float, + exact as c_int, cprops as *const Cell as CellPtr); + HANDLE_ERROR(AfError::from(err_val)); + } + } + /// Render given Array as an image pub fn draw_image(&self, input: &Array, title: Option) { let tstr = match title { @@ -231,31 +365,45 @@ impl Window { } /// Render given two Array's `x` and `y` as a 2d line plot - pub fn draw_plot(&self, x: &Array, y: &Array, title: Option) { + pub fn draw_plot2(&self, x: &Array, y: &Array, 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_plot(self.handle as WndHandle, - x.get() as AfArray, - y.get() as AfArray, - cprops as *const Cell as CellPtr); + let err_val = af_draw_plot_2d(self.handle as WndHandle, + x.get() as AfArray, y.get() as AfArray, + cprops as *const Cell as CellPtr); + HANDLE_ERROR(AfError::from(err_val)); + } + } + + /// Render given Array's `x`, `y` and `z` as a 3d line plot + pub fn draw_plot3(&self, x: &Array, y: &Array, z: &Array, 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_plot_3d(self.handle as WndHandle, + x.get() as AfArray, y.get() as AfArray, z.get() as AfArray, + cprops as *const Cell as CellPtr); HANDLE_ERROR(AfError::from(err_val)); } } /// Render give Arrays of points as a 3d line plot - pub fn draw_plot3(&self, points: &Array, title: Option) { + pub fn draw_plot(&self, points: &Array, 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_plot3(self.handle as WndHandle, points.get() as AfArray, - cprops as *const Cell as CellPtr); + let err_val = af_draw_plot_nd(self.handle as WndHandle, points.get() as AfArray, + cprops as *const Cell as CellPtr); HANDLE_ERROR(AfError::from(err_val)); } } @@ -292,36 +440,100 @@ impl Window { } } - /// Render give Arrays as 2d scatter plot - pub fn draw_scatter(&self, xvals: &Array, yvals: &Array, marker: MarkerType, title: Option) { + /// Render given Arrays as 2d scatter plot + pub fn draw_scatter2(&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); + let err_val = af_draw_scatter_2d(self.handle as WndHandle, + xvals.get() as AfArray, yvals.get() as AfArray, + marker as c_int, cprops as *const Cell as CellPtr); + HANDLE_ERROR(AfError::from(err_val)); + } + } + + /// Render given Arrays as 3d scatter plot + pub fn draw_scatter3(&self, xvals: &Array, yvals: &Array, zvals: &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_3d(self.handle as WndHandle, xvals.get() as AfArray, + yvals.get() as AfArray, zvals.get() as AfArray, + marker as c_int, cprops as *const Cell as CellPtr); HANDLE_ERROR(AfError::from(err_val)); } } /// Render give Array as 3d scatter plot - pub fn draw_scatter3(&self, vals: &Array, marker: MarkerType, title: Option) { + pub fn draw_scatter(&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_scatter_nd(self.handle as WndHandle, vals.get() as AfArray, + marker as c_int, cprops as *const Cell as CellPtr); + HANDLE_ERROR(AfError::from(err_val)); + } + } + + /// Render given Arrays as 2d vector field + pub fn draw_vector_field2(&self, xpnts: &Array, ypnts: &Array, + xdirs: &Array, ydirs: &Array, 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); + let err_val = af_draw_vector_field_2d(self.handle as WndHandle, + xpnts.get() as AfArray, ypnts.get() as AfArray, + xdirs.get() as AfArray, ydirs.get() as AfArray, + cprops as *const Cell as CellPtr); HANDLE_ERROR(AfError::from(err_val)); } } -} \ No newline at end of file + + /// Render given Arrays as 3d vector field + pub fn draw_vector_field3(&self, xpnts: &Array, ypnts: &Array, zpnts: &Array, + xdirs: &Array, ydirs: &Array, zdirs: &Array, + 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_vector_field_3d(self.handle as WndHandle, xpnts.get() as AfArray, + ypnts.get() as AfArray, zpnts.get() as AfArray, + xdirs.get() as AfArray, ydirs.get() as AfArray, + zdirs.get() as AfArray, + cprops as *const Cell as CellPtr); + HANDLE_ERROR(AfError::from(err_val)); + } + } + + /// Render given Array as vector field + pub fn draw_vector_field(&self, points: &Array, directions: &Array, 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_vector_field_nd(self.handle as WndHandle, + points.get() as AfArray, directions.get() as AfArray, + cprops as *const Cell as CellPtr); + HANDLE_ERROR(AfError::from(err_val)); + } + } +} From 37c5091e8094bffc11c2382201f18b213c2ac5b0 Mon Sep 17 00:00:00 2001 From: pradeep Date: Mon, 12 Sep 2016 18:04:32 +0530 Subject: [PATCH 18/36] FEATURE: one dimensional median filter for images --- src/image/mod.rs | 23 +++++++++++++++++++++++ src/lib.rs | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/image/mod.rs b/src/image/mod.rs index 7b5bdb3cb..0e8538917 100644 --- a/src/image/mod.rs +++ b/src/image/mod.rs @@ -65,6 +65,8 @@ extern { fn af_medfilt(out: MutAfArray, input: AfArray, wlen: DimT, wwid: DimT, etype: uint8_t) -> c_int; + fn af_medfilt1(out: MutAfArray, input: AfArray, wlen: DimT, etype: uint8_t) -> c_int; + fn af_minfilt(out: MutAfArray, input: AfArray, wlen: DimT, wwid: DimT, etype: uint8_t) -> c_int; @@ -1183,3 +1185,24 @@ pub fn moments_all(input: &Array, moment: MomentType) -> f64 { temp } } + +/// One dimensional median filter on image +/// +/// # Parameters +/// +/// - `input` is the input image(Array) +/// - `wlen` is the horizontal length of the filter +/// - `etype` is enum of type [BorderType](./enum.BorderType.html) +/// +/// # Return Values +/// +/// An Array with filtered image data. +pub fn medfilt1(input: &Array, wlen: u64, etype: BorderType) -> Array { + unsafe { + let mut temp: i64 = 0; + let err_val = af_medfilt1(&mut temp as MutAfArray, input.get() as AfArray, + wlen as DimT, etype as uint8_t); + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) + } +} diff --git a/src/lib.rs b/src/lib.rs index 9a09e403d..c1a068a22 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -72,7 +72,7 @@ pub use image::{resize, transform, rotate, translate, scale, skew}; pub use image::{dilate, dilate3, erode, erode3, minfilt, maxfilt}; pub use image::{gradient, histogram, hist_equal, regions}; pub use image::{gray2rgb, rgb2gray, hsv2rgb, rgb2hsv, color_space}; -pub use image::{bilateral, mean_shift, medfilt, sobel}; +pub use image::{bilateral, mean_shift, medfilt, sobel, medfilt1}; pub use image::{unwrap, wrap, sat, rgb2ycbcr, ycbcr2rgb, is_imageio_available, transform_coords}; pub use image::{moments, moments_all}; mod image; From c95175803d5beaba33c981b20bd9fcdefb1b9e12 Mon Sep 17 00:00:00 2001 From: pradeep Date: Tue, 13 Sep 2016 09:13:32 +0530 Subject: [PATCH 19/36] update ArrayFire upstream to v3.4.0 tag --- arrayfire | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arrayfire b/arrayfire index 2f474a804..10d9716a4 160000 --- a/arrayfire +++ b/arrayfire @@ -1 +1 @@ -Subproject commit 2f474a804a381915770981f518493204bb53d3c1 +Subproject commit 10d9716a4aca5bc413d642be6295ce08614d5c36 From 8a9a467b32b7a150c4484f99522f47903c4c2bad Mon Sep 17 00:00:00 2001 From: pradeep Date: Tue, 13 Sep 2016 11:06:13 +0530 Subject: [PATCH 20/36] fix unused function warning in build script --- build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.rs b/build.rs index 3a4df9cca..1230ba6b8 100644 --- a/build.rs +++ b/build.rs @@ -6,7 +6,7 @@ use std::env; use std::fs; use rustc_serialize::json; use std::fs::OpenOptions; -use std::io::{ErrorKind, Read, Write}; +use std::io::{ErrorKind, Read}; use std::path::PathBuf; use std::process::Command; use std::convert::AsRef; From 38a4393125671a7f7e4bba44bc570459926bf98d Mon Sep 17 00:00:00 2001 From: pradeep Date: Tue, 13 Sep 2016 11:40:36 +0530 Subject: [PATCH 21/36] array memory lock, unlock and get device pointer fns --- src/array.rs | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/src/array.rs b/src/array.rs index 29a3494bc..922d674d0 100644 --- a/src/array.rs +++ b/src/array.rs @@ -11,12 +11,13 @@ type MutDouble = *mut self::libc::c_double; type MutUint = *mut self::libc::c_uint; type AfArray = self::libc::c_longlong; type DimT = self::libc::c_longlong; +type MutVoidPtr = *mut self::libc::c_ulonglong; +type VoidPtr = self::libc::c_ulonglong; // Some unused functions from array.h in C-API of ArrayFire // af_create_handle // af_copy_array // af_write_array -// af_get_data_ptr // af_get_data_ref_count #[allow(dead_code)] @@ -95,6 +96,12 @@ extern { fn af_is_linear(result: *mut c_int, arr: AfArray) -> c_int; fn af_is_owner(result: *mut c_int, arr: AfArray) -> c_int; + + fn af_lock_array(arr: AfArray) -> c_int; + + fn af_unlock_array(arr: AfArray) -> c_int; + + fn af_get_device_ptr(ptr: MutVoidPtr, arr: AfArray) -> c_int; } /// A multidimensional data container @@ -327,6 +334,39 @@ impl Array { Array::from(temp) } } + + /// Lock the device buffer in the memory manager + /// + /// Locked buffers are not freed by memory manager until unlock is called. + pub fn lock(&self) { + unsafe { + let err_val = af_lock_array(self.handle as AfArray); + HANDLE_ERROR(AfError::from(err_val)); + } + } + + /// Unlock the device buffer in the memory manager + /// + /// This function will give back the control over the device pointer to the + /// memory manager. + pub fn unlock(&self) { + unsafe { + let err_val = af_unlock_array(self.handle as AfArray); + HANDLE_ERROR(AfError::from(err_val)); + } + } + + /// Get the device pointer and lock the buffer in memory manager + /// + /// The device pointer is not freed by memory manager until unlock is called. + pub fn device_ptr(&self) -> u64 { + unsafe { + let mut temp: u64 = 0; + let err_val = af_get_device_ptr(&mut temp as MutVoidPtr, self.handle as AfArray); + HANDLE_ERROR(AfError::from(err_val)); + temp + } + } } /// Used for creating Array object from native resource id From 34c81b7624805606c0d9cb09f9c162b7e5783e6e Mon Sep 17 00:00:00 2001 From: pradeep Date: Tue, 13 Sep 2016 18:24:01 +0530 Subject: [PATCH 22/36] FEATURE: sparse module with sparse array functions --- src/array.rs | 12 ++ src/defines.rs | 14 +++ src/lib.rs | 7 +- src/sparse/mod.rs | 288 ++++++++++++++++++++++++++++++++++++++++++++++ src/util.rs | 8 ++ 5 files changed, 328 insertions(+), 1 deletion(-) create mode 100644 src/sparse/mod.rs diff --git a/src/array.rs b/src/array.rs index 922d674d0..7c16e18d2 100644 --- a/src/array.rs +++ b/src/array.rs @@ -97,6 +97,8 @@ extern { fn af_is_owner(result: *mut c_int, arr: AfArray) -> c_int; + fn af_is_sparse(result: *mut c_int, arr: AfArray) -> c_int; + fn af_lock_array(arr: AfArray) -> c_int; fn af_unlock_array(arr: AfArray) -> c_int; @@ -335,6 +337,16 @@ impl Array { } } + /// Find if the current array is sparse + pub fn is_sparse(&self) -> bool { + unsafe { + let mut temp: i32 = 0; + let err_val = af_is_sparse(&mut temp as *mut c_int, self.handle as AfArray); + HANDLE_ERROR(AfError::from(err_val)); + temp > 0 + } + } + /// Lock the device buffer in the memory manager /// /// Locked buffers are not freed by memory manager until unlock is called. diff --git a/src/defines.rs b/src/defines.rs index e75ebaa2a..dd9393872 100644 --- a/src/defines.rs +++ b/src/defines.rs @@ -344,3 +344,17 @@ pub enum MomentType { M11 = 8, // 1<<3 FIRST_ORDER = 1<<0 | 1<<1 | 1<<2 | 1<<3 } + +/// Sparse storage format type +#[repr(C)] +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum SparseFormat { + /// Dense format + DENSE = 0, + /// Compressed sparse row format + CSR = 1, + /// Compressed sparse coloumn format + CSC = 2, + /// Coordinate list (row, coloumn, value) tuples. + COO = 3 +} diff --git a/src/lib.rs b/src/lib.rs index c1a068a22..de2fab657 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -47,7 +47,7 @@ mod device; 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, MomentType}; +pub use defines::{MarkerType, MomentType, SparseFormat}; mod defines; pub use dim4::Dim4; @@ -93,6 +93,11 @@ pub use signal::{fft_convolve1, fft_convolve2, fft_convolve3}; pub use signal::{fir, iir}; mod signal; +pub use sparse::{sparse, sparse_from_host, sparse_from_dense, sparse_convert_to}; +pub use sparse::{sparse_to_dense, sparse_get_info, sparse_get_values, sparse_get_nnz}; +pub use sparse::{sparse_get_row_indices, sparse_get_col_indices, sparse_get_format}; +mod sparse; + pub use statistics::{mean, stdev, median, var, cov, corrcoef}; pub use statistics::{mean_weighted, var_weighted}; pub use statistics::{var_all, mean_all, stdev_all, median_all}; diff --git a/src/sparse/mod.rs b/src/sparse/mod.rs new file mode 100644 index 000000000..1950edcb8 --- /dev/null +++ b/src/sparse/mod.rs @@ -0,0 +1,288 @@ +extern crate libc; + +use array::Array; +use defines::{AfError, SparseFormat}; +use error::HANDLE_ERROR; +use self::libc::{uint8_t, c_void, c_int}; +use util::HasAfEnum; + +type MutAfArray = *mut self::libc::c_longlong; +type AfArray = self::libc::c_longlong; +type DimT = self::libc::c_longlong; +type MutDimT = *mut self::libc::c_longlong; + +#[allow(dead_code)] +extern { + fn af_create_sparse_array(out: MutAfArray, nRows: DimT, nCols: DimT, vals: AfArray, + rowIdx: AfArray, colIdx: AfArray, stype: uint8_t) -> c_int; + + fn af_create_sparse_array_from_ptr(out: MutAfArray, nRows: DimT, nCols: DimT, nNZ: DimT, + values: *const c_void, rowIdx: *const c_int, colIdx: *const c_int, + aftype: uint8_t, stype: uint8_t, src: uint8_t) -> c_int; + + fn af_create_sparse_array_from_dense(out: MutAfArray, dense: AfArray, stype: uint8_t) -> c_int; + + fn af_sparse_convert_to(out: MutAfArray, input: AfArray, dstStrge: uint8_t) -> c_int; + + fn af_sparse_to_dense(out: MutAfArray, sparse: AfArray) -> c_int; + + fn af_sparse_get_info(vals: MutAfArray, rIdx: MutAfArray, cIdx: MutAfArray, stype: *mut uint8_t, + input: AfArray) -> c_int; + + fn af_sparse_get_values(out: MutAfArray, input: AfArray) -> c_int; + + fn af_sparse_get_row_idx(out: MutAfArray, input: AfArray) -> c_int; + + fn af_sparse_get_col_idx(out: MutAfArray, input: AfArray) -> c_int; + + fn af_sparse_get_nnz(out: MutDimT, input: AfArray) -> c_int; + + fn af_sparse_get_storage(out: *mut uint8_t, input: AfArray) -> c_int; +} + +/// Create sprase matrix from arrays +/// +/// This function converts [Array](./struct.Array.html) of `values` into sparse array +/// of `format` sparse format using arrays `row_indices` and `col_indices`. +/// +/// # Parameters +/// +/// - `rows` is the number of rows in the dense matrix +/// - `cols` is the number of columns in the dense matrix +/// - `values` is the \ref af::array containing the non-zero elements +/// `of the matrix +/// - `row_indices` is the row indices for the sparse array +/// - `col_indices` is the column indices for the sparse array +/// - `format` is the storage format of the sparse array +/// +/// # Return Values +/// +/// Array with data in given sparse format +/// +/// # Note +/// +/// This function only uses references of the input arrays to create the +/// sparse data structure and does not perform deep copies. +pub fn sparse(rows: u64, cols: u64, values: &Array, row_indices: &Array, col_indices: &Array, + format: SparseFormat) -> Array { + unsafe { + let mut temp: i64 = 0; + let err_val = af_create_sparse_array(&mut temp as MutAfArray, rows as DimT, cols as DimT, + values.get() as AfArray, row_indices.get() as AfArray, + col_indices.get() as AfArray, format as uint8_t); + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) + } +} + +/// Create sprase matrix from data on host memory +/// +/// This function converts host array `values` into sparse array of `format` sparse +/// format using host arrays `row_indices` and `col_indices`. +/// +/// # Parameters +/// +/// - `rows` is the number of rows in the dense matrix +/// - `cols` is the number of columns in the dense matrix +/// - `nzz` is the number of non zero elements in the dense matrix +/// - `values` is the \ref af::array containing the non-zero elements +/// `of the matrix +/// - `row_indices` is the row indices for the sparse array +/// - `col_indices` is the column indices for the sparse array +/// - `format` is the storage format of the sparse array +/// +/// # Return Values +/// +/// Array with data in given sparse format +/// +/// # Note +/// +/// The rules for deep copy/shallow copy/reference are the same as for creating a +/// regular [Array](./struct.Array.html). +pub fn sparse_from_host(rows: u64, cols: u64, nzz: u64, + values: &[T], row_indices: &[i32], col_indices: &[i32], + format: SparseFormat) -> Array { + unsafe { + let aftype = T::get_af_dtype(); + let mut temp: i64 = 0; + let err_val = af_create_sparse_array_from_ptr(&mut temp as MutAfArray, + rows as DimT, cols as DimT, nzz as DimT, + values.as_ptr() as *const c_void, + row_indices.as_ptr() as *const c_int, + col_indices.as_ptr() as *const c_int, + aftype as uint8_t, format as uint8_t, 1); + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) + } +} + +/// Convert dense array to sparse array +/// +/// # Parameters +/// +/// - `dense` is the dense format array +/// - `format` is the target sparse format +/// +/// # Return Values +/// +/// Sparse Array +pub fn sparse_from_dense(dense: &Array, format: SparseFormat) -> Array { + unsafe { + let mut temp : i64 = 0; + let err_val = af_create_sparse_array_from_dense(&mut temp as MutAfArray, dense.get() as AfArray, + format as uint8_t); + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) + } +} + +/// Convert between sparse formats +/// +/// # Parameters +/// +/// - `input` is the input sparse array +/// - `format` is the target sparse format +/// +/// # Return Values +/// +/// Sparse Array in targe sparse format. +pub fn sparse_convert_to(input: &Array, format: SparseFormat) -> Array { + unsafe { + let mut temp : i64 = 0; + let err_val = af_sparse_convert_to(&mut temp as MutAfArray, input.get() as AfArray, + format as uint8_t); + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) + } +} + +/// Convert sparse array to dense array +/// +/// # Parameters +/// +/// - `input` is the sparse array +/// +/// # Return Values +/// +/// Dense Array +pub fn sparse_to_dense(input: &Array) -> Array { + unsafe { + let mut temp : i64 = 0; + let err_val = af_sparse_to_dense(&mut temp as MutAfArray, input.get() as AfArray); + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) + } +} + +/// Get sparse Array information +/// +/// # Parameters +/// +/// - `input` is the sparse array +/// +/// # Return Values +/// +/// A tuple of values, row indices, coloumn indices Arrays and SparseFormat enum. +pub fn sparse_get_info(input: &Array) -> (Array, Array, Array, SparseFormat) { + unsafe { + let mut val : i64 = 0; + let mut row : i64 = 0; + let mut col : i64 = 0; + let mut stype : u8 = 0; + let err_val = af_sparse_get_info(&mut val as MutAfArray, &mut row as MutAfArray, + &mut col as MutAfArray, &mut stype as *mut uint8_t, + input.get() as AfArray); + HANDLE_ERROR(AfError::from(err_val)); + (Array::from(val), Array::from(row), Array::from(col), SparseFormat::from(stype as i32)) + } +} + +/// Get values of sparse Array +/// +/// # Parameters +/// +/// - `input` is the sparse array +/// +/// # Return Values +/// +/// Sparse array values +pub fn sparse_get_values(input: &Array) -> Array { + unsafe { + let mut val : i64 = 0; + let err_val = af_sparse_get_values(&mut val as MutAfArray, input.get() as AfArray); + HANDLE_ERROR(AfError::from(err_val)); + Array::from(val) + } +} + +/// Get row indices Array +/// +/// # Parameters +/// +/// - `input` is the sparse array +/// +/// # Return Values +/// +/// Array with row indices values of sparse Array +pub fn sparse_get_row_indices(input: &Array) -> Array { + unsafe { + let mut val : i64 = 0; + let err_val = af_sparse_get_row_idx(&mut val as MutAfArray, input.get() as AfArray); + HANDLE_ERROR(AfError::from(err_val)); + Array::from(val) + } +} + +/// Get cololumn indices Array +/// +/// # Parameters +/// +/// - `input` is the sparse array +/// +/// # Return Values +/// +/// Array with coloumn indices values of sparse Array +pub fn sparse_get_col_indices(input: &Array) -> Array { + unsafe { + let mut val : i64 = 0; + let err_val = af_sparse_get_col_idx(&mut val as MutAfArray, input.get() as AfArray); + HANDLE_ERROR(AfError::from(err_val)); + Array::from(val) + } +} + +/// Get number of non-zero elements in sparse array +/// +/// # Parameters +/// +/// - `input` is the sparse array +/// +/// # Return Values +/// +/// Number of non-zero elements of sparse Array +pub fn sparse_get_nnz(input: &Array) -> i64 { + unsafe { + let mut count : i64 = 0; + let err_val = af_sparse_get_nnz(&mut count as *mut DimT, input.get() as AfArray); + HANDLE_ERROR(AfError::from(err_val)); + count + } +} + +/// Get sparse format +/// +/// # Parameters +/// +/// - `input` is the sparse array +/// +/// # Return Values +/// +/// Sparse array format +pub fn sparse_get_format(input: &Array) -> SparseFormat { + unsafe { + let mut stype : u8 = 0; + let err_val = af_sparse_get_storage(&mut stype as *mut uint8_t, input.get() as AfArray); + HANDLE_ERROR(AfError::from(err_val)); + SparseFormat::from(stype as i32) + } +} diff --git a/src/util.rs b/src/util.rs index 21d59b3f8..60b34bbeb 100644 --- a/src/util.rs +++ b/src/util.rs @@ -2,6 +2,7 @@ extern crate libc; extern crate num; use defines::{AfError, ColorMap, ConvDomain, ConvMode, DType, InterpType, MatProp, MatchType}; +use defines::{SparseFormat}; use error::HANDLE_ERROR; use std::mem; use self::num::Complex; @@ -135,3 +136,10 @@ 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); + +impl From for SparseFormat { + fn from(t: i32) -> SparseFormat { + assert!(SparseFormat::DENSE as i32 <= t && t <= SparseFormat::COO as i32); + unsafe { mem::transmute(t) } + } +} From 689f3b832bd7dda9598b5ec361ede055c5c030ed Mon Sep 17 00:00:00 2001 From: pradeep Date: Tue, 13 Sep 2016 18:25:20 +0530 Subject: [PATCH 23/36] BUGFIX: fix ffi call arguments for strided array creation --- src/array.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/array.rs b/src/array.rs index 7c16e18d2..58011022c 100644 --- a/src/array.rs +++ b/src/array.rs @@ -86,7 +86,7 @@ extern { 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; + aftype: uint8_t, stype: uint8_t) -> c_int; fn af_get_strides(s0: *mut DimT, s1: *mut DimT, s2: *mut DimT, s3: *mut DimT, arr: AfArray) -> c_int; @@ -168,7 +168,7 @@ impl Array { 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); + aftype as uint8_t, 1); HANDLE_ERROR(AfError::from(err_val)); Array::from(temp) } From bfd5ada20e5c5d176839c2b2d89a3f94e76c3d44 Mon Sep 17 00:00:00 2001 From: pradeep Date: Tue, 13 Sep 2016 18:51:24 +0530 Subject: [PATCH 24/36] Added new interpolation types for transformation functions --- src/defines.rs | 12 ++++++++++++ src/util.rs | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/defines.rs b/src/defines.rs index dd9393872..d6c14db43 100644 --- a/src/defines.rs +++ b/src/defines.rs @@ -147,6 +147,18 @@ pub enum InterpType { BILINEAR= 2, /// Cubic interpolation method CUBIC = 3, + /// Floor indexed + LOWER = 4, + /// Linear interpolation with cosine smoothing + LINEAR_COSINE = 5, + /// Bilinear interpolation with cosine smoothing + BILINEAR_COSINE = 6, + /// Bicubic interpolation + BICUBIC = 7, + /// Cubic interpolation with Catmull-Rom splines + CUBIC_SPLINE = 8, + /// Bicubic interpolation with Catmull-Rom splines + BICUBIC_SPLINE = 9 } /// Helps determine how to pad kernels along borders diff --git a/src/util.rs b/src/util.rs index 60b34bbeb..82b27c076 100644 --- a/src/util.rs +++ b/src/util.rs @@ -39,7 +39,7 @@ impl From for DType { impl From for InterpType { fn from(t: i32) -> InterpType { - assert!(InterpType::NEAREST as i32 <= t && t <= InterpType::CUBIC as i32); + assert!(InterpType::NEAREST as i32 <= t && t <= InterpType::BICUBIC_SPLINE as i32); unsafe { mem::transmute(t) } } } From 8330324635a4d53593eae373bfba9de136dd4b69 Mon Sep 17 00:00:00 2001 From: pradeep Date: Tue, 13 Sep 2016 19:10:30 +0530 Subject: [PATCH 25/36] FEATURE: generalized scan functions * scan * scan_by_key --- src/algorithm/mod.rs | 56 ++++++++++++++++++++++++++++++++++++++++++-- src/defines.rs | 10 ++++++++ src/lib.rs | 4 ++-- src/util.rs | 9 ++++++- 4 files changed, 74 insertions(+), 5 deletions(-) diff --git a/src/algorithm/mod.rs b/src/algorithm/mod.rs index 8b90b285f..acedfb3b4 100644 --- a/src/algorithm/mod.rs +++ b/src/algorithm/mod.rs @@ -1,9 +1,9 @@ extern crate libc; use array::Array; -use defines::AfError; +use defines::{AfError, BinaryOp}; use error::HANDLE_ERROR; -use self::libc::{c_int, c_uint, c_double}; +use self::libc::{c_int, uint8_t, c_uint, c_double}; type MutAfArray = *mut self::libc::c_longlong; type MutDouble = *mut self::libc::c_double; @@ -46,6 +46,10 @@ extern { fn af_sort_by_key(out_keys: MutAfArray, out_vals: MutAfArray, in_keys: AfArray, in_vals: AfArray, dim: c_uint, ascend: c_int) -> c_int; + + fn af_scan(out: MutAfArray, inp: AfArray, dim: c_int, op: uint8_t, inclusive: c_int) -> c_int; + fn af_scan_by_key(out: MutAfArray, key: AfArray, inp: AfArray, + dim: c_int, op: uint8_t, inclusive: c_int) -> c_int; } macro_rules! dim_reduce_func_def { @@ -855,3 +859,51 @@ pub fn set_intersect(first: &Array, second: &Array, is_unique: bool) -> Array { Array::from(temp) } } + +/// Generalized scan +/// +/// # Parameters +/// +/// - `input` is the data on which scan is to be performed +/// - `dim` is the dimension along which scan operation is to be performed +/// - `op` takes value of [BinaryOp](./enum.BinaryOp.html) enum indicating +/// the type of scan operation +/// - `inclusive` says if inclusive/exclusive scan is to be performed +/// +/// # Return Values +/// +/// Output Array of scanned input +pub fn scan(input: &Array, dim: i32, op: BinaryOp, inclusive: bool) -> Array { + unsafe { + let mut temp : i64 = 0; + let err_val = af_scan(&mut temp as MutAfArray, input.get() as AfArray, dim as c_int, + op as uint8_t, inclusive as c_int); + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) + } +} + +/// Generalized scan by key +/// +/// # Parameters +/// +/// - `key` is the key Array +/// - `input` is the data on which scan is to be performed +/// - `dim` is the dimension along which scan operation is to be performed +/// - `op` takes value of [BinaryOp](./enum.BinaryOp.html) enum indicating +/// the type of scan operation +/// - `inclusive` says if inclusive/exclusive scan is to be performed +/// +/// # Return Values +/// +/// Output Array of scanned input +pub fn scan_by_key(key: &Array, input: &Array, dim: i32, op: BinaryOp, inclusive: bool) -> Array { + unsafe { + let mut temp : i64 = 0; + let err_val = af_scan_by_key(&mut temp as MutAfArray, + key.get() as AfArray, input.get() as AfArray, dim as c_int, + op as uint8_t, inclusive as c_int); + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) + } +} diff --git a/src/defines.rs b/src/defines.rs index d6c14db43..105e78d3e 100644 --- a/src/defines.rs +++ b/src/defines.rs @@ -370,3 +370,13 @@ pub enum SparseFormat { /// Coordinate list (row, coloumn, value) tuples. COO = 3 } + +/// Binary operation types for generalized scan functions +#[repr(C)] +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum BinaryOp { + ADD = 0, + MUL = 1, + MIN = 2, + MAX = 3 +} diff --git a/src/lib.rs b/src/lib.rs index de2fab657..9e347162e 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,7 +14,7 @@ pub use algorithm::{sum, product, min, max, all_true, any_true, count, sum_nan, pub use algorithm::{sum_all, product_all, min_all, max_all, sum_nan_all, product_nan_all}; pub use algorithm::{all_true_all, any_true_all, count_all, imin, imax, imin_all, imax_all}; pub use algorithm::{accum, locate, diff1, diff2, sort, sort_index, sort_by_key}; -pub use algorithm::{set_unique, set_union, set_intersect}; +pub use algorithm::{set_unique, set_union, set_intersect, scan, scan_by_key}; mod algorithm; pub use arith::{add, sub, div, mul, lt, gt, le, ge, eq, neq, and, or, minof, maxof, rem}; @@ -47,7 +47,7 @@ mod device; 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, MomentType, SparseFormat}; +pub use defines::{MarkerType, MomentType, SparseFormat, BinaryOp}; mod defines; pub use dim4::Dim4; diff --git a/src/util.rs b/src/util.rs index 82b27c076..2942043ca 100644 --- a/src/util.rs +++ b/src/util.rs @@ -2,7 +2,7 @@ extern crate libc; extern crate num; use defines::{AfError, ColorMap, ConvDomain, ConvMode, DType, InterpType, MatProp, MatchType}; -use defines::{SparseFormat}; +use defines::{SparseFormat, BinaryOp}; use error::HANDLE_ERROR; use std::mem; use self::num::Complex; @@ -143,3 +143,10 @@ impl From for SparseFormat { unsafe { mem::transmute(t) } } } + +impl From for BinaryOp { + fn from(t: i32) -> BinaryOp { + assert!(BinaryOp::ADD as i32 <= t && t <= BinaryOp::MAX as i32); + unsafe { mem::transmute(t) } + } +} From 279d463eec9be88a98aaf89c1bdb39c0d193d068 Mon Sep 17 00:00:00 2001 From: pradeep Date: Tue, 13 Sep 2016 23:14:16 +0530 Subject: [PATCH 26/36] FEATURE: random number generation functions * Moved old rand* functions to random module * New object `RandomEngine` is added * Additional random number generation functions that use RandomEngine object are added. --- src/data/mod.rs | 65 +++--------- src/defines.rs | 17 +++ src/lib.rs | 9 +- src/random/mod.rs | 260 ++++++++++++++++++++++++++++++++++++++++++++++ src/util.rs | 9 +- 5 files changed, 308 insertions(+), 52 deletions(-) create mode 100644 src/random/mod.rs diff --git a/src/data/mod.rs b/src/data/mod.rs index 7edad1665..511237d71 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -38,12 +38,6 @@ extern { fn af_iota(out: MutAfArray, ndims: c_uint, dims: *const DimT, t_ndims: c_uint, tdims: *const DimT, afdtype: uint8_t) -> c_int; - fn af_randu(out: MutAfArray, ndims: c_uint, dims: *const DimT, afdtype: uint8_t) -> c_int; - fn af_randn(out: MutAfArray, ndims: c_uint, dims: *const DimT, afdtype: uint8_t) -> c_int; - - fn af_set_seed(seed: Uintl) -> c_int; - fn af_get_seed(seed: *mut Uintl) -> c_int; - fn af_identity(out: MutAfArray, ndims: c_uint, dims: *const DimT, afdtype: uint8_t) -> c_int; fn af_diag_create(out: MutAfArray, arr: AfArray, num: c_int) -> c_int; fn af_diag_extract(out: MutAfArray, arr: AfArray, num: c_int) -> c_int; @@ -250,55 +244,28 @@ pub fn iota(dims: Dim4, tdims: Dim4) -> Array { } } -/// Set seed for random number generation -pub fn set_seed(seed: u64) { - unsafe { - let err_val = af_set_seed(seed as Uintl); - HANDLE_ERROR(AfError::from(err_val)); - } -} - -/// Get the seed of random number generator +/// Create an identity array with 1's in diagonal +/// +/// # Parameters +/// +/// - `dims` is the output Array dimensions +/// +/// # Return Values +/// +/// Identity matrix #[allow(unused_mut)] -pub fn get_seed() -> u64 { +pub fn identity(dims: Dim4) -> Array { unsafe { - let mut temp: u64 = 0; - let err_val = af_get_seed(&mut temp as *mut Uintl); + let aftype = T::get_af_dtype(); + let mut temp: i64 = 0; + let err_val = af_identity(&mut temp as MutAfArray, + dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT, + aftype as uint8_t); HANDLE_ERROR(AfError::from(err_val)); - temp + Array::from(temp) } } -macro_rules! data_gen_def { - ($doc_str: expr, $fn_name:ident, $ffi_name: ident) => ( - #[doc=$doc_str] - /// - ///# Parameters - /// - /// - `dims` is the output dimensions - /// - ///# Return Values - /// - /// An Array with modified data. - #[allow(unused_mut)] - 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); - HANDLE_ERROR(AfError::from(err_val)); - Array::from(temp) - } - } - ) -} - -data_gen_def!("Create random numbers from uniform distribution", randu, af_randu); -data_gen_def!("Create random numbers from normal distribution", randn, af_randn); -data_gen_def!("Create an identity array with 1's in diagonal", identity, af_identity); - /// Create a diagonal matrix /// /// # Parameters diff --git a/src/defines.rs b/src/defines.rs index 105e78d3e..e74337d3b 100644 --- a/src/defines.rs +++ b/src/defines.rs @@ -380,3 +380,20 @@ pub enum BinaryOp { MIN = 2, MAX = 3 } + +/// Random engine types +#[repr(C)] +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum RandomEngineType { + ///Philox variant with N=4, W=32 and Rounds=10 + PHILOX_4X32_10 = 100, + ///Threefry variant with N=2, W=32 and Rounds=16 + THREEFRY_2X32_16 = 200, + ///Mersenne variant with MEXP = 11213 + MERSENNE_GP11213 = 300 +} + +pub const PHILOX : RandomEngineType = RandomEngineType::PHILOX_4X32_10; +pub const THREEFRY : RandomEngineType = RandomEngineType::THREEFRY_2X32_16; +pub const MERSENNE : RandomEngineType = RandomEngineType::MERSENNE_GP11213; +pub const DEFAULT_RANDOM_ENGINE : RandomEngineType = PHILOX; diff --git a/src/lib.rs b/src/lib.rs index 9e347162e..3badbe3e8 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,7 +33,6 @@ pub use blas::{matmul, dot, transpose, transpose_inplace}; mod blas; pub use data::{constant, range, iota}; -pub use data::{set_seed, get_seed, randu, randn}; pub use data::{identity, diag_create, diag_extract, lower, upper}; pub use data::{join, join_many, tile}; pub use data::{reorder, shift, moddims, flat, flip}; @@ -47,7 +46,8 @@ mod device; 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, MomentType, SparseFormat, BinaryOp}; +pub use defines::{MarkerType, MomentType, SparseFormat, BinaryOp, RandomEngineType}; +pub use defines::{PHILOX, THREEFRY, MERSENNE, DEFAULT_RANDOM_ENGINE}; mod defines; pub use dim4::Dim4; @@ -83,6 +83,11 @@ mod lapack; mod macros; mod num; +pub use random::RandomEngine; +pub use random::{set_seed, get_seed, randu, randn, random_uniform, random_normal}; +pub use random::{get_default_random_engine, set_default_random_engine_type}; +mod random; + pub use signal::{approx1, approx2, set_fft_plan_cache_size}; pub use signal::{fft, fft2, fft3, ifft, ifft2, ifft3}; pub use signal::{fft_r2c, fft2_r2c, fft3_r2c, fft_c2r, fft2_c2r, fft3_c2r}; diff --git a/src/random/mod.rs b/src/random/mod.rs new file mode 100644 index 000000000..b3a624e80 --- /dev/null +++ b/src/random/mod.rs @@ -0,0 +1,260 @@ +extern crate libc; + +use array::Array; +use dim4::Dim4; +use defines::{AfError, RandomEngineType}; +use error::HANDLE_ERROR; +use self::libc::{uint8_t, c_int, c_uint, c_ulong}; +use util::HasAfEnum; + +type MutAfArray = *mut self::libc::c_longlong; +type AfArray = self::libc::c_longlong; +type MutRandEngine = *mut self::libc::c_longlong; +type RandEngine = self::libc::c_longlong; +type DimT = self::libc::c_longlong; +type Intl = self::libc::c_longlong; +type Uintl = self::libc::c_ulonglong; + +#[allow(dead_code)] +extern { + fn af_set_seed(seed: Uintl) -> c_int; + fn af_get_seed(seed: *mut Uintl) -> c_int; + + fn af_randu(out: MutAfArray, ndims: c_uint, dims: *const DimT, afdtype: uint8_t) -> c_int; + fn af_randn(out: MutAfArray, ndims: c_uint, dims: *const DimT, afdtype: uint8_t) -> c_int; + + fn af_create_random_engine(engine: MutRandEngine, rtype: uint8_t, seed: Uintl) -> c_int; + fn af_retain_random_engine(engine: MutRandEngine, inputEngine: RandEngine) -> c_int; + fn af_random_engine_set_type(engine: MutRandEngine, rtpye: uint8_t) -> c_int; + fn af_random_engine_get_type(rtype: *mut uint8_t, engine: RandEngine) -> c_int; + fn af_random_engine_set_seed(engine: MutRandEngine, seed: Uintl) -> c_int; + fn af_random_engine_get_seed(seed: *mut Uintl, engine: RandEngine) -> c_int; + fn af_release_random_engine(engine: RandEngine) -> c_int; + + fn af_get_default_random_engine(engine: MutRandEngine) -> c_int; + fn af_set_default_random_engine_type(rtype: uint8_t) -> c_int; + + fn af_random_uniform(out: MutAfArray, ndims: c_uint, dims: *const DimT, + aftype: uint8_t, engine: RandEngine) -> c_int; + fn af_random_normal(out: MutAfArray, ndims: c_uint, dims: *const DimT, + aftype: uint8_t, engine: RandEngine) -> c_int; +} + +/// Set seed for random number generation +pub fn set_seed(seed: u64) { + unsafe { + let err_val = af_set_seed(seed as Uintl); + HANDLE_ERROR(AfError::from(err_val)); + } +} + +/// Get the seed of random number generator +#[allow(unused_mut)] +pub fn get_seed() -> u64 { + unsafe { + let mut temp: u64 = 0; + let err_val = af_get_seed(&mut temp as *mut Uintl); + HANDLE_ERROR(AfError::from(err_val)); + temp + } +} + +macro_rules! data_gen_def { + ($doc_str: expr, $fn_name:ident, $ffi_name: ident) => ( + #[doc=$doc_str] + /// + ///# Parameters + /// + /// - `dims` is the output dimensions + /// + ///# Return Values + /// + /// An Array with random values. + #[allow(unused_mut)] + 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); + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) + } + } + ) +} + +data_gen_def!("Create random numbers from uniform distribution", randu, af_randu); +data_gen_def!("Create random numbers from normal distribution", randn, af_randn); + +/// Random number generator engine +/// +/// This is a wrapper for ArrayFire's native random number generator engine. +pub struct RandomEngine { + handle: i64, +} + +/// Used for creating RandomEngine object from native resource id +impl From for RandomEngine { + fn from(t: i64) -> RandomEngine { + RandomEngine {handle: t} + } +} + +impl RandomEngine { + /// Create a new random engine object + /// + /// # Parameters + /// + /// - `rengine` can be value of [RandomEngineType](./enum.RandomEngineType.html) enum. + /// - `seed` is the initial seed value + /// + /// # Return Values + /// + /// A object of type RandomEngine + pub fn new(rengine: RandomEngineType, seed: Option) -> RandomEngine { + unsafe { + let mut temp: i64 = 0; + let err_val = af_create_random_engine(&mut temp as MutRandEngine, rengine as uint8_t, + match seed {Some(s) => s, None => 0} as c_ulong); + HANDLE_ERROR(AfError::from(err_val)); + RandomEngine::from(temp) + } + } + + /// Get random engine type + pub fn get_type(&self) -> RandomEngineType { + unsafe { + let mut temp: u8 = 0; + let err_val = af_random_engine_get_type(&mut temp as *mut uint8_t, + self.handle as RandEngine); + HANDLE_ERROR(AfError::from(err_val)); + RandomEngineType::from(temp as i32) + } + } + + /// Get random engine type + pub fn set_type(&mut self, engine_type: RandomEngineType) { + unsafe { + let err_val = af_random_engine_set_type(&mut self.handle as MutRandEngine, + engine_type as uint8_t); + HANDLE_ERROR(AfError::from(err_val)); + } + } + + /// Set seed for random engine + pub fn set_seed(&mut self, seed: u64) { + unsafe { + let err_val = af_random_engine_set_seed(&mut self.handle as MutRandEngine, + seed as Uintl); + HANDLE_ERROR(AfError::from(err_val)); + } + } + + /// Get seed of the random engine + pub fn get_seed(&self) -> u64 { + unsafe { + let mut seed: u64 = 0; + let err_val = af_random_engine_get_seed(&mut seed as *mut Uintl, self.handle as RandEngine); + HANDLE_ERROR(AfError::from(err_val)); + seed + } + } + + /// Returns the native FFI handle for Rust object `RandomEngine` + pub fn get(&self) -> i64 { + self.handle + } +} + +/// Increment reference count of RandomEngine's native resource +impl Clone for RandomEngine { + fn clone(&self) -> RandomEngine { + unsafe { + let mut temp: i64 = 0; + let err_val = af_retain_random_engine(&mut temp as MutRandEngine, self.handle as RandEngine); + HANDLE_ERROR(AfError::from(err_val)); + RandomEngine::from(temp) + } + } +} + +/// Free RandomEngine's native resource +impl Drop for RandomEngine { + fn drop(&mut self) { + unsafe { + let err_val = af_release_random_engine(self.handle as RandEngine); + HANDLE_ERROR(AfError::from(err_val)); + } + } +} + +/// Get default random engine +pub fn get_default_random_engine() -> RandomEngine { + unsafe { + let mut temp : i64 = 0; + let mut err_val = af_get_default_random_engine(&mut temp as MutRandEngine); + HANDLE_ERROR(AfError::from(err_val)); + let mut handle : i64 = 0; + err_val = af_retain_random_engine(&mut handle as MutRandEngine, temp as RandEngine); + HANDLE_ERROR(AfError::from(err_val)); + RandomEngine::from(handle) + } +} + +/// Set the random engine type for default random number generator +/// +/// # Parameters +/// +/// - `rtype` can take one of the values of enum [RandomEngineType](./enum.RandomEngineType.html) +pub fn set_default_random_engine_type(rtype: RandomEngineType) { + unsafe { + let err_val = af_set_default_random_engine_type(rtype as uint8_t); + HANDLE_ERROR(AfError::from(err_val)); + } +} + +/// Generate array of uniform numbers using a random engine +/// +/// # Parameters +/// +/// - `dims` is output array dimensions +/// - `engine` is an object of type [RandomEngine](./struct.RandomEngine.html) +/// +/// # Return Values +/// +/// An Array with uniform numbers generated using random engine +pub fn random_uniform(dims: Dim4, engine: RandomEngine) -> Array { + unsafe { + let aftype = T::get_af_dtype(); + let mut temp : i64 = 0; + let err_val = af_random_uniform(&mut temp as MutAfArray, + dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT, + aftype as uint8_t, engine.get() as RandEngine); + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) + } +} + +/// Generate array of normal numbers using a random engine +/// +/// # Parameters +/// +/// - `dims` is output array dimensions +/// - `engine` is an object of type [RandomEngine](./struct.RandomEngine.html) +/// +/// # Return Values +/// +/// An Array with normal numbers generated using random engine +pub fn random_normal(dims: Dim4, engine: RandomEngine) -> Array { + unsafe { + let aftype = T::get_af_dtype(); + let mut temp : i64 = 0; + let err_val = af_random_normal(&mut temp as MutAfArray, + dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT, + aftype as uint8_t, engine.get() as RandEngine); + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) + } +} diff --git a/src/util.rs b/src/util.rs index 2942043ca..db8740bb2 100644 --- a/src/util.rs +++ b/src/util.rs @@ -2,7 +2,7 @@ extern crate libc; extern crate num; use defines::{AfError, ColorMap, ConvDomain, ConvMode, DType, InterpType, MatProp, MatchType}; -use defines::{SparseFormat, BinaryOp}; +use defines::{SparseFormat, BinaryOp, RandomEngineType}; use error::HANDLE_ERROR; use std::mem; use self::num::Complex; @@ -150,3 +150,10 @@ impl From for BinaryOp { unsafe { mem::transmute(t) } } } + +impl From for RandomEngineType { + fn from(t: i32) -> RandomEngineType { + assert!(RandomEngineType::PHILOX_4X32_10 as i32 <= t && t <= RandomEngineType::MERSENNE_GP11213 as i32); + unsafe { mem::transmute(t) } + } +} From 6c3e1dcfc9c15f652ba6cdd55c9cb90198e9c79d Mon Sep 17 00:00:00 2001 From: pradeep Date: Tue, 13 Sep 2016 23:19:04 +0530 Subject: [PATCH 27/36] Update README with latest version number details --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a55cf2315..8bf58bbee 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.3 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.4 API. If you find any bugs, please report them [here](https://github.com/arrayfire/arrayfire-rust/issues). ## Documentation @@ -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.2"` to the dependencies section of your project's Cargo.toml file. +4. Add `arrayfire = "3.4.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 ffe748ac5967e9aad2dc151c619b503153cb92cb Mon Sep 17 00:00:00 2001 From: pradeep Date: Wed, 14 Sep 2016 09:20:36 +0530 Subject: [PATCH 28/36] Correct doc test annotations --- src/algorithm/mod.rs | 43 ++++++++++++++++++++++++++----------------- src/array.rs | 6 +++--- src/data/mod.rs | 10 +++++----- src/device/mod.rs | 2 +- src/dim4.rs | 6 +++--- src/graphics.rs | 2 +- src/image/mod.rs | 2 +- src/index.rs | 12 ++++++------ src/macros.rs | 8 ++++---- 9 files changed, 50 insertions(+), 41 deletions(-) diff --git a/src/algorithm/mod.rs b/src/algorithm/mod.rs index acedfb3b4..8a7622705 100644 --- a/src/algorithm/mod.rs +++ b/src/algorithm/mod.rs @@ -82,7 +82,7 @@ dim_reduce_func_def!(" # Examples - ``` + ```rust use arrayfire::{Dim4, print, randu, sum}; let dims = Dim4::new(&[5, 3, 1, 1]); let a = randu::(dims); @@ -109,7 +109,7 @@ dim_reduce_func_def!(" # Examples - ``` + ```rust use arrayfire::{Dim4, print, randu, product}; let dims = Dim4::new(&[5, 3, 1, 1]); let a = randu::(dims); @@ -135,7 +135,7 @@ dim_reduce_func_def!(" # Examples - ``` + ```rust use arrayfire::{Dim4, print, randu, min}; let dims = Dim4::new(&[5, 3, 1, 1]); let a = randu::(dims); @@ -144,6 +144,7 @@ dim_reduce_func_def!(" print(&b); let c = min(&a, 1); print(&c); + ``` ", min, af_min); dim_reduce_func_def!(" @@ -160,7 +161,7 @@ dim_reduce_func_def!(" # Examples - ``` + ```rust use arrayfire::{Dim4, print, randu, max}; let dims = Dim4::new(&[5, 3, 1, 1]); let a = randu::(dims); @@ -169,6 +170,7 @@ dim_reduce_func_def!(" print(&b); let c = max(&a, 1); print(&c); + ``` ", max, af_max); dim_reduce_func_def!(" @@ -185,7 +187,7 @@ dim_reduce_func_def!(" # Examples - ``` + ```rust use arrayfire::{Dim4, print, randu, all_true}; let dims = Dim4::new(&[5, 3, 1, 1]); let a = randu::(dims); @@ -194,6 +196,7 @@ dim_reduce_func_def!(" print(&b); let c = all_true(&a, 1); print(&c); + ``` ", all_true, af_all_true); dim_reduce_func_def!(" @@ -210,7 +213,7 @@ dim_reduce_func_def!(" # Examples - ``` + ```rust use arrayfire::{Dim4, print, randu, any_true}; let dims = Dim4::new(&[5, 3, 1, 1]); let a = randu::(dims); @@ -219,6 +222,7 @@ dim_reduce_func_def!(" print(&b); let c = any_true(&a, 1); print(&c); + ``` ", any_true, af_any_true); dim_reduce_func_def!(" @@ -235,7 +239,7 @@ dim_reduce_func_def!(" # Examples - ``` + ```rust use arrayfire::{Dim4, gt, print, randu, count}; let dims = Dim4::new(&[5, 3, 1, 1]); let a = gt(&randu::(dims), &0.5, false); @@ -244,6 +248,7 @@ dim_reduce_func_def!(" print(&b); let c = count(&a, 1); print(&c); + ``` ", count, af_count); dim_reduce_func_def!(" @@ -260,7 +265,7 @@ dim_reduce_func_def!(" # Examples - ``` + ```rust use arrayfire::{Dim4, print, randu, accum}; let dims = Dim4::new(&[5, 3, 1, 1]); let a = randu::(dims); @@ -269,6 +274,7 @@ dim_reduce_func_def!(" print(&b); let c = accum(&a, 1); print(&c); + ``` ", accum, af_accum); dim_reduce_func_def!(" @@ -285,7 +291,7 @@ dim_reduce_func_def!(" # Examples - ``` + ```rust use arrayfire::{Dim4, print, randu, diff1}; let dims = Dim4::new(&[5, 3, 1, 1]); let a = randu::(dims); @@ -294,6 +300,7 @@ dim_reduce_func_def!(" print(&b); let c = diff1(&a, 1); print(&c); + ``` ", diff1, af_diff1); dim_reduce_func_def!(" @@ -310,7 +317,7 @@ dim_reduce_func_def!(" # Examples - ``` + ```rust use arrayfire::{Dim4, print, randu, diff2}; let dims = Dim4::new(&[5, 3, 1, 1]); let a = randu::(dims); @@ -319,6 +326,7 @@ dim_reduce_func_def!(" print(&b); let c = diff2(&a, 1); print(&c); + ``` ", diff2, af_diff2); /// Sum along specific dimension using user specified value instead of `NAN` values @@ -400,7 +408,7 @@ all_reduce_func_def!(" # Examples - ``` + ```rust use arrayfire::{Dim4, print, randu, sum_all}; let dims = Dim4::new(&[5, 5, 1, 1]); let a = randu::(dims); @@ -424,7 +432,7 @@ all_reduce_func_def!(" # Examples - ``` + ```rust use arrayfire::{Dim4, print, randu, product_all}; let dims = Dim4::new(&[5, 5, 1, 1]); let a = randu::(dims); @@ -448,7 +456,7 @@ all_reduce_func_def!(" # Examples - ``` + ```rust use arrayfire::{Dim4, print, randu, min_all}; let dims = Dim4::new(&[5, 5, 1, 1]); let a = randu::(dims); @@ -472,7 +480,7 @@ all_reduce_func_def!(" # Examples - ``` + ```rust use arrayfire::{Dim4, print, randu, max_all}; let dims = Dim4::new(&[5, 5, 1, 1]); let a = randu::(dims); @@ -494,7 +502,7 @@ all_reduce_func_def!(" # Examples - ``` + ```rust use arrayfire::{Dim4, print, randu, all_true_all}; let dims = Dim4::new(&[5, 5, 1, 1]); let a = randu::(dims); @@ -516,12 +524,13 @@ all_reduce_func_def!(" # Examples - ``` + ```rust use arrayfire::{Dim4, print, randu, any_true_all}; let dims = Dim4::new(&[5, 5, 1, 1]); let a = randu::(dims); print(&a); println!(\"Result : {:?}\", any_true_all(&a)); + ``` ", any_true_all, af_any_true_all); all_reduce_func_def!(" @@ -537,7 +546,7 @@ all_reduce_func_def!(" # Examples - ``` + ```rust use arrayfire::{Dim4, print, randu, count_all}; let dims = Dim4::new(&[5, 5, 1, 1]); let a = randu::(dims); diff --git a/src/array.rs b/src/array.rs index 58011022c..c7636a2e8 100644 --- a/src/array.rs +++ b/src/array.rs @@ -132,7 +132,7 @@ impl Array { /// /// # Examples /// - /// ``` + /// ```rust /// use arrayfire::{Array, Dim4, print}; /// let values: [f32; 3] = [1.0, 2.0, 3.0]; /// let indices = Array::new(&values, Dim4::new(&[3, 1, 1, 1])); @@ -419,7 +419,7 @@ impl Drop for Array { /// /// # Examples /// -/// ``` +/// ```rust /// use arrayfire::{Dim4, print, randu}; /// println!("Create a 5-by-3 matrix of random floats on the GPU"); /// let dims = Dim4::new(&[5, 3, 1, 1]); @@ -429,7 +429,7 @@ impl Drop for Array { /// /// The sample output will look like below: /// -/// ```bash +/// ```text /// [5 3 1 1] /// 0.7402 0.4464 0.7762 /// 0.9210 0.6673 0.2948 diff --git a/src/data/mod.rs b/src/data/mod.rs index 511237d71..23fbfbf24 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -481,7 +481,7 @@ pub fn upper(input: &Array, is_unit_diag: bool) -> Array { /// This function does the C-equivalent of the following statement, except that the operation /// happens on a GPU for all elements simultaneously. /// -/// ```ignore +/// ```text /// c = cond ? a : b; /// where cond, a & b are all objects of type Array /// ``` /// @@ -512,7 +512,7 @@ pub fn select(a: &Array, cond: &Array, b: &Array) -> Array { /// This function does the C-equivalent of the following statement, except that the operation /// happens on a GPU for all elements simultaneously. /// -/// ```ignore +/// ```text /// c = cond ? a : b; /// where a is a scalar(f64) and b is Array /// ``` /// @@ -543,7 +543,7 @@ pub fn selectl(a: f64, cond: &Array, b: &Array) -> Array { /// This function does the C-equivalent of the following statement, except that the operation /// happens on a GPU for all elements simultaneously. /// -/// ```ignore +/// ```text /// c = cond ? a : b; /// where a is Array and b is a scalar(f64) /// ``` /// @@ -574,7 +574,7 @@ pub fn selectr(a: &Array, cond: &Array, b: f64) -> Array { /// This function does the C-equivalent of the following statement, except that the operation /// happens on a GPU for all elements simultaneously. /// -/// ```ignore +/// ```text /// a = cond ? a : b; /// where cond, a & b are all objects of type Array /// ``` /// @@ -601,7 +601,7 @@ pub fn replace(a: &mut Array, cond: &Array, b: &Array) { /// This function does the C-equivalent of the following statement, except that the operation /// happens on a GPU for all elements simultaneously. /// -/// ```ignore +/// ```text /// 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 250b2fbb5..d8a8a0081 100644 --- a/src/device/mod.rs +++ b/src/device/mod.rs @@ -44,7 +44,7 @@ pub fn get_version() -> (i32, i32, i32) { /// /// An example output of `af::info` call looks like below /// -/// ```ignore +/// ```text /// 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 29eda2375..0ddcac59f 100644 --- a/src/dim4.rs +++ b/src/dim4.rs @@ -18,7 +18,7 @@ impl Default for Dim4 { /// /// # Examples /// -/// ``` +/// ```rust /// use arrayfire::Dim4; /// /// let dims = Dim4::new(&[4, 4, 2, 1]); @@ -39,7 +39,7 @@ impl Index for Dim4 { /// /// # Examples /// -/// ``` +/// ```rust /// use arrayfire::Dim4; /// /// let dims = Dim4::new(&[4, 4, 2, 1]); @@ -56,7 +56,7 @@ impl Dim4 { /// /// # Examples /// - /// ``` + /// ```rust /// use arrayfire::Dim4; /// let dims = Dim4::new(&[4, 4, 2, 1]); /// ``` diff --git a/src/graphics.rs b/src/graphics.rs index b15f3e95a..ed92255c4 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -85,7 +85,7 @@ pub struct Cell { /// /// # Examples /// -/// ```no_run +/// ```rust,no_run /// use arrayfire::{histogram, load_image, Window}; /// 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*/); diff --git a/src/image/mod.rs b/src/image/mod.rs index 0e8538917..88258d541 100644 --- a/src/image/mod.rs +++ b/src/image/mod.rs @@ -931,7 +931,7 @@ hsvrgb_func_def!("RGB to HSV color space conversion", rgb2hsv, af_rgb2hsv); /// /// # Examples /// -/// ```ignore +/// ```text /// 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 f520578cd..273963bab 100644 --- a/src/index.rs +++ b/src/index.rs @@ -117,7 +117,7 @@ impl Drop for Indexer { /// /// # Examples /// -/// ``` +/// ```rust /// use arrayfire::{Dim4, Seq, index, randu, print}; /// let dims = Dim4::new(&[5, 5, 1, 1]); /// let a = randu::(dims); @@ -145,7 +145,7 @@ pub fn index(input: &Array, seqs: &[Seq]) -> Array /// /// # Examples /// -/// ``` +/// ```rust /// use arrayfire::{Dim4, randu, row, print}; /// let dims = Dim4::new(&[5, 5, 1, 1]); /// let a = randu::(dims); @@ -183,7 +183,7 @@ pub fn set_rows(input: &Array, new_rows: &Array, first: u64, last: u64) -> Array /// /// # Examples /// -/// ``` +/// ```rust /// use arrayfire::{Dim4, randu, col, print}; /// let dims = Dim4::new(&[5, 5, 1, 1]); /// let a = randu::(dims); @@ -274,7 +274,7 @@ pub fn lookup(input: &Array, indices: &Array, seq_dim: i32) -> Array { /// /// # Examples /// -/// ``` +/// ```rust /// use arrayfire::{constant, Dim4, Seq, assign_seq, print}; /// let a = constant(2.0 as f32, Dim4::new(&[5, 3, 1, 1])); /// let b = constant(1.0 as f32, Dim4::new(&[3, 3, 1, 1])); @@ -313,7 +313,7 @@ pub fn assign_seq(lhs: &Array, seqs: &[Seq], rhs: &Array) -> Array /// /// # Examples /// -/// ``` +/// ```rust /// use arrayfire::{Array, Dim4, Seq, print, randu, index_gen, Indexer}; /// let values: [f32; 3] = [1.0, 2.0, 3.0]; /// let indices = Array::new(&values, Dim4::new(&[3, 1, 1, 1])); @@ -352,7 +352,7 @@ pub fn index_gen(input: &Array, indices: Indexer) -> Array { /// /// # Examples /// -/// ``` +/// ```rust /// use arrayfire::{Array, Dim4, Seq, print, randu, constant, Indexer, assign_gen}; /// let values: [f32; 3] = [1.0, 2.0, 3.0]; /// let indices = Array::new(&values, Dim4::new(&[3, 1, 1, 1])); diff --git a/src/macros.rs b/src/macros.rs index 5ceb4ca8d..b26b683d1 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -35,7 +35,7 @@ /// /// # Examples /// -/// ``` +/// ```rust /// # #[macro_use(mem_info)] extern crate arrayfire; /// # fn main() { /// use arrayfire::{Dim4, device_mem_info, print, randu}; @@ -49,7 +49,7 @@ /// /// Sample Output: /// -/// ```ignore +/// ```text /// AF Memory: Here /// Allocated [ Bytes | Buffers ] = [ 4096 | 4 ] /// In Use [ Bytes | Buffers ] = [ 2048 | 2 ] @@ -72,7 +72,7 @@ macro_rules! mem_info { /// /// # Examples /// -/// ``` +/// ```rust /// # #[macro_use] extern crate arrayfire; /// /// # fn main() { @@ -108,7 +108,7 @@ macro_rules! join_many { /// /// # Examples /// -/// ``` +/// ```rust /// # #[macro_use] extern crate arrayfire; /// /// # fn main() { From 88d48370ea6ba605b5327f187545b12c436e4ea2 Mon Sep 17 00:00:00 2001 From: pradeep Date: Wed, 14 Sep 2016 12:40:20 +0530 Subject: [PATCH 29/36] Add add/sub/mul/div operator traits for type Array These operator traits were implemented only for &Array earlier. --- src/arith/mod.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/arith/mod.rs b/src/arith/mod.rs index af0faf0ac..fdb5a196f 100644 --- a/src/arith/mod.rs +++ b/src/arith/mod.rs @@ -333,7 +333,22 @@ macro_rules! arith_scalar_func { unsafe { let mut temp: i64 = 0; let err_val = $ffi_fn(&mut temp as MutAfArray, self.get() as AfArray, - cnst_arr.get() as AfArray, 0); + cnst_arr.get() as AfArray, 0); + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) + } + } + } + + impl $op_name<$rust_type> for Array { + type Output = Array; + + fn $fn_name(self, rhs: $rust_type) -> Array { + let cnst_arr = constant(rhs, self.dims()); + unsafe { + let mut temp: i64 = 0; + 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) } From 2801bbacf588444f27847167fca96fd62e667d57 Mon Sep 17 00:00:00 2001 From: pradeep Date: Wed, 14 Sep 2016 12:41:19 +0530 Subject: [PATCH 30/36] FEATURE: Array print function with precision parameter Also fixed the earlier print function to stop printing the string "No Name Array" when no array message was given. --- src/array.rs | 55 +++++++++++++++++++++++++++++++++++++++++++++++++-- src/lib.rs | 2 +- src/macros.rs | 5 ++--- 3 files changed, 56 insertions(+), 6 deletions(-) diff --git a/src/array.rs b/src/array.rs index c7636a2e8..aa6df0b46 100644 --- a/src/array.rs +++ b/src/array.rs @@ -4,7 +4,8 @@ use dim4::Dim4; 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}; +use self::libc::{uint8_t, c_void, c_int, c_uint, c_longlong, c_char}; +use std::ffi::CString; type MutAfArray = *mut self::libc::c_longlong; type MutDouble = *mut self::libc::c_double; @@ -78,6 +79,8 @@ extern { fn af_print_array(arr: AfArray) -> c_int; + fn af_print_array_gen(exp: *const c_char, arr: AfArray, precision: c_int) -> c_int; + 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; @@ -417,6 +420,10 @@ impl Drop for Array { /// Print data in the Array /// +/// # Parameters +/// +/// - `input` is the Array to be printed +/// /// # Examples /// /// ```rust @@ -438,8 +445,52 @@ impl Drop for Array { /// 0.9251 0.5132 0.6814 /// ``` pub fn print(input: &Array) { + let emptystring = CString::new("").unwrap(); + unsafe { + let err_val = af_print_array_gen(emptystring.to_bytes_with_nul().as_ptr() as *const c_char, + input.get() as AfArray, 4); + HANDLE_ERROR(AfError::from(err_val)); + } +} + +/// Generalized Array print function +/// +/// Use this function to print Array data with arbitrary preicsion +/// +/// # Parameters +/// +/// - `msg` is message to be printed before printing the Array data +/// - `input` is the Array to be printed +/// - `precision` is data precision with which Array has to be printed +/// +/// # Examples +/// +/// ```rust +/// use arrayfire::{Dim4, print_gen, randu}; +/// println!("Create a 5-by-3 matrix of random floats on the GPU"); +/// let dims = Dim4::new(&[5, 3, 1, 1]); +/// let a = randu::(dims); +/// print_gen(String::from("Random Array"), &a, Some(6)); +/// ``` +/// +/// The sample output will look like below: +/// +/// ```text +/// Random Array +/// +/// [5 3 1 1] +/// 0.740276 0.446440 0.776202 +/// 0.921094 0.667321 0.294810 +/// 0.039014 0.109939 0.714090 +/// 0.969058 0.470269 0.358590 +/// 0.925181 0.513225 0.681451 +/// ``` +pub fn print_gen(msg: String, input: &Array, precision: Option) { + let emptystring = CString::new(msg.as_bytes()).unwrap(); unsafe { - let err_val = af_print_array(input.get() as AfArray); + let err_val = af_print_array_gen(emptystring.to_bytes_with_nul().as_ptr() as *const c_char, + input.get() as AfArray, + match precision {Some(p)=>p, None=>4} as c_int); HANDLE_ERROR(AfError::from(err_val)); } } diff --git a/src/lib.rs b/src/lib.rs index 3badbe3e8..00a4426ef 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,7 +6,7 @@ extern crate lazy_static; pub use array::Array; -pub use array::{print, eval_multiple, is_eval_manual, set_manual_eval}; +pub use array::{print, print_gen, eval_multiple, is_eval_manual, set_manual_eval}; mod array; //pub use algorithm::{sum_nan, product_nan, sum_nan_all, product_nan_all}; diff --git a/src/macros.rs b/src/macros.rs index b26b683d1..d427af28d 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -112,7 +112,7 @@ macro_rules! join_many { /// # #[macro_use] extern crate arrayfire; /// /// # fn main() { -/// use arrayfire::{Dim4, print, randu}; +/// use arrayfire::{Dim4, print_gen, randu}; /// let dims = Dim4::new(&[3, 1, 1, 1]); /// let a = randu::(dims); /// af_print!("Create a 5-by-3 matrix of random floats on the GPU", a); @@ -123,8 +123,7 @@ macro_rules! join_many { macro_rules! af_print { [$msg: expr, $x: ident] => { { - println!("{}", $msg); - print(&$x); + print_gen(String::from($msg), &$x, Some(4)); } }; } From af545685d3eb464ced9911f5aeab44e54776bba1 Mon Sep 17 00:00:00 2001 From: pradeep Date: Wed, 14 Sep 2016 21:00:46 +0530 Subject: [PATCH 31/36] fix doc test for count function to use f32 type If the scalar constant is of type f64, tests are failing on devices that doesn't support double data types. This is a temporary fix. --- src/algorithm/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/algorithm/mod.rs b/src/algorithm/mod.rs index 8a7622705..87379ed6e 100644 --- a/src/algorithm/mod.rs +++ b/src/algorithm/mod.rs @@ -242,7 +242,8 @@ dim_reduce_func_def!(" ```rust use arrayfire::{Dim4, gt, print, randu, count}; let dims = Dim4::new(&[5, 3, 1, 1]); - let a = gt(&randu::(dims), &0.5, false); + let cnst: f32 = 0.5; + let a = gt(&randu::(dims), &cnst, false); print(&a); let b = count(&a, 0); print(&b); From edf9fdf8e08c1bcc5c4a22d6eed47312600a587f Mon Sep 17 00:00:00 2001 From: pradeep Date: Wed, 14 Sep 2016 21:03:43 +0530 Subject: [PATCH 32/36] BUGFIX: fix type mismatch in RandomEngine new method --- src/random/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/random/mod.rs b/src/random/mod.rs index b3a624e80..018fad274 100644 --- a/src/random/mod.rs +++ b/src/random/mod.rs @@ -117,7 +117,7 @@ impl RandomEngine { unsafe { let mut temp: i64 = 0; let err_val = af_create_random_engine(&mut temp as MutRandEngine, rengine as uint8_t, - match seed {Some(s) => s, None => 0} as c_ulong); + match seed {Some(s) => s, None => 0} as Uintl); HANDLE_ERROR(AfError::from(err_val)); RandomEngine::from(temp) } From 316c97e7086e56caef57474393290b8194d0a394 Mon Sep 17 00:00:00 2001 From: pradeep Date: Thu, 15 Sep 2016 12:20:00 +0530 Subject: [PATCH 33/36] Change README rust example code to reflect v3.4.0 --- README.md | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 8bf58bbee..87a1f4a6e 100644 --- a/README.md +++ b/README.md @@ -58,12 +58,8 @@ cargo build let num_rows: u64 = 5; let num_cols: u64 = 3; 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) { - Ok(value) => value, - Err(error) => panic!("{}", error), -}; -print(&a); +let a = randu::(dims); +af_print!("Create a 5-by-3 matrix of random floats on the GPU", a); ``` ### Sample output @@ -72,9 +68,10 @@ print(&a); ~/p/arrayfire_rust> cargo run --example helloworld ... running 1 test -ArrayFire v3.2.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 +ArrayFire v3.4.0 (CUDA, 64-bit Linux, build 10d9716) +Platform: CUDA Toolkit 7.5, Driver: 361.42 +[0] GeForce GT 650M, 2048 MB, CUDA Compute 3.0 + Create a 5-by-3 matrix of random floats on the GPU [5 3 1 1] 0.7402 0.4464 0.7762 @@ -82,7 +79,6 @@ Create a 5-by-3 matrix of random floats on the GPU 0.0390 0.1099 0.7140 0.9690 0.4702 0.3585 0.9251 0.5132 0.6814 - ... ``` From fdda86b9d50ddb606aef4606384aba016c389efa Mon Sep 17 00:00:00 2001 From: pradeep Date: Thu, 15 Sep 2016 12:22:03 +0530 Subject: [PATCH 34/36] Removed unused imports in random module --- src/random/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/random/mod.rs b/src/random/mod.rs index 018fad274..9a095ad2d 100644 --- a/src/random/mod.rs +++ b/src/random/mod.rs @@ -4,7 +4,7 @@ use array::Array; use dim4::Dim4; use defines::{AfError, RandomEngineType}; use error::HANDLE_ERROR; -use self::libc::{uint8_t, c_int, c_uint, c_ulong}; +use self::libc::{uint8_t, c_int, c_uint}; use util::HasAfEnum; type MutAfArray = *mut self::libc::c_longlong; From f60f43ac88398f9086d6188f89c75af98c15aab4 Mon Sep 17 00:00:00 2001 From: pradeep Date: Thu, 15 Sep 2016 13:34:30 +0530 Subject: [PATCH 35/36] Add documentation for clamp function --- src/arith/mod.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/arith/mod.rs b/src/arith/mod.rs index fdb5a196f..6a49a68ad 100644 --- a/src/arith/mod.rs +++ b/src/arith/mod.rs @@ -256,6 +256,10 @@ macro_rules! overloaded_binary_func { ///# Return Values /// /// An Array with results of the binary operation. + /// + ///# Note + /// + /// The trait `Convertable` essentially translates to a scalar native type on rust or Array. pub fn $fn_name (arg1: &T, arg2: &U, batch: bool) -> Array where T: Convertable, U: Convertable { let lhs = arg1.convert(); let rhs = arg2.convert(); @@ -294,6 +298,24 @@ overloaded_binary_func!("Create complex array from two Arrays", cplx2, cplx2_hel overloaded_binary_func!("Compute root", root, root_helper, af_root); overloaded_binary_func!("Computer power", pow, pow_helper, af_pow); +/// Clamp the values of Array +/// +/// # Parameters +/// +/// - `arg1`is an argument that implements an internal trait `Convertable`. +/// - `arg2`is an argument that implements an internal trait `Convertable`. +/// - `batch` is an boolean that indicates if the current operation is an batch operation. +/// +/// Both parameters `arg1` and `arg2` can be either an Array or a value of rust integral +/// type. +/// +/// # Return Values +/// +/// An Array with results of the binary operation. +/// +/// # Note +/// +/// The trait `Convertable` essentially translates to a scalar native type on rust or Array. pub fn clamp (input: &Array, arg1: &T, arg2: &U, batch: bool) -> Array where T: Convertable, U: Convertable { From 5e98e824b4259c08e3c9127e1f91c81729d2c470 Mon Sep 17 00:00:00 2001 From: pradeep Date: Thu, 15 Sep 2016 13:51:53 +0530 Subject: [PATCH 36/36] Update documentation for graphics module --- src/graphics.rs | 131 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 128 insertions(+), 3 deletions(-) diff --git a/src/graphics.rs b/src/graphics.rs index ed92255c4..e17f65c1a 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -134,6 +134,16 @@ impl Drop for Window { impl Window { /// Creates new Window object + /// + /// # Parameters + /// + /// - `width` is width of the window + /// - `height` is the height of window + /// - `title` is the string displayed on window title bar + /// + /// # Return Values + /// + /// Window Object #[allow(unused_mut)] pub fn new(width: i32, height: i32, title: String) -> Window { unsafe { @@ -153,6 +163,11 @@ impl Window { } /// Set window starting position on the screen + /// + /// # Parameters + /// + /// - `x` is the horiontal coordinate where window is to be placed + /// - `y` is the vertical coordinate where window is to be placed 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); @@ -161,6 +176,10 @@ impl Window { } /// Set window title + /// + /// # Parameters + /// + /// - `title` is the string to be displayed on window title bar pub fn set_title(&self, title: String) { unsafe { let cstr_ret = CString::new(title.as_bytes()); @@ -220,7 +239,12 @@ impl Window { } } - /// Used to setup display layout in multiview mode + /// Setup display layout in multiview mode + /// + /// # Parameters + /// + /// - `rows` is the number of rows into which whole window is split into in multiple view mode + /// - `cols` is the number of cols into which whole window is split into in multiple view mode 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); @@ -239,8 +263,14 @@ impl Window { } } - /// Used in multiview mode to set the current sub-region to which the subsequence draw call - /// renders to + /// Set the current sub-region to render + /// + /// This function is only to be used into multiview mode + /// + /// # Parameters + /// + /// - `r` is the target row id + /// - `c` is the target row id pub fn set_view(&mut self, r: i32, c: i32) { self.row = r; self.col = c; @@ -351,6 +381,12 @@ impl Window { } /// Render given Array as an image + /// + /// # Parameters + /// + /// - `input` image + /// - `title` parameter has effect only in multiview mode, where this string + /// is displayed as the respective cell/view title. pub fn draw_image(&self, input: &Array, title: Option) { let tstr = match title { Some(s) => s, @@ -365,6 +401,13 @@ impl Window { } /// Render given two Array's `x` and `y` as a 2d line plot + /// + /// # Parameters + /// + /// - `x` is the x coordinates of the plot + /// - `y` is the y coordinates of the plot + /// - `title` parameter has effect only in multiview mode, where this string + /// is displayed as the respective cell/view title. pub fn draw_plot2(&self, x: &Array, y: &Array, title: Option) { let tstr = match title { Some(s) => s, @@ -380,6 +423,14 @@ impl Window { } /// Render given Array's `x`, `y` and `z` as a 3d line plot + /// + /// # Parameters + /// + /// - `x` is the x coordinates of the plot + /// - `y` is the y coordinates of the plot + /// - `z` is the z coordinates of the plot + /// - `title` parameter has effect only in multiview mode, where this string + /// is displayed as the respective cell/view title. pub fn draw_plot3(&self, x: &Array, y: &Array, z: &Array, title: Option) { let tstr = match title { Some(s) => s, @@ -395,6 +446,12 @@ impl Window { } /// Render give Arrays of points as a 3d line plot + /// + /// # Parameters + /// + /// - `points` is an Array containing list of points of plot + /// - `title` parameter has effect only in multiview mode, where this string + /// is displayed as the respective cell/view title. pub fn draw_plot(&self, points: &Array, title: Option) { let tstr = match title { Some(s) => s, @@ -409,6 +466,14 @@ impl Window { } /// Render given Array as a histogram + /// + /// # Parameters + /// + /// - `hst` is an Array containing histogram data + /// - `minval` is the minimum bin value of histogram + /// - `maxval` is the maximum bin value of histogram + /// - `title` parameter has effect only in multiview mode, where this string + /// is displayed as the respective cell/view title. pub fn draw_hist(&self, hst: &Array, minval: f64, maxval: f64, title: Option) { let tstr = match title { Some(s) => s, @@ -424,6 +489,14 @@ impl Window { } /// Render give Arrays as 3d surface + /// + /// # Parameters + /// + /// - `x` is the x coordinates of the surface plot + /// - `y` is the y coordinates of the surface plot + /// - `z` is the z coordinates of the surface plot + /// - `title` parameter has effect only in multiview mode, where this string + /// is displayed as the respective cell/view title. pub fn draw_surface(&self, xvals: &Array, yvals: &Array, zvals: &Array, title: Option) { let tstr = match title { Some(s) => s, @@ -441,6 +514,14 @@ impl Window { } /// Render given Arrays as 2d scatter plot + /// + /// # Parameters + /// + /// - `xvals` is the x coordinates of the scatter plot + /// - `yvals` is the y coordinates of the scatter plot + /// - `marker` is of enum type [MarkerType](./enum.MarkerType.html) + /// - `title` parameter has effect only in multiview mode, where this string + /// is displayed as the respective cell/view title. pub fn draw_scatter2(&self, xvals: &Array, yvals: &Array, marker: MarkerType, title: Option) { let tstr = match title { @@ -457,6 +538,15 @@ impl Window { } /// Render given Arrays as 3d scatter plot + /// + /// # Parameters + /// + /// - `xvals` is the x coordinates of the scatter plot + /// - `yvals` is the y coordinates of the scatter plot + /// - `zvals` is the z coordinates of the scatter plot + /// - `marker` is of enum type [MarkerType](./enum.MarkerType.html) + /// - `title` parameter has effect only in multiview mode, where this string + /// is displayed as the respective cell/view title. pub fn draw_scatter3(&self, xvals: &Array, yvals: &Array, zvals: &Array, marker: MarkerType, title: Option) { let tstr = match title { @@ -473,6 +563,13 @@ impl Window { } /// Render give Array as 3d scatter plot + /// + /// # Parameters + /// + /// - `points` is an Array containing list of points of plot + /// - `marker` is of enum type [MarkerType](./enum.MarkerType.html) + /// - `title` parameter has effect only in multiview mode, where this string + /// is displayed as the respective cell/view title. pub fn draw_scatter(&self, vals: &Array, marker: MarkerType, title: Option) { let tstr = match title { Some(s) => s, @@ -487,6 +584,15 @@ impl Window { } /// Render given Arrays as 2d vector field + /// + /// # Parameters + /// + /// - `xpnts` is an Array containing list of x coordinates + /// - `xdirs` is an Array containing direction component of x coord + /// - `ypnts` is an Array containing list of y coordinates + /// - `ydirs` is an Array containing direction component of y coord + /// - `title` parameter has effect only in multiview mode, where this string + /// is displayed as the respective cell/view title. pub fn draw_vector_field2(&self, xpnts: &Array, ypnts: &Array, xdirs: &Array, ydirs: &Array, title: Option) { let tstr = match title { @@ -504,6 +610,17 @@ impl Window { } /// Render given Arrays as 3d vector field + /// + /// # Parameters + /// + /// - `xpnts` is an Array containing list of x coordinates + /// - `xdirs` is an Array containing direction component of x coord + /// - `ypnts` is an Array containing list of y coordinates + /// - `ydirs` is an Array containing direction component of y coord + /// - `zpnts` is an Array containing list of z coordinates + /// - `zdirs` is an Array containing direction component of z coord + /// - `title` parameter has effect only in multiview mode, where this string + /// is displayed as the respective cell/view title. pub fn draw_vector_field3(&self, xpnts: &Array, ypnts: &Array, zpnts: &Array, xdirs: &Array, ydirs: &Array, zdirs: &Array, title: Option) { @@ -523,6 +640,14 @@ impl Window { } /// Render given Array as vector field + /// + /// # Parameters + /// + /// - `points` is an Array containing list of coordinates of vector field + /// - `directions` is an Array containing directions at the coordinates specified in `points` + /// Array. + /// - `title` parameter has effect only in multiview mode, where this string + /// is displayed as the respective cell/view title. pub fn draw_vector_field(&self, points: &Array, directions: &Array, title: Option) { let tstr = match title { Some(s) => s,