extern crate libc;
use self::libc::{c_double, c_int, c_uint};
use crate::array::Array;
use crate::defines::AfError;
use crate::error::HANDLE_ERROR;
use crate::seq::Seq;
use crate::util::{AfArray, AfIndex, DimT, HasAfEnum, MutAfArray, MutAfIndex};
use std::marker::PhantomData;
#[allow(dead_code)]
extern "C" {
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() -> Self {
let mut temp: i64 = 0;
unsafe {
let err_val = af_create_indexers(&mut temp as MutAfIndex);
HANDLE_ERROR(AfError::from(err_val));
}
Self {
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>,
{
Self {
begin: From::from(s.begin()),
end: From::from(s.end()),
step: From::from(s.step()),
}
}
}