Skip to content

Make Seq generic #57

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 3 commits into from
Feb 26, 2016
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
4 changes: 2 additions & 2 deletions examples/helloworld.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
52 changes: 39 additions & 13 deletions src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}
Expand Down Expand Up @@ -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<T: Copy> Indexable for Seq<T> where c_double: From<T> {
fn set(&self, idxr: &Indexer, dim: u32, is_batch: Option<bool>) -> 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)),
Expand Down Expand Up @@ -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<Array, AfError> {
pub fn index<T: Copy>(input: &Array, seqs: &[Seq<T>]) -> Result<Array, AfError>
where c_double: From<T>
{
unsafe {
let mut temp: i64 = 0;
// TODO: allocating a whole new array on the heap just for this is BAD
let seqs: Vec<SeqInternal> = 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)),
Expand All @@ -155,8 +160,8 @@ pub fn index(input: &Array, seqs: &[Seq]) -> Result<Array, AfError> {
/// ```
#[allow(dead_code)]
pub fn row(input: &Array, row_num: u64) -> Result<Array, AfError> {
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)]
Expand Down Expand Up @@ -300,11 +305,15 @@ pub fn lookup(input: &Array, indices: &Array, seq_dim: i32) -> Result<Array, AfE
/// // 1.0 1.0 1.0
/// // 2.0 2.0 2.0
/// ```
pub fn assign_seq(lhs: &Array, seqs: &[Seq], rhs: &Array) -> Result<Array, AfError> {
pub fn assign_seq<T: Copy>(lhs: &Array, seqs: &[Seq<T>], rhs: &Array) -> Result<Array, AfError>
where c_double: From<T>
{
unsafe{
let mut temp: i64 = 0;
// TODO: allocating a whole new array on the heap just for this is BAD
let seqs: Vec<SeqInternal> = 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)),
Expand Down Expand Up @@ -402,3 +411,20 @@ pub fn assign_gen(lhs: &Array, indices: &Indexer, rhs: &Array) -> Result<Array,
}
}
}

#[repr(C)]
struct SeqInternal {
begin: c_double,
end: c_double,
step: c_double,
}

impl SeqInternal {
fn from_seq<T: Copy>(s: &Seq<T>) -> Self where c_double: From<T> {
SeqInternal {
begin: From::from(s.begin()),
end: From::from(s.end()),
step: From::from(s.step()),
}
}
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,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};
Expand Down
46 changes: 46 additions & 0 deletions src/num.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
pub trait Zero {
fn zero() -> Self;
}

pub trait One {
fn one() -> Self;
}

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 } }
)
}

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);
35 changes: 18 additions & 17 deletions src/seq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,49 +2,50 @@ extern crate libc;

use std::fmt;
use std::default::Default;
use self::libc::{c_double};

use num::{One, Zero};

/// Sequences are used for indexing Arrays
#[derive(Copy, Clone)]
#[repr(C)]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you even need this anymore necessarily?

pub struct Seq {
begin: c_double,
end: c_double,
step: c_double,
pub struct Seq<T> {
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<T: One+Zero> Default for Seq<T> {
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<T: fmt::Display> fmt::Display for Seq<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[begin: {}, end: {}, step: {}]", self.begin, self.end, self.step)
}
}

impl Seq {
impl<T: Copy> Seq<T> {
/// 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
}
}