From 80651c9ae2c5b442ae5fc8b0a56e44c14c48a7bf Mon Sep 17 00:00:00 2001 From: Theodore DeRego Date: Wed, 24 Feb 2016 11:05:20 -1000 Subject: [PATCH 1/3] Make Seq generic and make use of generic Seq in helloworld example --- examples/helloworld.rs | 4 ++-- src/index.rs | 52 +++++++++++++++++++++++++++++++----------- src/lib.rs | 2 ++ src/seq.rs | 34 +++++++++++++-------------- 4 files changed, 60 insertions(+), 32 deletions(-) diff --git a/examples/helloworld.rs b/examples/helloworld.rs index 6ed726019..356d3986c 100644 --- a/examples/helloworld.rs +++ b/examples/helloworld.rs @@ -42,12 +42,12 @@ fn main() { println!("a + b"); print(&test); // Index array using sequences - let seqs = &[Seq::new(1.0, 3.0, 1.0), Seq::default()]; + let seqs = &[Seq::new(1u32, 3, 1), Seq::default()]; let sub = index(&a, seqs).unwrap(); println!("a(seq(1,3,1), span)"); print(&sub); //Index array using array and sequence - let seq4gen = Seq::new(0.0, 2.0, 1.0); + let seq4gen = Seq::new(0u32, 2, 1); let mut idxrs = match Indexer::new() { Ok(v) => v, diff --git a/src/index.rs b/src/index.rs index c782b32a2..2aca11327 100644 --- a/src/index.rs +++ b/src/index.rs @@ -3,7 +3,7 @@ extern crate libc; use array::Array; use defines::AfError; use seq::Seq; -use self::libc::{c_int, c_uint, c_longlong}; +use self::libc::{c_double, c_int, c_uint}; type MutAfIndex = *mut self::libc::c_longlong; type MutAfArray = *mut self::libc::c_longlong; @@ -15,12 +15,12 @@ type IndexT = self::libc::c_longlong; extern { fn af_create_indexers(indexers: MutAfIndex) -> c_int; fn af_set_array_indexer(indexer: MutAfIndex, idx: AfArray, dim: DimT) -> c_int; - fn af_set_seq_indexer(indexer: MutAfIndex, idx: *const Seq, dim: DimT, is_batch: c_int) -> c_int; + fn af_set_seq_indexer(indexer: MutAfIndex, idx: *const SeqInternal, dim: DimT, is_batch: c_int) -> c_int; fn af_release_indexers(indexers: MutAfIndex) -> c_int; - fn af_index(out: MutAfArray, input: AfArray, ndims: c_uint, index: *const Seq) -> c_int; + fn af_index(out: MutAfArray, input: AfArray, ndims: c_uint, index: *const SeqInternal) -> c_int; fn af_lookup(out: MutAfArray, arr: AfArray, indices: AfArray, dim: c_uint) -> c_int; - fn af_assign_seq(out: MutAfArray, lhs: AfArray, ndims: c_uint, indices: *const Seq, rhs: AfArray) -> c_int; + fn af_assign_seq(out: MutAfArray, lhs: AfArray, ndims: c_uint, indices: *const SeqInternal, rhs: AfArray) -> c_int; fn af_index_gen(out: MutAfArray, input: AfArray, ndims: DimT, indices: *const IndexT) -> c_int; fn af_assign_gen(out: MutAfArray, lhs: AfArray, ndims: DimT, indices: *const IndexT, rhs: AfArray) -> c_int; } @@ -62,11 +62,12 @@ impl Indexable for Array { /// /// This is used in functions [index_gen](./fn.index_gen.html) and /// [assign_gen](./fn.assign_gen.html) -impl Indexable for Seq { +impl Indexable for Seq where c_double: From { fn set(&self, idxr: &Indexer, dim: u32, is_batch: Option) -> Result<(), AfError> { unsafe { - let err_val = af_set_seq_indexer(idxr.clone().get() as MutAfIndex, self as *const Seq, - dim as DimT, is_batch.unwrap() as c_int); + let err_val = af_set_seq_indexer(idxr.clone().get() as MutAfIndex, + &SeqInternal::from_seq(self) as *const SeqInternal, + dim as DimT, is_batch.unwrap() as c_int); match err_val { 0 => Ok(()), _ => Err(AfError::from(err_val)), @@ -130,12 +131,16 @@ impl Drop for Indexer { /// println!("a(seq(1, 3, 1), span)"); /// print(&sub); /// ``` -pub fn index(input: &Array, seqs: &[Seq]) -> Result { +pub fn index(input: &Array, seqs: &[Seq]) -> Result + where c_double: From +{ unsafe { let mut temp: i64 = 0; + // TODO: allocating a whole new array on the heap just for this is BAD + let seqs: Vec = seqs.iter().map(|s| SeqInternal::from_seq(s)).collect(); let err_val = af_index(&mut temp as MutAfArray , input.get() as AfArray, seqs.len() as u32 - , seqs.as_ptr() as *const Seq); + , seqs.as_ptr() as *const SeqInternal); match err_val { 0 => Ok(Array::from(temp)), _ => Err(AfError::from(err_val)), @@ -155,8 +160,8 @@ pub fn index(input: &Array, seqs: &[Seq]) -> Result { /// ``` #[allow(dead_code)] pub fn row(input: &Array, row_num: u64) -> Result { - index(input, &[Seq::new(row_num as f64, row_num as f64, 1.0) - , Seq::default()]) + index(input, &[Seq::new(row_num as f64, row_num as f64, 1.0), + Seq::default()]) } #[allow(dead_code)] @@ -300,11 +305,15 @@ pub fn lookup(input: &Array, indices: &Array, seq_dim: i32) -> Result Result { +pub fn assign_seq(lhs: &Array, seqs: &[Seq], rhs: &Array) -> Result + where c_double: From +{ unsafe{ let mut temp: i64 = 0; + // TODO: allocating a whole new array on the heap just for this is BAD + let seqs: Vec = seqs.iter().map(|s| SeqInternal::from_seq(s)).collect(); let err_val = af_assign_seq(&mut temp as MutAfArray, lhs.get() as AfArray, - seqs.len() as c_uint, seqs.as_ptr() as *const Seq, + seqs.len() as c_uint, seqs.as_ptr() as *const SeqInternal, rhs.get() as AfArray); match err_val { 0 => Ok(Array::from(temp)), @@ -402,3 +411,20 @@ pub fn assign_gen(lhs: &Array, indices: &Indexer, rhs: &Array) -> Result(s: &Seq) -> Self where c_double: From { + SeqInternal { + begin: From::from(s.begin()), + end: From::from(s.end()), + step: From::from(s.step()), + } + } +} diff --git a/src/lib.rs b/src/lib.rs index a09af0e1c..4a87d996f 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,5 @@ +#![feature(zero_one)] + #![doc(html_logo_url = "http://www.arrayfire.com/logos/arrayfire_logo_symbol.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://arrayfire.com/docs/rust")] diff --git a/src/seq.rs b/src/seq.rs index ae0a43b96..c09aa0245 100644 --- a/src/seq.rs +++ b/src/seq.rs @@ -2,49 +2,49 @@ extern crate libc; use std::fmt; use std::default::Default; -use self::libc::{c_double}; +use std::num::{One, Zero}; /// Sequences are used for indexing Arrays #[derive(Copy, Clone)] #[repr(C)] -pub struct Seq { - begin: c_double, - end: c_double, - step: c_double, +pub struct Seq { + begin: T, + end: T, + step: T, } /// Default `Seq` spans all the elements along a dimension -impl Default for Seq { - fn default() -> Seq { - Seq { begin: 1.0, end: 1.0, step: 0.0, } +impl Default for Seq { + fn default() -> Self { + Seq { begin: One::one(), end: One::one(), step: Zero::zero() } } } /// Enables use of `Seq` with `{}` format in print statements -impl fmt::Display for Seq { +impl fmt::Display for Seq { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "[begin: {}, end: {}, step: {}]", self.begin, self.end, self.step) } } -impl Seq { +impl Seq { /// Create a `Seq` that goes from `begin` to `end` at a step size of `step` - pub fn new(begin: f64, end: f64, step: f64) -> Seq { + pub fn new(begin: T, end: T, step: T) -> Self { Seq { begin: begin, end: end, step: step, } } /// Get begin index of Seq - pub fn begin(&self) -> f64 { - self.begin as f64 + pub fn begin(&self) -> T { + self.begin } /// Get begin index of Seq - pub fn end(&self) -> f64 { - self.end as f64 + pub fn end(&self) -> T { + self.end } /// Get step size of Seq - pub fn step(&self) -> f64 { - self.step as f64 + pub fn step(&self) -> T { + self.step } } From ab618ad20f4ee9bbb21865891cbe497a0f312eed Mon Sep 17 00:00:00 2001 From: Theodore DeRego Date: Thu, 25 Feb 2016 10:13:25 -1000 Subject: [PATCH 2/3] Made our own One+Zero traits so we can use stable rust --- src/lib.rs | 3 +-- src/num.rs | 33 +++++++++++++++++++++++++++++++++ src/seq.rs | 3 ++- 3 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 src/num.rs diff --git a/src/lib.rs b/src/lib.rs index 4a87d996f..09d7a5b1e 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,3 @@ -#![feature(zero_one)] - #![doc(html_logo_url = "http://www.arrayfire.com/logos/arrayfire_logo_symbol.png", html_favicon_url = "http://www.rust-lang.org/favicon.ico", html_root_url = "http://arrayfire.com/docs/rust")] @@ -73,6 +71,7 @@ mod image; pub use lapack::{svd, lu, qr, cholesky, solve, solve_lu, inverse, det, rank, norm}; pub use lapack::{svd_inplace, lu_inplace, qr_inplace, cholesky_inplace}; mod lapack; +mod num; pub use signal::{approx1, approx2}; pub use signal::{fft, fft2, fft3, ifft, ifft2, ifft3}; diff --git a/src/num.rs b/src/num.rs new file mode 100644 index 000000000..4214d9d5e --- /dev/null +++ b/src/num.rs @@ -0,0 +1,33 @@ +pub trait Zero { + fn zero() -> Self; +} + +pub trait One { + fn one() -> Self; +} + +impl Zero for u8 { fn zero() -> Self { 0 } } +impl Zero for u16 { fn zero() -> Self { 0 } } +impl Zero for u32 { fn zero() -> Self { 0 } } +impl Zero for u64 { fn zero() -> Self { 0 } } +impl Zero for usize { fn zero() -> Self { 0 } } +impl Zero for i8 { fn zero() -> Self { 0 } } +impl Zero for i16 { fn zero() -> Self { 0 } } +impl Zero for i32 { fn zero() -> Self { 0 } } +impl Zero for i64 { fn zero() -> Self { 0 } } +impl Zero for isize { fn zero() -> Self { 0 } } +impl Zero for f32 { fn zero() -> Self { 0.0 } } +impl Zero for f64 { fn zero() -> Self { 0.0 } } + +impl One for u8 { fn one() -> Self { 1 } } +impl One for u16 { fn one() -> Self { 1 } } +impl One for u32 { fn one() -> Self { 1 } } +impl One for u64 { fn one() -> Self { 1 } } +impl One for usize { fn one() -> Self { 1 } } +impl One for i8 { fn one() -> Self { 1 } } +impl One for i16 { fn one() -> Self { 1 } } +impl One for i32 { fn one() -> Self { 1 } } +impl One for i64 { fn one() -> Self { 1 } } +impl One for isize { fn one() -> Self { 1 } } +impl One for f32 { fn one() -> Self { 1.0 } } +impl One for f64 { fn one() -> Self { 1.0 } } diff --git a/src/seq.rs b/src/seq.rs index c09aa0245..a56410362 100644 --- a/src/seq.rs +++ b/src/seq.rs @@ -2,7 +2,8 @@ extern crate libc; use std::fmt; use std::default::Default; -use std::num::{One, Zero}; + +use num::{One, Zero}; /// Sequences are used for indexing Arrays #[derive(Copy, Clone)] From 70fcd0f752afe03149a8980adc88a3b834d70df5 Mon Sep 17 00:00:00 2001 From: Theodore DeRego Date: Thu, 25 Feb 2016 14:44:36 -1000 Subject: [PATCH 3/3] Macro-ify Zero and One trait impls --- src/num.rs | 61 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/src/num.rs b/src/num.rs index 4214d9d5e..d5858d486 100644 --- a/src/num.rs +++ b/src/num.rs @@ -6,28 +6,41 @@ pub trait One { fn one() -> Self; } -impl Zero for u8 { fn zero() -> Self { 0 } } -impl Zero for u16 { fn zero() -> Self { 0 } } -impl Zero for u32 { fn zero() -> Self { 0 } } -impl Zero for u64 { fn zero() -> Self { 0 } } -impl Zero for usize { fn zero() -> Self { 0 } } -impl Zero for i8 { fn zero() -> Self { 0 } } -impl Zero for i16 { fn zero() -> Self { 0 } } -impl Zero for i32 { fn zero() -> Self { 0 } } -impl Zero for i64 { fn zero() -> Self { 0 } } -impl Zero for isize { fn zero() -> Self { 0 } } -impl Zero for f32 { fn zero() -> Self { 0.0 } } -impl Zero for f64 { fn zero() -> Self { 0.0 } } +macro_rules! zero_impl { + ( $t:ident, $z:expr ) => ( + impl Zero for $t { fn zero() -> Self { $z } } + ) +} + +zero_impl!(u8, 0); +zero_impl!(u16, 0); +zero_impl!(u32, 0); +zero_impl!(u64, 0); +zero_impl!(usize, 0); +zero_impl!(i8, 0); +zero_impl!(i16, 0); +zero_impl!(i32, 0); +zero_impl!(i64, 0); +zero_impl!(isize, 0); +zero_impl!(f32, 0.0); +zero_impl!(f64, 0.0); + + +macro_rules! one_impl { + ( $t:ident, $o:expr ) => ( + impl One for $t { fn one() -> Self { $o } } + ) +} -impl One for u8 { fn one() -> Self { 1 } } -impl One for u16 { fn one() -> Self { 1 } } -impl One for u32 { fn one() -> Self { 1 } } -impl One for u64 { fn one() -> Self { 1 } } -impl One for usize { fn one() -> Self { 1 } } -impl One for i8 { fn one() -> Self { 1 } } -impl One for i16 { fn one() -> Self { 1 } } -impl One for i32 { fn one() -> Self { 1 } } -impl One for i64 { fn one() -> Self { 1 } } -impl One for isize { fn one() -> Self { 1 } } -impl One for f32 { fn one() -> Self { 1.0 } } -impl One for f64 { fn one() -> Self { 1.0 } } +one_impl!(u8, 1); +one_impl!(u16, 1); +one_impl!(u32, 1); +one_impl!(u64, 1); +one_impl!(usize, 1); +one_impl!(i8, 1); +one_impl!(i16, 1); +one_impl!(i32, 1); +one_impl!(i64, 1); +one_impl!(isize, 1); +one_impl!(f32, 1.0); +one_impl!(f64, 1.0);