Skip to content

Commit f75a858

Browse files
authored
Merge pull request #96 from arrayfire/devel
v3.4.1 devel to master
2 parents da87964 + 456a335 commit f75a858

File tree

8 files changed

+329
-36
lines changed

8 files changed

+329
-36
lines changed

Cargo.toml

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "arrayfire"
33
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."
4-
version = "3.4.0"
4+
version = "3.4.1"
55
documentation = "http://arrayfire.github.io/arrayfire-rust/arrayfire/index.html"
66
homepage = "https://github.com/arrayfire/arrayfire"
77
repository = "https://github.com/arrayfire/arrayfire-rust"
@@ -46,3 +46,7 @@ path = "examples/snow.rs"
4646
[[example]]
4747
name = "histogram"
4848
path = "examples/histogram.rs"
49+
50+
[[example]]
51+
name = "acoustic_wave"
52+
path = "examples/acoustic_wave.rs"

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
|:-------:|:-------:|:---:|
44
| [![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/) |
55

6-
[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).
6+
[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).
77

88
## Documentation
99

@@ -30,7 +30,7 @@ first.
3030
3. Make sure you add the path to library files to your path environment variables.
3131
- On Linux & OSX: do `export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$AF_PATH/lib`
3232
- On Windows: Add `%AF_PATH%\lib` to your PATH environment variable.
33-
4. Add `arrayfire = "3.4.0"` to the dependencies section of your project's Cargo.toml file.
33+
4. Add `arrayfire = "3.4.1"` to the dependencies section of your project's Cargo.toml file.
3434

3535
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).
3636

examples/acoustic_wave.rs

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
extern crate arrayfire as af;
2+
3+
use af::*;
4+
use std::f64::consts::*;
5+
6+
fn main() {
7+
set_device(0);
8+
info();
9+
10+
acoustic_wave_simulation();
11+
}
12+
13+
fn normalise(a: &Array) -> Array {
14+
(a/(max_all(&abs(a)).0 as f32 * 2.0f32)) + 0.5f32
15+
}
16+
fn acoustic_wave_simulation() {
17+
// Speed of sound
18+
let c = 0.1;
19+
// Distance step
20+
let dx = 0.5;
21+
// Time step
22+
let dt = 1.0;
23+
24+
// Grid size.
25+
let nx = 1500;
26+
let ny = 1500;
27+
28+
// Grid dimensions.
29+
let dims = Dim4::new(&[nx, ny, 1, 1]);
30+
31+
// Pressure field
32+
let mut p = constant::<f32>(0.0, dims);
33+
// d(pressure)/dt field
34+
let mut p_dot = p.clone();
35+
36+
// Laplacian (Del^2) convolution kernel.
37+
let laplacian_values = [0.0f32, 1.0, 0.0,
38+
1.0, -4.0, 1.0,
39+
0.0, 1.0, 0.0];
40+
let laplacian_kernel = Array::new(&laplacian_values, Dim4::new(&[3, 3, 1, 1])) / (dx * dx);
41+
42+
// Create a window to show the waves.
43+
let mut win = Window::new(1000, 1000, "Waves".to_string());
44+
45+
// Hann windowed pulse.
46+
let pulse_time = 100.0f64;
47+
let centre_freq = 0.05;
48+
49+
// Number of samples in pulse.
50+
let pulse_n = (pulse_time/dt).floor() as u64;
51+
52+
let i = range::<f32>(Dim4::new(&[pulse_n, 1, 1, 1]), 0);
53+
let t = i.clone() * dt;
54+
let hamming_window = cos(&(i * (2.0 * PI / pulse_n as f64))) * -0.46 + 0.54;
55+
let wave = sin(&(&t * centre_freq * 2.0 * PI));
56+
let pulse = wave * hamming_window;
57+
58+
// Iteration count.
59+
let mut it = 0;
60+
61+
while !win.is_closed() {
62+
// Convole with laplacian to get spacial second derivative.
63+
let lap_p = convolve2(&p, &laplacian_kernel, ConvMode::DEFAULT, ConvDomain::SPATIAL);
64+
// Calculate the updated pressure and d(pressure)/dt fields.
65+
p_dot += lap_p * (c * dt);
66+
p += &p_dot * dt;
67+
68+
if it < pulse_n {
69+
// Location of the source.
70+
let seqs = &[Seq::new(700.0, 800.0, 1.0), Seq::new(800.0, 800.0, 1.0)];
71+
// Set the pressure there.
72+
p = assign_seq(&p, seqs, &index(&pulse, &[Seq::new(it as f64, it as f64, 1.0)]));
73+
}
74+
75+
// Draw the image.
76+
win.set_colormap(af::ColorMap::BLUE);
77+
win.draw_image(&normalise(&p), None);
78+
79+
it += 1;
80+
}
81+
}

src/arith/mod.rs

+28-2
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@ extern crate num;
33

44
use dim4::Dim4;
55
use array::Array;
6-
use defines::AfError;
6+
use defines::{AfError, DType, Scalar};
77
use error::HANDLE_ERROR;
88
use self::libc::{c_int};
9-
use data::{constant, tile};
9+
use data::{constant, constant_t, tile};
1010
use self::num::Complex;
1111

12+
use std::ops::Neg;
13+
14+
type Complex32 = Complex<f32>;
15+
type Complex64 = Complex<f64>;
1216
type MutAfArray = *mut self::libc::c_longlong;
1317
type MutDouble = *mut self::libc::c_double;
1418
type MutUint = *mut self::libc::c_uint;
@@ -485,3 +489,25 @@ bit_assign_func!(BitOrAssign, bitor_assign, bitor);
485489
bit_assign_func!(BitXorAssign, bitxor_assign, bitxor);
486490

487491
}
492+
493+
///Implement negation trait for Array
494+
impl Neg for Array {
495+
type Output = Array;
496+
497+
fn neg(self) -> Self::Output {
498+
match self.get_type() {
499+
DType::S64 => (constant_t(Scalar::S64(0 as i64), self.dims(), DType::S64) - self),
500+
DType::U64 => (constant_t(Scalar::U64(0 as u64), self.dims(), DType::U64) - self),
501+
DType::C32 => (constant_t(Scalar::C32(Complex32::new(0.0, 0.0)), self.dims(), DType::C32) - self),
502+
DType::C64 => (constant_t(Scalar::C64(Complex64::new(0.0, 0.0)), self.dims(), DType::C64) - self),
503+
DType::F32 => (constant_t(Scalar::F32(0 as f32), self.dims(), DType::F32) - self),
504+
DType::F64 => (constant_t(Scalar::F64(0 as f64), self.dims(), DType::F64) - self),
505+
DType::B8 => (constant_t(Scalar::B8 (false ), self.dims(), DType::B8 ) - self),
506+
DType::S32 => (constant_t(Scalar::S32(0 as i32), self.dims(), DType::S32) - self),
507+
DType::U32 => (constant_t(Scalar::U32(0 as u32), self.dims(), DType::U32) - self),
508+
DType::U8 => (constant_t(Scalar::U8 (0 as u8 ), self.dims(), DType::U8 ) - self),
509+
DType::S16 => (constant_t(Scalar::S16(0 as i16), self.dims(), DType::S16) - self),
510+
DType::U16 => (constant_t(Scalar::U16(0 as u16), self.dims(), DType::U16) - self),
511+
}
512+
}
513+
}

src/data/mod.rs

+137-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ extern crate num;
33

44
use array::Array;
55
use dim4::Dim4;
6-
use defines::AfError;
6+
use defines::{AfError, DType, Scalar};
77
use error::HANDLE_ERROR;
88
use self::libc::{uint8_t, c_int, c_uint, c_double};
99
use self::num::Complex;
@@ -622,3 +622,139 @@ pub fn replace_scalar(a: &mut Array, cond: &Array, b: f64) {
622622
HANDLE_ERROR(AfError::from(err_val));
623623
}
624624
}
625+
626+
/// Create a range of values of given type([DType](./enum.DType.html))
627+
///
628+
/// Creates an array with [0, n] values along the `seq_dim` which is tiled across other dimensions.
629+
///
630+
/// # Parameters
631+
///
632+
/// - `dims` is the size of Array
633+
/// - `seq_dim` is the dimension along which range values are populated, all values along other
634+
/// dimensions are just repeated
635+
/// - `dtype` indicates whats the type of the Array to be created
636+
///
637+
/// # Return Values
638+
/// Array
639+
#[allow(unused_mut)]
640+
pub fn range_t(dims: Dim4, seq_dim: i32, dtype: DType) -> Array {
641+
unsafe {
642+
let mut temp: i64 = 0;
643+
let err_val = af_range(&mut temp as MutAfArray,
644+
dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT,
645+
seq_dim as c_int, dtype as uint8_t);
646+
HANDLE_ERROR(AfError::from(err_val));
647+
Array::from(temp)
648+
}
649+
}
650+
651+
/// Create a range of values of given type([DType](./enum.DType.html))
652+
///
653+
/// Create an sequence [0, dims.elements() - 1] and modify to specified dimensions dims and then tile it according to tile_dims.
654+
///
655+
/// # Parameters
656+
///
657+
/// - `dims` is the dimensions of the sequence to be generated
658+
/// - `tdims` is the number of repitions of the unit dimensions
659+
/// - `dtype` indicates whats the type of the Array to be created
660+
///
661+
/// # Return Values
662+
///
663+
/// Array
664+
#[allow(unused_mut)]
665+
pub fn iota_t(dims: Dim4, tdims: Dim4, dtype: DType) -> Array {
666+
unsafe {
667+
let mut temp: i64 = 0;
668+
let err_val =af_iota(&mut temp as MutAfArray,
669+
dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT,
670+
tdims.ndims() as c_uint, tdims.get().as_ptr() as *const DimT,
671+
dtype as uint8_t);
672+
HANDLE_ERROR(AfError::from(err_val));
673+
Array::from(temp)
674+
}
675+
}
676+
677+
/// Create an identity array with 1's in diagonal of given type([DType](./enum.DType.html))
678+
///
679+
/// # Parameters
680+
///
681+
/// - `dims` is the output Array dimensions
682+
/// - `dtype` indicates whats the type of the Array to be created
683+
///
684+
/// # Return Values
685+
///
686+
/// Identity matrix
687+
#[allow(unused_mut)]
688+
pub fn identity_t(dims: Dim4, dtype: DType) -> Array {
689+
unsafe {
690+
let mut temp: i64 = 0;
691+
let err_val = af_identity(&mut temp as MutAfArray,
692+
dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT,
693+
dtype as uint8_t);
694+
HANDLE_ERROR(AfError::from(err_val));
695+
Array::from(temp)
696+
}
697+
}
698+
699+
/// Create a constant array of given type([DType](./enum.DType.html))
700+
///
701+
/// You can use this function to create arrays of type dictated by the enum
702+
/// [DType](./enum.DType.html) using the scalar `value` that has the shape similar
703+
/// to `dims`.
704+
///
705+
/// # Parameters
706+
///
707+
/// - `value` is the [Scalar](./enum.Scalar.html) to be filled into the array
708+
/// - `dims` is the output Array dimensions
709+
/// - `dtype` indicates the type of Array to be created and is the type of the scalar to be passed
710+
/// via the paramter `value`.
711+
///
712+
/// # Return Values
713+
///
714+
/// Array of `dims` shape and filed with given constant `value`.
715+
#[allow(unused_mut)]
716+
pub fn constant_t(value: Scalar, dims: Dim4, dtype: DType) -> Array {
717+
use Scalar::*;
718+
719+
// Below macro is only visible to this function
720+
// and it is used to abbreviate the repetitive const calls
721+
macro_rules! expand_const_call {
722+
($ffi_name: ident, $temp: expr, $v: expr, $dims: expr, $dt: expr) => ({
723+
$ffi_name(&mut $temp as MutAfArray, $v as c_double,
724+
$dims.ndims() as c_uint, $dims.get().as_ptr() as *const DimT, $dt)
725+
})
726+
}
727+
728+
unsafe {
729+
let dt = dtype as c_int;
730+
let mut temp: i64 = 0;
731+
let err_val = match value {
732+
C32(v) => {
733+
af_constant_complex(&mut temp as MutAfArray, v.re as c_double, v.im as c_double,
734+
dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT, dt)
735+
},
736+
C64(v) => {
737+
af_constant_complex(&mut temp as MutAfArray, v.re as c_double, v.im as c_double,
738+
dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT, dt)
739+
},
740+
S64(v) => {
741+
af_constant_long(&mut temp as MutAfArray, v as Intl,
742+
dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT)
743+
},
744+
U64(v) => {
745+
af_constant_ulong(&mut temp as MutAfArray, v as Uintl,
746+
dims.ndims() as c_uint, dims.get().as_ptr() as *const DimT)
747+
},
748+
F32(v) => expand_const_call!(af_constant, temp, v, dims, dt),
749+
F64(v) => expand_const_call!(af_constant, temp, v, dims, dt),
750+
B8(v) => expand_const_call!(af_constant, temp, v as i32, dims, dt),
751+
S32(v) => expand_const_call!(af_constant, temp, v, dims, dt),
752+
U32(v) => expand_const_call!(af_constant, temp, v, dims, dt),
753+
U8(v) => expand_const_call!(af_constant, temp, v, dims, dt),
754+
S16(v) => expand_const_call!(af_constant, temp, v, dims, dt),
755+
U16(v) => expand_const_call!(af_constant, temp, v, dims, dt),
756+
};
757+
HANDLE_ERROR(AfError::from(err_val));
758+
Array::from(temp)
759+
}
760+
}

src/defines.rs

+32
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
extern crate num;
2+
13
use std::error::Error;
24
use std::fmt::{Display, Formatter};
35
use std::fmt::Error as FmtError;
6+
use self::num::Complex;
47

58
/// Error codes
69
#[repr(C)]
@@ -397,3 +400,32 @@ pub const PHILOX : RandomEngineType = RandomEngineType::PHILOX_4X32_10;
397400
pub const THREEFRY : RandomEngineType = RandomEngineType::THREEFRY_2X32_16;
398401
pub const MERSENNE : RandomEngineType = RandomEngineType::MERSENNE_GP11213;
399402
pub const DEFAULT_RANDOM_ENGINE : RandomEngineType = PHILOX;
403+
404+
/// Scalar value types
405+
#[derive(Clone, Copy, Debug, PartialEq)]
406+
pub enum Scalar {
407+
/// 32 bit float
408+
F32(f32),
409+
/// 32 bit complex float
410+
C32(Complex<f32>),
411+
/// 64 bit float
412+
F64(f64),
413+
/// 64 bit complex float
414+
C64(Complex<f64>),
415+
/// 8 bit boolean
416+
B8(bool),
417+
/// 32 bit signed integer
418+
S32(i32),
419+
/// 32 bit unsigned integer
420+
U32(u32),
421+
/// 8 bit unsigned integer
422+
U8(u8),
423+
/// 64 bit signed integer
424+
S64(i64),
425+
/// 64 bit unsigned integer
426+
U64(u64),
427+
/// 16 bit signed integer
428+
S16(i16),
429+
/// 16 bit unsigned integer
430+
U16(u16),
431+
}

0 commit comments

Comments
 (0)