From 4b79dec92cf3b7eef04498ae50f388f123aa84f7 Mon Sep 17 00:00:00 2001 From: Tim Date: Sat, 22 Oct 2016 16:03:58 +0100 Subject: [PATCH 1/9] Add acoustic wave example --- examples/acoustic_wave.rs | 81 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 examples/acoustic_wave.rs diff --git a/examples/acoustic_wave.rs b/examples/acoustic_wave.rs new file mode 100644 index 000000000..b29a19777 --- /dev/null +++ b/examples/acoustic_wave.rs @@ -0,0 +1,81 @@ +extern crate arrayfire as af; + +use af::*; +use std::f64::consts::*; + +fn main() { + set_device(0); + info(); + + acoustic_wave_simulation(); +} + +fn normalise(a: &Array) -> Array { + (a/(max_all(&abs(a)).0 as f32 * 2.0f32)) + 0.5f32 +} +fn acoustic_wave_simulation() { + // Speed of sound + let c = 0.1; + // Distance step + let dx = 0.5; + // Time step + let dt = 1.0; + + // Grid size. + let nx = 1500; + let ny = 1500; + + // Grid dimensions. + let dims = Dim4::new(&[nx, ny, 1, 1]); + + // Pressure field + let mut p = constant::(0.0, dims); + // d(pressure)/dt field + let mut p_dot = p.clone(); + + // Laplacian (Del^2) convolution kernel. + let laplacian_values = [0.0f32, 1.0, 0.0, + 1.0, -4.0, 1.0, + 0.0, 1.0, 0.0]; + let laplacian_kernel = Array::new(&laplacian_values, Dim4::new(&[3, 3, 1, 1])) / (dx * dx); + + // Create a window to show the waves. + let mut win = Window::new(1000, 1000, "Waves".to_string()); + + // Hann windowed pulse. + let pulse_time = 100.0f64; + let centre_freq = 0.05; + + // Number of samples in pulse. + let pulse_n = (pulse_time/dt).floor() as u64; + + let i = range::(Dim4::new(&[pulse_n, 1, 1, 1]), 0); + let t = i.clone() * dt; + let hamming_window = cos(&(i * (2.0 * PI / pulse_n as f64))) * -0.46 + 0.54; + let wave = sin(&(&t * centre_freq * 2.0 * PI)); + let pulse = wave * hamming_window; + + // Iteration count. + let mut it = 0; + + while !win.is_closed() { + // Convole with laplacian to get spacial second derivative. + let lap_p = convolve2(&p, &laplacian_kernel, ConvMode::DEFAULT, ConvDomain::SPATIAL); + // Calculate the updated pressure and d(pressure)/dt fields. + p_dot += lap_p * (c * dt); + p += &p_dot * dt; + + if it < pulse_n { + // Location of the source. + let seqs = &[Seq::new(700.0, 800.0, 1.0), Seq::new(800.0, 800.0, 1.0)]; + // Set the pressure there. + p = assign_seq(&p, seqs, &index(&pulse, &[Seq::new(it as f64, it as f64, 1.0)])); + } + + // Draw the image. + win.set_colormap(af::ColorMap::BLUE); + win.draw_image(&normalise(&p), None); + + it += 1; + } +} From 51d917b81a3353c9e88401e9c4f67b0dea63cddc Mon Sep 17 00:00:00 2001 From: Tim Date: Sat, 22 Oct 2016 16:04:47 +0100 Subject: [PATCH 2/9] Add acoustic wave example to Cargo.toml --- Cargo.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index eb5ca7752..ddbbc535f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,3 +46,7 @@ path = "examples/snow.rs" [[example]] name = "histogram" path = "examples/histogram.rs" + +[[example]] +name = "acoustic_wave" +path = "examples/acoustic_wave.rs" From 32f0868e68dfb194454efb5f3b3e9b976ee6f815 Mon Sep 17 00:00:00 2001 From: kryptan Date: Tue, 15 Nov 2016 22:28:25 +0300 Subject: [PATCH 3/9] Simplify string passing between Rust and C --- src/graphics.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/graphics.rs b/src/graphics.rs index e17f65c1a..16210e239 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -148,12 +148,12 @@ impl Window { pub fn new(width: i32, height: i32, title: String) -> Window { unsafe { let mut temp: u64 = 0; - let cstr_ret = CString::new(title.as_bytes()); + let cstr_ret = CString::new(title); match cstr_ret { Ok(cstr) => { let err_val = af_create_window(&mut temp as MutWndHandle, width as c_int, height as c_int, - cstr.to_bytes_with_nul().as_ptr() as *const c_char); + cstr.as_ptr()); HANDLE_ERROR(AfError::from(err_val)); Window::from(temp) }, @@ -182,11 +182,11 @@ impl Window { /// - `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()); + let cstr_ret = CString::new(title); match cstr_ret { Ok(cstr) => { let err_val = af_set_title(self.handle as WndHandle, - cstr.to_bytes_with_nul().as_ptr() as *const c_char); + cstr.as_ptr()); HANDLE_ERROR(AfError::from(err_val)); }, Err(_) => HANDLE_ERROR(AfError::ERR_INTERNAL), @@ -285,14 +285,14 @@ impl Window { /// - `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(); + let xstr = CString::new(xlabel).unwrap(); + let ystr = CString::new(ylabel).unwrap(); + let zstr = CString::new(zlabel).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, + xstr.as_ptr(), + ystr.as_ptr(), + zstr.as_ptr(), cprops as *const Cell as CellPtr); HANDLE_ERROR(AfError::from(err_val)); } From 576fa0e67dd035cb064d28267b2f39480996a23e Mon Sep 17 00:00:00 2001 From: kryptan Date: Tue, 15 Nov 2016 22:30:22 +0300 Subject: [PATCH 4/9] Fix Cell structure layout --- src/graphics.rs | 46 +++++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/src/graphics.rs b/src/graphics.rs index 16210e239..52d4a5907 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -73,7 +73,7 @@ extern { pub struct Cell { pub row: i32, pub col: i32, - pub title: String, + pub title: *const c_char, pub cmap: ColorMap, } @@ -284,7 +284,7 @@ impl Window { /// - `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 cprops = &Cell {row: self.row, col: self.col, title: [0].as_ptr(), cmap: self.cmap}; let xstr = CString::new(xlabel).unwrap(); let ystr = CString::new(ylabel).unwrap(); let zstr = CString::new(zlabel).unwrap(); @@ -314,7 +314,7 @@ impl Window { /// 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}; + let cprops = &Cell {row: self.row, col: self.col, title: [0].as_ptr(), cmap: self.cmap}; unsafe { let err_val = af_set_axes_limits_compute(self.handle as WndHandle, xrange.get() as AfArray, @@ -343,7 +343,7 @@ impl Window { /// 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}; + let cprops = &Cell {row: self.row, col: self.col, title: [0].as_ptr(), 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, @@ -370,7 +370,7 @@ impl Window { /// 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}; + let cprops = &Cell {row: self.row, col: self.col, title: [0].as_ptr(), 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, @@ -392,7 +392,8 @@ impl Window { 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}; + let tstr = CString::new(tstr).unwrap(); + let cprops = &Cell {row: self.row, col: self.col, title: tstr.as_ptr(), cmap: self.cmap}; unsafe { let err_val = af_draw_image(self.handle as WndHandle, input.get() as AfArray, cprops as *const Cell as CellPtr); @@ -413,7 +414,8 @@ impl Window { 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}; + let tstr = CString::new(tstr).unwrap(); + let cprops = &Cell {row: self.row, col: self.col, title: tstr.as_ptr(), cmap: self.cmap}; unsafe { let err_val = af_draw_plot_2d(self.handle as WndHandle, x.get() as AfArray, y.get() as AfArray, @@ -436,7 +438,8 @@ impl Window { 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}; + let tstr = CString::new(tstr).unwrap(); + let cprops = &Cell {row: self.row, col: self.col, title: tstr.as_ptr(), 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, @@ -457,7 +460,8 @@ impl Window { 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}; + let tstr = CString::new(tstr).unwrap(); + let cprops = &Cell {row: self.row, col: self.col, title: tstr.as_ptr(), cmap: self.cmap}; unsafe { let err_val = af_draw_plot_nd(self.handle as WndHandle, points.get() as AfArray, cprops as *const Cell as CellPtr); @@ -479,7 +483,8 @@ impl Window { 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}; + let tstr = CString::new(tstr).unwrap(); + let cprops = &Cell {row: self.row, col: self.col, title: tstr.as_ptr(), cmap: self.cmap}; unsafe { let err_val = af_draw_hist(self.handle as WndHandle, hst.get() as AfArray, minval as c_double, maxval as c_double, @@ -502,7 +507,8 @@ impl Window { 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}; + let tstr = CString::new(tstr).unwrap(); + let cprops = &Cell {row: self.row, col: self.col, title: tstr.as_ptr(), cmap: self.cmap}; unsafe { let err_val = af_draw_surface(self.handle as WndHandle, xvals.get() as AfArray, @@ -528,7 +534,8 @@ impl Window { 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}; + let tstr = CString::new(tstr).unwrap(); + let cprops = &Cell {row: self.row, col: self.col, title: tstr.as_ptr(), cmap: self.cmap}; unsafe { let err_val = af_draw_scatter_2d(self.handle as WndHandle, xvals.get() as AfArray, yvals.get() as AfArray, @@ -553,7 +560,8 @@ impl Window { 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}; + let tstr = CString::new(tstr).unwrap(); + let cprops = &Cell {row: self.row, col: self.col, title: tstr.as_ptr(), 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, @@ -575,7 +583,8 @@ impl Window { 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}; + let tstr = CString::new(tstr).unwrap(); + let cprops = &Cell {row: self.row, col: self.col, title: tstr.as_ptr(), 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); @@ -599,7 +608,8 @@ impl Window { 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}; + let tstr = CString::new(tstr).unwrap(); + let cprops = &Cell {row: self.row, col: self.col, title: tstr.as_ptr(), cmap: self.cmap}; unsafe { let err_val = af_draw_vector_field_2d(self.handle as WndHandle, xpnts.get() as AfArray, ypnts.get() as AfArray, @@ -628,7 +638,8 @@ impl Window { 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}; + let tstr = CString::new(tstr).unwrap(); + let cprops = &Cell {row: self.row, col: self.col, title: tstr.as_ptr(), 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, @@ -653,7 +664,8 @@ impl Window { 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}; + let tstr = CString::new(tstr).unwrap(); + let cprops = &Cell {row: self.row, col: self.col, title: tstr.as_ptr(), cmap: self.cmap}; unsafe { let err_val = af_draw_vector_field_nd(self.handle as WndHandle, points.get() as AfArray, directions.get() as AfArray, From 9c35ce4d5ec66d224da20120b0a2de1a2367b509 Mon Sep 17 00:00:00 2001 From: kryptan Date: Thu, 17 Nov 2016 19:56:06 +0300 Subject: [PATCH 5/9] Use null pointer instead of a pointer to an empty string --- src/graphics.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/graphics.rs b/src/graphics.rs index 52d4a5907..4cc6e657b 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -6,6 +6,7 @@ use defines::{ColorMap, MarkerType}; use error::HANDLE_ERROR; use self::libc::{c_int, c_uint, c_float, c_double, c_char}; use std::ffi::CString; +use std::ptr; type MutWndHandle = *mut self::libc::c_ulonglong; type WndHandle = self::libc::c_ulonglong; @@ -284,7 +285,7 @@ impl Window { /// - `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: [0].as_ptr(), cmap: self.cmap}; + let cprops = &Cell {row: self.row, col: self.col, title: ptr::null(), cmap: self.cmap}; let xstr = CString::new(xlabel).unwrap(); let ystr = CString::new(ylabel).unwrap(); let zstr = CString::new(zlabel).unwrap(); @@ -314,7 +315,7 @@ impl Window { /// 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: [0].as_ptr(), cmap: self.cmap}; + let cprops = &Cell {row: self.row, col: self.col, title: ptr::null(), cmap: self.cmap}; unsafe { let err_val = af_set_axes_limits_compute(self.handle as WndHandle, xrange.get() as AfArray, @@ -343,7 +344,7 @@ impl Window { /// 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: [0].as_ptr(), cmap: self.cmap}; + let cprops = &Cell {row: self.row, col: self.col, title: ptr::null(), 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, @@ -370,7 +371,7 @@ impl Window { /// 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: [0].as_ptr(), cmap: self.cmap}; + let cprops = &Cell {row: self.row, col: self.col, title: ptr::null(), 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, From bcd99097df075bf10e6ed615b9da391369fd2dc7 Mon Sep 17 00:00:00 2001 From: pradeep Date: Thu, 15 Dec 2016 12:30:42 +0530 Subject: [PATCH 6/9] new data generation function: constant_like function to create an array with same shape and type as input array filled with a constant --- src/data/mod.rs | 23 +++++++++++++++++++++++ src/lib.rs | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/data/mod.rs b/src/data/mod.rs index 23fbfbf24..ed6abd552 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -622,3 +622,26 @@ pub fn replace_scalar(a: &mut Array, cond: &Array, b: f64) { HANDLE_ERROR(AfError::from(err_val)); } } + +/// Create an array filled with given constant retaining type/shape of another Array. +/// +/// # Parameters +/// +/// - `value` is the constant with which output Array is to be filled +/// - `input` is the Array whose shape the output Array has to maintain +/// +/// # Return Values +/// +/// Array with given constant value and input Array's shape and similar internal data type. +pub fn constant_like(value: f64, input: &Array) -> Array { + let dims = input.dims(); + unsafe { + let mut temp: i64 = 0; + let err_val = af_constant(&mut temp as MutAfArray, value as c_double, + dims.ndims() as c_uint, + dims.get().as_ptr() as *const DimT, + input.get_type() as c_int); + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) + } +} diff --git a/src/lib.rs b/src/lib.rs index 00a4426ef..ae44f4ab6 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,7 +32,7 @@ mod backend; pub use blas::{matmul, dot, transpose, transpose_inplace}; mod blas; -pub use data::{constant, range, iota}; +pub use data::{constant, constant_like, range, iota}; 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}; From 63293afa34d33114f1675c5b0106f386d70d3c35 Mon Sep 17 00:00:00 2001 From: pradeep Date: Thu, 15 Dec 2016 12:37:55 +0530 Subject: [PATCH 7/9] Implement negation trait for Array --- src/arith/mod.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/arith/mod.rs b/src/arith/mod.rs index 6a49a68ad..4e50aa40a 100644 --- a/src/arith/mod.rs +++ b/src/arith/mod.rs @@ -6,9 +6,11 @@ use array::Array; use defines::AfError; use error::HANDLE_ERROR; use self::libc::{c_int}; -use data::{constant, tile}; +use data::{constant, constant_like, tile}; use self::num::Complex; +use std::ops::Neg; + type MutAfArray = *mut self::libc::c_longlong; type MutDouble = *mut self::libc::c_double; type MutUint = *mut self::libc::c_uint; @@ -485,3 +487,12 @@ bit_assign_func!(BitOrAssign, bitor_assign, bitor); bit_assign_func!(BitXorAssign, bitxor_assign, bitxor); } + +///Implement negation trait for Array +impl Neg for Array { + type Output = Array; + + fn neg(self) -> Self::Output { + constant_like(0.0, &self) - self + } +} From 10a20d1b9326c6551aa6e1265c2adf1f2b552bda Mon Sep 17 00:00:00 2001 From: pradeep Date: Sat, 17 Dec 2016 21:45:28 +0530 Subject: [PATCH 8/9] New fns to create arrays using Dim4 and DType params * constant_t * range_t * range_t * iota_t --- src/arith/mod.rs | 21 ++++++-- src/data/mod.rs | 135 +++++++++++++++++++++++++++++++++++++++++++---- src/defines.rs | 32 +++++++++++ src/lib.rs | 7 +-- 4 files changed, 178 insertions(+), 17 deletions(-) diff --git a/src/arith/mod.rs b/src/arith/mod.rs index 4e50aa40a..32e291dd9 100644 --- a/src/arith/mod.rs +++ b/src/arith/mod.rs @@ -3,14 +3,16 @@ extern crate num; use dim4::Dim4; use array::Array; -use defines::AfError; +use defines::{AfError, DType, Scalar}; use error::HANDLE_ERROR; use self::libc::{c_int}; -use data::{constant, constant_like, tile}; +use data::{constant, constant_t, tile}; use self::num::Complex; use std::ops::Neg; +type Complex32 = Complex; +type Complex64 = Complex; type MutAfArray = *mut self::libc::c_longlong; type MutDouble = *mut self::libc::c_double; type MutUint = *mut self::libc::c_uint; @@ -493,6 +495,19 @@ impl Neg for Array { type Output = Array; fn neg(self) -> Self::Output { - constant_like(0.0, &self) - self + match self.get_type() { + DType::S64 => (constant_t(Scalar::S64(0 as i64), self.dims(), DType::S64) - self), + DType::U64 => (constant_t(Scalar::U64(0 as u64), self.dims(), DType::U64) - self), + DType::C32 => (constant_t(Scalar::C32(Complex32::new(0.0, 0.0)), self.dims(), DType::C32) - self), + DType::C64 => (constant_t(Scalar::C64(Complex64::new(0.0, 0.0)), self.dims(), DType::C64) - self), + DType::F32 => (constant_t(Scalar::F32(0 as f32), self.dims(), DType::F32) - self), + DType::F64 => (constant_t(Scalar::F64(0 as f64), self.dims(), DType::F64) - self), + DType::B8 => (constant_t(Scalar::B8 (false ), self.dims(), DType::B8 ) - self), + DType::S32 => (constant_t(Scalar::S32(0 as i32), self.dims(), DType::S32) - self), + DType::U32 => (constant_t(Scalar::U32(0 as u32), self.dims(), DType::U32) - self), + DType::U8 => (constant_t(Scalar::U8 (0 as u8 ), self.dims(), DType::U8 ) - self), + DType::S16 => (constant_t(Scalar::S16(0 as i16), self.dims(), DType::S16) - self), + DType::U16 => (constant_t(Scalar::U16(0 as u16), self.dims(), DType::U16) - self), + } } } diff --git a/src/data/mod.rs b/src/data/mod.rs index ed6abd552..a85f0382a 100644 --- a/src/data/mod.rs +++ b/src/data/mod.rs @@ -3,7 +3,7 @@ extern crate num; use array::Array; use dim4::Dim4; -use defines::AfError; +use defines::{AfError, DType, Scalar}; use error::HANDLE_ERROR; use self::libc::{uint8_t, c_int, c_uint, c_double}; use self::num::Complex; @@ -623,24 +623,137 @@ pub fn replace_scalar(a: &mut Array, cond: &Array, b: f64) { } } -/// Create an array filled with given constant retaining type/shape of another Array. +/// Create a range of values of given type([DType](./enum.DType.html)) +/// +/// Creates an array with [0, n] values along the `seq_dim` which is tiled across other dimensions. +/// +/// # Parameters +/// +/// - `dims` is the size of Array +/// - `seq_dim` is the dimension along which range values are populated, all values along other +/// dimensions are just repeated +/// - `dtype` indicates whats the type of the Array to be created +/// +/// # Return Values +/// Array +#[allow(unused_mut)] +pub fn range_t(dims: Dim4, seq_dim: i32, dtype: DType) -> Array { + unsafe { + let mut temp: i64 = 0; + let err_val = af_range(&mut temp as MutAfArray, + dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT, + seq_dim as c_int, dtype as uint8_t); + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) + } +} + +/// Create a range of values of given type([DType](./enum.DType.html)) +/// +/// Create an sequence [0, dims.elements() - 1] and modify to specified dimensions dims and then tile it according to tile_dims. +/// +/// # Parameters +/// +/// - `dims` is the dimensions of the sequence to be generated +/// - `tdims` is the number of repitions of the unit dimensions +/// - `dtype` indicates whats the type of the Array to be created +/// +/// # Return Values +/// +/// Array +#[allow(unused_mut)] +pub fn iota_t(dims: Dim4, tdims: Dim4, dtype: DType) -> Array { + unsafe { + let mut temp: i64 = 0; + let err_val =af_iota(&mut temp as MutAfArray, + dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT, + tdims.ndims() as c_uint, tdims.get().as_ptr() as *const DimT, + dtype as uint8_t); + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) + } +} + +/// Create an identity array with 1's in diagonal of given type([DType](./enum.DType.html)) /// /// # Parameters /// -/// - `value` is the constant with which output Array is to be filled -/// - `input` is the Array whose shape the output Array has to maintain +/// - `dims` is the output Array dimensions +/// - `dtype` indicates whats the type of the Array to be created /// /// # Return Values /// -/// Array with given constant value and input Array's shape and similar internal data type. -pub fn constant_like(value: f64, input: &Array) -> Array { - let dims = input.dims(); +/// Identity matrix +#[allow(unused_mut)] +pub fn identity_t(dims: Dim4, dtype: DType) -> Array { + unsafe { + 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, + dtype as uint8_t); + HANDLE_ERROR(AfError::from(err_val)); + Array::from(temp) + } +} + +/// Create a constant array of given type([DType](./enum.DType.html)) +/// +/// You can use this function to create arrays of type dictated by the enum +/// [DType](./enum.DType.html) using the scalar `value` that has the shape similar +/// to `dims`. +/// +/// # Parameters +/// +/// - `value` is the [Scalar](./enum.Scalar.html) to be filled into the array +/// - `dims` is the output Array dimensions +/// - `dtype` indicates the type of Array to be created and is the type of the scalar to be passed +/// via the paramter `value`. +/// +/// # Return Values +/// +/// Array of `dims` shape and filed with given constant `value`. +#[allow(unused_mut)] +pub fn constant_t(value: Scalar, dims: Dim4, dtype: DType) -> Array { + use Scalar::*; + + // Below macro is only visible to this function + // and it is used to abbreviate the repetitive const calls + macro_rules! expand_const_call { + ($ffi_name: ident, $temp: expr, $v: expr, $dims: expr, $dt: expr) => ({ + $ffi_name(&mut $temp as MutAfArray, $v as c_double, + $dims.ndims() as c_uint, $dims.get().as_ptr() as *const DimT, $dt) + }) + } + unsafe { + let dt = dtype as c_int; let mut temp: i64 = 0; - let err_val = af_constant(&mut temp as MutAfArray, value as c_double, - dims.ndims() as c_uint, - dims.get().as_ptr() as *const DimT, - input.get_type() as c_int); + let err_val = match value { + C32(v) => { + af_constant_complex(&mut temp as MutAfArray, v.re as c_double, v.im as c_double, + dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT, dt) + }, + C64(v) => { + af_constant_complex(&mut temp as MutAfArray, v.re as c_double, v.im as c_double, + dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT, dt) + }, + S64(v) => { + af_constant_long(&mut temp as MutAfArray, v as Intl, + dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT) + }, + U64(v) => { + af_constant_ulong(&mut temp as MutAfArray, v as Uintl, + dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT) + }, + F32(v) => expand_const_call!(af_constant, temp, v, dims, dt), + F64(v) => expand_const_call!(af_constant, temp, v, dims, dt), + B8(v) => expand_const_call!(af_constant, temp, v as i32, dims, dt), + S32(v) => expand_const_call!(af_constant, temp, v, dims, dt), + U32(v) => expand_const_call!(af_constant, temp, v, dims, dt), + U8(v) => expand_const_call!(af_constant, temp, v, dims, dt), + S16(v) => expand_const_call!(af_constant, temp, v, dims, dt), + U16(v) => expand_const_call!(af_constant, temp, v, dims, dt), + }; HANDLE_ERROR(AfError::from(err_val)); Array::from(temp) } diff --git a/src/defines.rs b/src/defines.rs index e74337d3b..ab42c3be7 100644 --- a/src/defines.rs +++ b/src/defines.rs @@ -1,6 +1,9 @@ +extern crate num; + use std::error::Error; use std::fmt::{Display, Formatter}; use std::fmt::Error as FmtError; +use self::num::Complex; /// Error codes #[repr(C)] @@ -397,3 +400,32 @@ 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; + +/// Scalar value types +#[derive(Clone, Copy, Debug, PartialEq)] +pub enum Scalar { + /// 32 bit float + F32(f32), + /// 32 bit complex float + C32(Complex), + /// 64 bit float + F64(f64), + /// 64 bit complex float + C64(Complex), + /// 8 bit boolean + B8(bool), + /// 32 bit signed integer + S32(i32), + /// 32 bit unsigned integer + U32(u32), + /// 8 bit unsigned integer + U8(u8), + /// 64 bit signed integer + S64(i64), + /// 64 bit unsigned integer + U64(u64), + /// 16 bit signed integer + S16(i16), + /// 16 bit unsigned integer + U16(u16), +} diff --git a/src/lib.rs b/src/lib.rs index ae44f4ab6..23b2a78dc 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -32,11 +32,12 @@ mod backend; pub use blas::{matmul, dot, transpose, transpose_inplace}; mod blas; -pub use data::{constant, constant_like, range, iota}; -pub use data::{identity, diag_create, diag_extract, lower, upper}; +pub use data::{constant, range, iota, identity}; +pub use data::{diag_create, diag_extract, lower, upper}; pub use data::{join, join_many, tile}; pub use data::{reorder, shift, moddims, flat, flip}; pub use data::{select, selectl, selectr, replace, replace_scalar}; +pub use data::{range_t, iota_t, identity_t, constant_t}; mod data; pub use device::{get_version, info, init, device_count, is_double_available, set_device, get_device}; @@ -47,7 +48,7 @@ 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, RandomEngineType}; -pub use defines::{PHILOX, THREEFRY, MERSENNE, DEFAULT_RANDOM_ENGINE}; +pub use defines::{PHILOX, THREEFRY, MERSENNE, DEFAULT_RANDOM_ENGINE, Scalar}; mod defines; pub use dim4::Dim4; From 456a3354d4d29a38a0b528e5db59eee1f87e5d71 Mon Sep 17 00:00:00 2001 From: pradeep Date: Wed, 11 Jan 2017 11:40:37 +0530 Subject: [PATCH 9/9] Bump version to 3.4.1 for release --- Cargo.toml | 2 +- README.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ddbbc535f..f84eab929 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.4.0" +version = "3.4.1" documentation = "http://arrayfire.github.io/arrayfire-rust/arrayfire/index.html" homepage = "https://github.com/arrayfire/arrayfire" repository = "https://github.com/arrayfire/arrayfire-rust" diff --git a/README.md b/README.md index 87a1f4a6e..11c9b6afc 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.4 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.x 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.4.0"` to the dependencies section of your project's Cargo.toml file. +4. Add `arrayfire = "3.4.1"` to the dependencies section of your project's Cargo.toml file. Once step (4) is over, you should be able to use ArrayFire in your Rust project. If you find any bugs, please report them [here](https://github.com/arrayfire/arrayfire-rust/issues).