extern crate libc;
use array::Array;
use defines::AfError;
use error::HANDLE_ERROR;
use seq::Seq;
use self::libc::{c_double, c_int, c_uint};
use util::{AfArray, AfIndex, DimT, HasAfEnum, MutAfArray, MutAfIndex};
use std::marker::PhantomData;
#[allow(dead_code)]
extern {
fn af_create_indexers(indexers: MutAfIndex) -> c_int;
fn af_set_array_indexer(indexer: AfIndex, idx: AfArray, dim: DimT) -> c_int;
fn af_set_seq_indexer(indexer: AfIndex, idx: *const SeqInternal, dim: DimT, is_batch: c_int) -> c_int;
fn af_release_indexers(indexers: AfIndex) -> 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 SeqInternal, rhs: AfArray) -> c_int;
fn af_index_gen(out: MutAfArray, input: AfArray, ndims: DimT, indices: AfIndex) -> c_int;
fn af_assign_gen(out: MutAfArray, lhs: AfArray, ndims: DimT, indices: AfIndex, rhs: AfArray) -> c_int;
}
pub struct Indexer<'object> {
handle: i64,
count: usize,
marker: PhantomData<&'object ()>,
}
pub trait Indexable {
fn set(&self, idxr: &mut Indexer, dim: u32, is_batch: Option<bool>);
}
impl<T: HasAfEnum> Indexable for Array<T> {
#[allow(unused_variables)]
fn set(&self, idxr: &mut Indexer, dim: u32, is_batch: Option<bool>) {
unsafe {
let err_val = af_set_array_indexer(idxr.get() as AfIndex, self.get() as AfArray,
dim as DimT);
HANDLE_ERROR(AfError::from(err_val));
}
}
}
impl<T: Copy> Indexable for Seq<T> where c_double: From<T> {
fn set(&self, idxr: &mut Indexer, dim: u32, is_batch: Option<bool>) {
unsafe {
let err_val = af_set_seq_indexer(idxr.get() as AfIndex,
&SeqInternal::from_seq(self) as *const SeqInternal,
dim as DimT, is_batch.unwrap() as c_int);
HANDLE_ERROR(AfError::from(err_val));
}
}
}
impl<'object> Indexer<'object> {
#[allow(unused_mut)]
pub fn new() -> Indexer<'object> {
let mut temp: i64 = 0;
unsafe {
let err_val = af_create_indexers(&mut temp as MutAfIndex);
HANDLE_ERROR(AfError::from(err_val));
}
Indexer{handle: temp, count: 0, marker: PhantomData}
}
pub fn set_index<'s, T>(&'s mut self, idx: &'object T, dim: u32, is_batch: Option<bool>)
where T : Indexable + 'object {
idx.set(self, dim, is_batch);
self.count = self.count+1;
}
pub fn len(&self) -> usize {
self.count
}
pub fn get(&self) -> i64 {
self.handle
}
}
impl<'object> Drop for Indexer<'object> {
fn drop(&mut self) {
unsafe {
let ret_val = af_release_indexers(self.handle as AfIndex);
match ret_val {
0 => (),
_ => panic!("Failed to release indexers resource: {}", ret_val),
}
}
}
}
pub fn index<IO, T: Copy>(input: &Array<IO>, seqs: &[Seq<T>]) -> Array<IO>
where c_double: From<T>, IO: HasAfEnum
{
let mut temp: i64 = 0;
unsafe {
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 SeqInternal);
HANDLE_ERROR(AfError::from(err_val));
}
temp.into()
}
#[allow(dead_code)]
pub fn row<T>(input: &Array<T>, row_num: u64) -> Array<T>
where T: HasAfEnum
{
index(input, &[Seq::new(row_num as f64, row_num as f64, 1.0), Seq::default()])
}
#[allow(dead_code)]
pub fn set_row<T>(input: &Array<T>, new_row: &Array<T>, row_num: u64) -> Array<T>
where T: HasAfEnum
{
let seqs = [Seq::new(row_num as f64, row_num as f64, 1.0), Seq::default()];
assign_seq(input, &seqs, new_row)
}
#[allow(dead_code)]
pub fn rows<T>(input: &Array<T>, first: u64, last: u64) -> Array<T>
where T: HasAfEnum
{
index(input, &[Seq::new(first as f64, last as f64, 1.0), Seq::default()])
}
#[allow(dead_code)]
pub fn set_rows<T>(input: &Array<T>, new_rows: &Array<T>, first: u64, last: u64) -> Array<T>
where T: HasAfEnum
{
let seqs = [Seq::new(first as f64, last as f64, 1.0), Seq::default()];
assign_seq(input, &seqs, new_rows)
}
#[allow(dead_code)]
pub fn col<T>(input: &Array<T>, col_num: u64) -> Array<T>
where T: HasAfEnum
{
index(input, &[Seq::default(), Seq::new(col_num as f64, col_num as f64, 1.0)])
}
#[allow(dead_code)]
pub fn set_col<T>(input: &Array<T>, new_col: &Array<T>, col_num: u64) -> Array<T>
where T: HasAfEnum
{
let seqs = [Seq::default(), Seq::new(col_num as f64, col_num as f64, 1.0)];
assign_seq(input, &seqs, new_col)
}
#[allow(dead_code)]
pub fn cols<T>(input: &Array<T>, first: u64, last: u64) -> Array<T>
where T: HasAfEnum
{
index(input, &[Seq::default(), Seq::new(first as f64, last as f64, 1.0)])
}
#[allow(dead_code)]
pub fn set_cols<T>(input: &Array<T>, new_cols: &Array<T>, first: u64, last: u64) -> Array<T>
where T: HasAfEnum
{
let seqs = [Seq::default(), Seq::new(first as f64, last as f64, 1.0)];
assign_seq(input, &seqs, new_cols)
}
#[allow(dead_code)]
pub fn slice<T>(input: &Array<T>, slice_num: u64) -> Array<T>
where T: HasAfEnum
{
let seqs = [Seq::default(), Seq::default(), Seq::new(slice_num as f64, slice_num as f64, 1.0)];
index(input, &seqs)
}
#[allow(dead_code)]
pub fn set_slice<T>(input: &Array<T>, new_slice: &Array<T>, slice_num: u64) -> Array<T>
where T: HasAfEnum
{
let seqs = [Seq::default(), Seq::default(), Seq::new(slice_num as f64, slice_num as f64, 1.0)];
assign_seq(input, &seqs, new_slice)
}
#[allow(dead_code)]
pub fn slices<T>(input: &Array<T>, first: u64, last: u64) -> Array<T>
where T: HasAfEnum
{
let seqs = [Seq::default(), Seq::default(), Seq::new(first as f64, last as f64, 1.0)];
index(input, &seqs)
}
#[allow(dead_code)]
pub fn set_slices<T>(input: &Array<T>, new_slices: &Array<T>, first: u64, last: u64) -> Array<T>
where T: HasAfEnum
{
let seqs = [Seq::default() , Seq::default(), Seq::new(first as f64, last as f64, 1.0)];
assign_seq(input, &seqs, new_slices)
}
pub fn lookup<T, I>(input: &Array<T>, indices: &Array<I>, seq_dim: i32) -> Array<T>
where T: HasAfEnum,
I: HasAfEnum
{
let mut temp: i64 = 0;
unsafe {
let err_val = af_lookup(&mut temp as MutAfArray, input.get() as AfArray,
indices.get() as AfArray, seq_dim as c_uint);
HANDLE_ERROR(AfError::from(err_val));
}
temp.into()
}
pub fn assign_seq<T: Copy, I>(lhs: &Array<I>, seqs: &[Seq<T>], rhs: &Array<I>) -> Array<I>
where c_double: From<T>,
I: HasAfEnum
{
let mut temp: i64 = 0;
let seqs: Vec<SeqInternal> = seqs.iter().map(|s| SeqInternal::from_seq(s)).collect();
unsafe {
let err_val = af_assign_seq(&mut temp as MutAfArray, lhs.get() as AfArray,
seqs.len() as c_uint, seqs.as_ptr() as *const SeqInternal,
rhs.get() as AfArray);
HANDLE_ERROR(AfError::from(err_val));
}
temp.into()
}
pub fn index_gen<T>(input: &Array<T>, indices: Indexer) -> Array<T>
where T: HasAfEnum
{
let mut temp: i64 = 0;
unsafe{
let err_val = af_index_gen(&mut temp as MutAfArray, input.get() as AfArray,
indices.len() as DimT, indices.get() as AfIndex);
HANDLE_ERROR(AfError::from(err_val));
}
temp.into()
}
pub fn assign_gen<T>(lhs: &Array<T>, indices: &Indexer, rhs: &Array<T>) -> Array<T>
where T: HasAfEnum
{
let mut temp: i64 = 0;
unsafe{
let err_val = af_assign_gen(&mut temp as MutAfArray, lhs.get() as AfArray,
indices.len() as DimT, indices.get() as AfIndex,
rhs.get() as AfArray);
HANDLE_ERROR(AfError::from(err_val));
}
temp.into()
}
#[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()),
}
}
}