Skip to content

v3.4.1 devel to master #96

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Jan 11, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -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"
Expand Down Expand Up @@ -46,3 +46,7 @@ path = "examples/snow.rs"
[[example]]
name = "histogram"
path = "examples/histogram.rs"

[[example]]
name = "acoustic_wave"
path = "examples/acoustic_wave.rs"
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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).

Expand Down
81 changes: 81 additions & 0 deletions examples/acoustic_wave.rs
Original file line number Diff line number Diff line change
@@ -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::<f32>(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::<f32>(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;
}
}
30 changes: 28 additions & 2 deletions src/arith/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +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, tile};
use data::{constant, constant_t, tile};
use self::num::Complex;

use std::ops::Neg;

type Complex32 = Complex<f32>;
type Complex64 = Complex<f64>;
type MutAfArray = *mut self::libc::c_longlong;
type MutDouble = *mut self::libc::c_double;
type MutUint = *mut self::libc::c_uint;
Expand Down Expand Up @@ -485,3 +489,25 @@ 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 {
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),
}
}
}
138 changes: 137 additions & 1 deletion src/data/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -622,3 +622,139 @@ pub fn replace_scalar(a: &mut Array, cond: &Array, b: f64) {
HANDLE_ERROR(AfError::from(err_val));
}
}

/// 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
///
/// - `dims` is the output Array dimensions
/// - `dtype` indicates whats the type of the Array to be created
///
/// # Return Values
///
/// 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 = 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)
}
}
32 changes: 32 additions & 0 deletions src/defines.rs
Original file line number Diff line number Diff line change
@@ -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)]
Expand Down Expand Up @@ -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<f32>),
/// 64 bit float
F64(f64),
/// 64 bit complex float
C64(Complex<f64>),
/// 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),
}
Loading