#![crate_name="ndarray"]
#![crate_type="dylib"]
#![cfg_attr(feature = "assign_ops", feature(augmented_assignments,
op_assign_traits))]
#[cfg(feature = "serde")]
extern crate serde;
#[cfg(feature = "rustc-serialize")]
extern crate rustc_serialize as serialize;
extern crate itertools as it;
#[cfg(not(nocomplex))]
extern crate num as libnum;
use std::mem;
use std::rc::Rc;
use libnum::Float;
use std::ops::{Add, Sub, Mul, Div, Rem, Neg, Not, Shr, Shl,
BitAnd,
BitOr,
BitXor,
};
pub use dimension::{Dimension, RemoveAxis};
pub use si::{Si, S, SliceRange};
use dimension::stride_offset;
pub use indexes::Indexes;
use iterators::Baseiter;
pub mod linalg;
mod arraytraits;
#[cfg(feature = "serde")]
mod arrayserialize;
mod arrayformat;
mod dimension;
mod indexes;
mod iterators;
mod si;
pub type Ix = u32;
pub type Ixs = i32;
pub struct ArrayBase<S, D> where S: Data {
data: S,
ptr: *mut S::Elem,
dim: D,
strides: D,
}
pub unsafe trait Data {
type Elem;
fn slice(&self) -> &[Self::Elem];
}
pub unsafe trait DataMut : Data {
fn slice_mut(&mut self) -> &mut [Self::Elem];
fn ensure_unique<D>(&mut ArrayBase<Self, D>)
where Self: Sized, D: Dimension
{
}
}
pub unsafe trait DataClone : Data {
unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem) -> (Self, *mut Self::Elem);
}
unsafe impl<A> Data for Rc<Vec<A>> {
type Elem = A;
fn slice(&self) -> &[A] { self }
}
unsafe impl<A> DataMut for Rc<Vec<A>> where A: Clone {
fn slice_mut(&mut self) -> &mut [A] { &mut Rc::make_mut(self)[..] }
fn ensure_unique<D>(self_: &mut ArrayBase<Self, D>)
where Self: Sized, D: Dimension
{
if Rc::get_mut(&mut self_.data).is_some() {
return
}
if self_.dim.size() <= self_.data.len() / 2 {
unsafe {
*self_ = Array::from_vec_dim(self_.dim.clone(),
self_.iter().map(|x| x.clone()).collect());
}
return;
}
let our_off = (self_.ptr as isize - self_.data.as_ptr() as isize)
/ mem::size_of::<A>() as isize;
let rvec = Rc::make_mut(&mut self_.data);
unsafe {
self_.ptr = rvec.as_mut_ptr().offset(our_off);
}
}
}
unsafe impl<A> DataClone for Rc<Vec<A>> {
unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem)
-> (Self, *mut Self::Elem)
{
(self.clone(), ptr)
}
}
unsafe impl<A> Data for Vec<A> {
type Elem = A;
fn slice(&self) -> &[A] { self }
}
unsafe impl<A> DataMut for Vec<A> {
fn slice_mut(&mut self) -> &mut [A] { self }
}
unsafe impl<A> DataClone for Vec<A> where A: Clone {
unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem)
-> (Self, *mut Self::Elem)
{
let mut u = self.clone();
let our_off = (self.as_ptr() as isize - ptr as isize)
/ mem::size_of::<A>() as isize;
let new_ptr = u.as_mut_ptr().offset(our_off);
(u, new_ptr)
}
}
unsafe impl<'a, A> Data for &'a [A] {
type Elem = A;
fn slice(&self) -> &[A] { self }
}
unsafe impl<'a, A> DataClone for &'a [A] {
unsafe fn clone_with_ptr(&self, ptr: *mut Self::Elem)
-> (Self, *mut Self::Elem)
{
(*self, ptr)
}
}
unsafe impl<'a, A> Data for &'a mut [A] {
type Elem = A;
fn slice(&self) -> &[A] { self }
}
unsafe impl<'a, A> DataMut for &'a mut [A] {
fn slice_mut(&mut self) -> &mut [A] { self }
}
pub unsafe trait DataOwned : Data {
fn new(elements: Vec<Self::Elem>) -> Self;
fn into_shared(self) -> Rc<Vec<Self::Elem>>;
}
pub trait DataShared : Clone + DataClone { }
impl<A> DataShared for Rc<Vec<A>> { }
impl<'a, A> DataShared for &'a [A] { }
unsafe impl<A> DataOwned for Vec<A> {
fn new(elements: Vec<A>) -> Self { elements }
fn into_shared(self) -> Rc<Vec<A>> { Rc::new(self) }
}
unsafe impl<A> DataOwned for Rc<Vec<A>> {
fn new(elements: Vec<A>) -> Self { Rc::new(elements) }
fn into_shared(self) -> Rc<Vec<A>> { self }
}
pub type Array<A, D> = ArrayBase<Rc<Vec<A>>, D>;
pub type OwnedArray<A, D> = ArrayBase<Vec<A>, D>;
pub type ArrayView<'a, A, D> = ArrayBase<&'a [A], D>;
pub type ArrayViewMut<'a, A, D> = ArrayBase<&'a mut [A], D>;
impl<S: DataClone, D: Clone> Clone for ArrayBase<S, D>
{
fn clone(&self) -> ArrayBase<S, D> {
unsafe {
let (data, ptr) = self.data.clone_with_ptr(self.ptr);
ArrayBase {
data: data,
ptr: ptr,
dim: self.dim.clone(),
strides: self.strides.clone(),
}
}
}
}
impl<S: DataClone + Copy, D: Copy> Copy for ArrayBase<S, D> { }
impl<S> ArrayBase<S, Ix>
where S: DataOwned,
{
pub fn from_vec(v: Vec<S::Elem>) -> Self {
unsafe {
Self::from_vec_dim(v.len() as Ix, v)
}
}
pub fn from_iter<I: IntoIterator<Item=S::Elem>>(iterable: I) -> ArrayBase<S, Ix> {
Self::from_vec(iterable.into_iter().collect())
}
}
impl Array<f32, Ix>
{
pub fn range(begin: f32, end: f32) -> Array<f32, Ix>
{
let n = (end - begin) as usize;
let span = if n > 0 { (n - 1) as f32 } else { 0. };
Array::from_iter(it::linspace(begin,
begin + span,
n))
}
}
impl<S, D> ArrayBase<S, D>
where S: DataOwned,
D: Dimension,
{
pub unsafe fn from_vec_dim(dim: D, mut v: Vec<S::Elem>) -> ArrayBase<S, D>
{
debug_assert!(dim.size() == v.len());
ArrayBase {
ptr: v.as_mut_ptr(),
data: DataOwned::new(v),
strides: dim.default_strides(),
dim: dim
}
}
pub fn zeros(dim: D) -> ArrayBase<S, D> where S::Elem: Clone + libnum::Zero
{
Self::from_elem(dim, libnum::zero())
}
pub fn from_elem(dim: D, elem: S::Elem) -> ArrayBase<S, D> where S::Elem: Clone
{
let v = std::iter::repeat(elem).take(dim.size()).collect();
unsafe {
Self::from_vec_dim(dim, v)
}
}
pub fn default(dim: D) -> ArrayBase<S, D>
where S::Elem: Default
{
let v = (0..dim.size()).map(|_| <S::Elem>::default()).collect();
unsafe {
Self::from_vec_dim(dim, v)
}
}
}
impl<'a, A, D> ArrayView<'a, A, D>
where D: Dimension,
{
#[inline]
fn into_base_iter(self) -> Baseiter<'a, A, D> {
unsafe {
Baseiter::new(self.ptr, self.dim.clone(), self.strides.clone())
}
}
fn into_iter_(self) -> Elements<'a, A, D> {
Elements { inner: self.into_base_iter() }
}
}
impl<'a, A, D> ArrayViewMut<'a, A, D>
where D: Dimension,
{
#[inline]
fn into_base_iter(self) -> Baseiter<'a, A, D> {
unsafe {
Baseiter::new(self.ptr, self.dim.clone(), self.strides.clone())
}
}
fn into_iter_(self) -> ElementsMut<'a, A, D> {
ElementsMut { inner: self.into_base_iter() }
}
}
impl<A, S, D> ArrayBase<S, D> where S: Data<Elem=A>, D: Dimension
{
pub fn len(&self) -> usize
{
self.dim.size()
}
pub fn dim(&self) -> D {
self.dim.clone()
}
pub fn shape(&self) -> &[Ix] {
self.dim.slice()
}
pub fn is_standard_layout(&self) -> bool
{
self.strides == self.dim.default_strides()
}
pub fn view(&self) -> ArrayView<A, D> {
ArrayView {
ptr: self.ptr,
dim: self.dim.clone(),
strides: self.strides.clone(),
data: self.raw_data(),
}
}
pub fn view_mut(&mut self) -> ArrayViewMut<A, D>
where S: DataMut,
{
self.ensure_unique();
ArrayViewMut {
ptr: self.ptr,
dim: self.dim.clone(),
strides: self.strides.clone(),
data: self.data.slice_mut(),
}
}
pub fn to_owned(&self) -> OwnedArray<A, D>
where A: Clone
{
let data = self.iter().cloned().collect();
unsafe {
ArrayBase::from_vec_dim(self.dim.clone(), data)
}
}
pub fn to_shared(&self) -> Array<A, D>
where A: Clone
{
let data = self.iter().cloned().collect();
unsafe {
ArrayBase::from_vec_dim(self.dim.clone(), data)
}
}
pub fn into_shared(self) -> Array<A, D>
where S: DataOwned,
{
let data = self.data.into_shared();
ArrayBase {
data: data,
ptr: self.ptr,
dim: self.dim,
strides: self.strides,
}
}
pub fn raw_data(&self) -> &[A]
{
self.data.slice()
}
pub fn slice(&self, indexes: &[Si]) -> Self
where S: DataShared
{
let mut arr = self.clone();
arr.islice(indexes);
arr
}
pub fn islice(&mut self, indexes: &[Si])
{
let offset = Dimension::do_slices(&mut self.dim, &mut self.strides, indexes);
unsafe {
self.ptr = self.ptr.offset(offset);
}
}
pub fn slice_iter(&self, indexes: &[Si]) -> Elements<A, D>
{
let mut it = self.iter();
let offset = Dimension::do_slices(&mut it.inner.dim, &mut it.inner.strides, indexes);
unsafe {
it.inner.ptr = it.inner.ptr.offset(offset);
}
it
}
pub fn get(&self, index: D) -> Option<&A> {
self.dim.stride_offset_checked(&self.strides, &index)
.map(|offset| unsafe {
&*self.ptr.offset(offset)
})
}
pub fn at(&self, index: D) -> Option<&A> {
self.get(index)
}
pub fn get_mut(&mut self, index: D) -> Option<&mut A>
where S: DataMut,
{
self.ensure_unique();
self.dim.stride_offset_checked(&self.strides, &index)
.map(|offset| unsafe {
&mut *self.ptr.offset(offset)
})
}
pub fn at_mut(&mut self, index: D) -> Option<&mut A>
where S: DataMut,
{
self.get_mut(index)
}
#[inline]
pub unsafe fn uchk_at(&self, index: D) -> &A {
debug_assert!(self.dim.stride_offset_checked(&self.strides, &index).is_some());
let off = Dimension::stride_offset(&index, &self.strides);
&*self.ptr.offset(off)
}
#[inline]
pub unsafe fn uchk_at_mut(&mut self, index: D) -> &mut A
where S: DataMut
{
debug_assert!(self.dim.stride_offset_checked(&self.strides, &index).is_some());
let off = Dimension::stride_offset(&index, &self.strides);
&mut *self.ptr.offset(off)
}
#[inline]
fn base_iter<'a>(&'a self) -> Baseiter<'a, A, D>
{
unsafe {
Baseiter::new(self.ptr, self.dim.clone(), self.strides.clone())
}
}
pub fn iter(&self) -> Elements<A, D>
{
Elements { inner: self.base_iter() }
}
pub fn indexed_iter(&self) -> Indexed<Elements<A, D>>
{
self.iter().indexed()
}
pub fn isubview(&mut self, axis: usize, index: Ix)
{
dimension::do_sub(&mut self.dim, &mut self.ptr, &self.strides, axis, index)
}
pub fn broadcast<E: Dimension>(&self, dim: E)
-> Option<ArrayView<A, E>>
{
fn upcast<D: Dimension, E: Dimension>(to: &D, from: &E, stride: &E) -> Option<D> {
let mut new_stride = to.clone();
if to.ndim() < from.ndim() {
return None
}
{
let mut new_stride_iter = new_stride.slice_mut().iter_mut().rev();
for ((er, es), dr) in from.slice().iter().rev()
.zip(stride.slice().iter().rev())
.zip(new_stride_iter.by_ref())
{
if *dr == *er {
*dr = *es;
} else if *er == 1 {
*dr = 0
} else {
return None;
}
}
for dr in new_stride_iter {
*dr = 0;
}
}
Some(new_stride)
}
let broadcast_strides =
match upcast(&dim, &self.dim, &self.strides) {
Some(st) => st,
None => return None,
};
Some(ArrayView {
data: self.raw_data(),
ptr: self.ptr,
dim: dim,
strides: broadcast_strides,
})
}
pub fn broadcast_iter<E: Dimension>(&self, dim: E)
-> Option<Elements<A, E>>
{
self.broadcast(dim).map(|v| v.into_iter_())
}
#[inline(never)]
fn broadcast_iter_unwrap<E: Dimension>(&self, dim: E)
-> Elements<A, E>
{
match self.broadcast_iter(dim.clone()) {
Some(it) => it,
None => panic!("Could not broadcast array from shape {:?} into: {:?}",
self.shape(), dim.slice())
}
}
pub fn swap_axes(&mut self, ax: usize, bx: usize)
{
self.dim.slice_mut().swap(ax, bx);
self.strides.slice_mut().swap(ax, bx);
}
fn diag_params(&self) -> (Ix, Ixs)
{
let len = self.dim.slice().iter().map(|x| *x).min().unwrap_or(1);
let stride = self.strides.slice().iter()
.map(|x| *x as Ixs)
.fold(0, |sum, s| sum + s);
return (len, stride)
}
pub fn diag_iter(&self) -> Elements<A, Ix>
{
let (len, stride) = self.diag_params();
unsafe {
Elements { inner:
Baseiter::new(self.ptr, len, stride as Ix)
}
}
}
pub fn diag(&self) -> ArrayBase<S, Ix>
where S: DataShared,
{
let (len, stride) = self.diag_params();
ArrayBase {
data: self.data.clone(),
ptr: self.ptr,
dim: len,
strides: stride as Ix,
}
}
pub fn map<'a, B, F>(&'a self, mut f: F) -> OwnedArray<B, D>
where F: FnMut(&'a A) -> B,
A: 'a,
{
let mut res = Vec::with_capacity(self.dim.size());
for elt in self.iter() {
res.push(f(elt))
}
unsafe {
ArrayBase::from_vec_dim(self.dim.clone(), res)
}
}
pub fn subview(&self, axis: usize, index: Ix) -> ArrayBase<S, <D as RemoveAxis>::Smaller>
where D: RemoveAxis,
S: DataShared,
{
let mut res = self.clone();
res.isubview(axis, index);
ArrayBase {
data: res.data,
ptr: res.ptr,
dim: res.dim.remove_axis(axis),
strides: res.strides.remove_axis(axis),
}
}
fn ensure_unique(&mut self)
where S: DataMut
{
S::ensure_unique(self);
}
pub fn iter_mut(&mut self) -> ElementsMut<A, D>
where S: DataMut,
{
self.ensure_unique();
ElementsMut { inner: self.base_iter() }
}
pub fn indexed_iter_mut(&mut self) -> Indexed<ElementsMut<A, D>>
where S: DataMut,
{
self.iter_mut().indexed()
}
pub fn slice_mut(&mut self, indexes: &[Si]) -> ArrayViewMut<A, D>
where S: DataMut
{
let mut arr = self.view_mut();
arr.islice(indexes);
arr
}
pub fn slice_iter_mut(&mut self, indexes: &[Si]) -> ElementsMut<A, D>
where S: DataMut,
{
let mut it = self.iter_mut();
let offset = Dimension::do_slices(&mut it.inner.dim, &mut it.inner.strides, indexes);
unsafe {
it.inner.ptr = it.inner.ptr.offset(offset);
}
it
}
pub fn subview_mut(&mut self, axis: usize, index: Ix)
-> ArrayViewMut<A, D::Smaller>
where S: DataMut,
D: RemoveAxis,
{
let mut res = self.view_mut();
res.isubview(axis, index);
ArrayBase {
data: res.data,
ptr: res.ptr,
dim: res.dim.remove_axis(axis),
strides: res.strides.remove_axis(axis),
}
}
pub fn sub_iter_mut(&mut self, axis: usize, index: Ix)
-> ElementsMut<A, D>
where S: DataMut,
{
let mut it = self.iter_mut();
dimension::do_sub(&mut it.inner.dim, &mut it.inner.ptr, &it.inner.strides, axis, index);
it
}
pub fn diag_iter_mut(&mut self) -> ElementsMut<A, Ix>
where S: DataMut,
{
self.ensure_unique();
let (len, stride) = self.diag_params();
unsafe {
ElementsMut { inner:
Baseiter::new(self.ptr, len, stride as Ix),
}
}
}
pub fn raw_data_mut(&mut self) -> &mut [A]
where S: DataMut,
{
self.ensure_unique();
self.data.slice_mut()
}
pub fn reshape<E: Dimension>(&self, shape: E) -> ArrayBase<S, E>
where S: DataShared + DataOwned, A: Clone,
{
if shape.size() != self.dim.size() {
panic!("Incompatible sizes in reshape, attempted from: {:?}, to: {:?}",
self.dim.slice(), shape.slice())
}
if self.is_standard_layout() {
let cl = self.clone();
ArrayBase {
data: cl.data,
ptr: cl.ptr,
strides: shape.default_strides(),
dim: shape,
}
} else {
let v = self.iter().map(|x| x.clone()).collect::<Vec<A>>();
unsafe {
ArrayBase::from_vec_dim(shape, v)
}
}
}
pub fn assign<E: Dimension, S2>(&mut self, rhs: &ArrayBase<S2, E>)
where S: DataMut,
A: Clone,
S2: Data<Elem=A>,
{
if self.shape() == rhs.shape() {
for (x, y) in self.iter_mut().zip(rhs.iter()) {
*x = y.clone();
}
} else {
let other_iter = rhs.broadcast_iter_unwrap(self.dim());
for (x, y) in self.iter_mut().zip(other_iter) {
*x = y.clone();
}
}
}
pub fn assign_scalar(&mut self, x: &A)
where S: DataMut, A: Clone,
{
for elt in self.iter_mut() {
*elt = x.clone();
}
}
}
pub fn arr0<A>(x: A) -> Array<A, ()>
{
let mut v = Vec::with_capacity(1);
v.push(x);
unsafe { Array::from_vec_dim((), v) }
}
pub fn arr1<A: Clone>(xs: &[A]) -> Array<A, Ix>
{
Array::from_vec(xs.to_vec())
}
pub fn aview0<A>(x: &A) -> ArrayView<A, ()> {
let data = unsafe {
std::slice::from_raw_parts(x, 1)
};
ArrayView {
data: data,
ptr: data.as_ptr() as *mut _,
dim: (),
strides: (),
}
}
pub fn aview1<A>(xs: &[A]) -> ArrayView<A, Ix> {
ArrayView {
data: xs,
ptr: xs.as_ptr() as *mut _,
dim: xs.len() as Ix,
strides: 1,
}
}
pub fn aview2<A, V: FixedInitializer<Elem=A>>(xs: &[V]) -> ArrayView<A, (Ix, Ix)> {
let cols = V::len();
let rows = xs.len();
let data = unsafe {
std::slice::from_raw_parts(xs.as_ptr() as *const A, cols * rows)
};
let dim = (rows as Ix, cols as Ix);
ArrayView {
data: data,
ptr: data.as_ptr() as *mut _,
strides: dim.default_strides(),
dim: dim,
}
}
pub unsafe trait Initializer {
type Elem;
fn as_init_slice(&self) -> &[Self::Elem];
fn is_fixed_size() -> bool { false }
}
pub unsafe trait FixedInitializer: Initializer {
fn len() -> usize;
}
unsafe impl<T> Initializer for [T] {
type Elem = T;
fn as_init_slice(&self) -> &[T] {
self
}
}
macro_rules! impl_arr_init {
(__impl $n: expr) => (
unsafe impl<T> Initializer for [T; $n] {
type Elem = T;
fn as_init_slice(&self) -> &[T] { self }
fn is_fixed_size() -> bool { true }
}
unsafe impl<T> FixedInitializer for [T; $n] {
fn len() -> usize { $n }
}
);
() => ();
($n: expr, $($m:expr,)*) => (
impl_arr_init!(__impl $n);
impl_arr_init!($($m,)*);
)
}
impl_arr_init!(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,);
pub fn arr2<A: Clone, V: Initializer<Elem=A>>(xs: &[V]) -> Array<A, (Ix, Ix)>
{
let (m, n) = (xs.len() as Ix,
xs.get(0).map_or(0, |snd| snd.as_init_slice().len() as Ix));
let dim = (m, n);
let mut result = Vec::<A>::with_capacity(dim.size());
for snd in xs.iter() {
let snd = snd.as_init_slice();
assert!(<V as Initializer>::is_fixed_size() || snd.len() as Ix == n);
result.extend(snd.iter().map(|x| x.clone()))
}
unsafe {
Array::from_vec_dim(dim, result)
}
}
pub fn arr3<A: Clone, V: Initializer<Elem=U>, U: Initializer<Elem=A>>(xs: &[V])
-> Array<A, (Ix, Ix, Ix)>
{
let m = xs.len() as Ix;
let fst = xs.get(0).map(|snd| snd.as_init_slice());
let thr = fst.and_then(|elt| elt.get(0).map(|elt2| elt2.as_init_slice()));
let n = fst.map_or(0, |v| v.len() as Ix);
let o = thr.map_or(0, |v| v.len() as Ix);
let dim = (m, n, o);
let mut result = Vec::<A>::with_capacity(dim.size());
for snd in xs.iter() {
let snd = snd.as_init_slice();
assert!(<V as Initializer>::is_fixed_size() || snd.len() as Ix == n);
for thr in snd.iter() {
let thr = thr.as_init_slice();
assert!(<U as Initializer>::is_fixed_size() || thr.len() as Ix == o);
result.extend(thr.iter().map(|x| x.clone()))
}
}
unsafe {
Array::from_vec_dim(dim, result)
}
}
impl<A, S, D> ArrayBase<S, D>
where A: Clone + Add<Output=A>,
S: Data<Elem=A>,
D: RemoveAxis,
{
pub fn sum(&self, axis: usize) -> OwnedArray<A, <D as RemoveAxis>::Smaller>
{
let n = self.shape()[axis];
let mut res = self.view().subview(axis, 0).to_owned();
for i in 1..n {
let view = self.view().subview(axis, i);
res.iadd(&view);
}
res
}
}
impl<A, S, D> ArrayBase<S, D>
where A: Copy + linalg::Field,
S: Data<Elem=A>,
D: RemoveAxis,
{
pub fn mean(&self, axis: usize) -> OwnedArray<A, <D as RemoveAxis>::Smaller>
{
let n = self.shape()[axis];
let mut sum = self.sum(axis);
let one = libnum::one::<A>();
let mut cnt = one;
for _ in 1..n {
cnt = cnt + one;
}
for elt in sum.iter_mut() {
*elt = *elt / cnt;
}
sum
}
}
impl<A, S> ArrayBase<S, (Ix, Ix)>
where S: Data<Elem=A>,
{
pub fn row_iter(&self, index: Ix) -> Elements<A, Ix>
{
let (m, n) = self.dim;
let (sr, sc) = self.strides;
assert!(index < m);
unsafe {
Elements { inner:
Baseiter::new(self.ptr.offset(stride_offset(index, sr)), n, sc)
}
}
}
pub fn col_iter(&self, index: Ix) -> Elements<A, Ix>
{
let (m, n) = self.dim;
let (sr, sc) = self.strides;
assert!(index < n);
unsafe {
Elements { inner:
Baseiter::new(self.ptr.offset(stride_offset(index, sc)), m, sr)
}
}
}
}
impl<A: Copy + linalg::Ring, S> ArrayBase<S, (Ix, Ix)>
where S: Data<Elem=A>,
{
pub fn mat_mul(&self, rhs: &ArrayBase<S, (Ix, Ix)>) -> Array<A, (Ix, Ix)>
{
let ((m, a), (b, n)) = (self.dim, rhs.dim);
let (self_columns, other_rows) = (a, b);
assert!(self_columns == other_rows);
let mut res_elems = Vec::<A>::with_capacity(m as usize * n as usize);
unsafe {
res_elems.set_len(m as usize * n as usize);
}
let mut i = 0;
let mut j = 0;
for rr in res_elems.iter_mut() {
unsafe {
let dot = (0..a).fold(libnum::zero::<A>(),
|s, k| s + *self.uchk_at((i, k)) * *rhs.uchk_at((k, j))
);
std::ptr::write(rr, dot);
}
j += 1;
if j == n {
j = 0;
i += 1;
}
}
unsafe {
ArrayBase::from_vec_dim((m, n), res_elems)
}
}
pub fn mat_mul_col(&self, rhs: &ArrayBase<S, Ix>) -> Array<A, Ix>
{
let ((m, a), n) = (self.dim, rhs.dim);
let (self_columns, other_rows) = (a, n);
assert!(self_columns == other_rows);
let mut res_elems = Vec::<A>::with_capacity(m as usize);
unsafe {
res_elems.set_len(m as usize);
}
let mut i = 0;
for rr in res_elems.iter_mut() {
unsafe {
let dot = (0..a).fold(libnum::zero::<A>(),
|s, k| s + *self.uchk_at((i, k)) * *rhs.uchk_at(k)
);
std::ptr::write(rr, dot);
}
i += 1;
}
unsafe {
ArrayBase::from_vec_dim(m, res_elems)
}
}
}
impl<A, S, D> ArrayBase<S, D>
where A: Float + PartialOrd,
S: Data<Elem=A>,
D: Dimension
{
pub fn allclose<S2>(&self, rhs: &ArrayBase<S2, D>, tol: A) -> bool
where S2: Data<Elem=A>,
{
self.shape() == rhs.shape() &&
self.iter().zip(rhs.iter()).all(|(x, y)| (*x - *y).abs() <= tol)
}
}
macro_rules! impl_binary_op(
($trt:ident, $mth:ident, $imethod:ident, $imth_scalar:ident, $doc:expr) => (
impl<A, S, D> ArrayBase<S, D> where
A: Clone + $trt<A, Output=A>,
S: DataMut<Elem=A>,
D: Dimension,
{
#[doc=$doc]
pub fn $imethod <E: Dimension, S2> (&mut self, rhs: &ArrayBase<S2, E>)
where S2: Data<Elem=A>,
{
if self.dim.ndim() == rhs.dim.ndim() &&
self.shape() == rhs.shape() {
for (x, y) in self.iter_mut().zip(rhs.iter()) {
*x = (x.clone()). $mth (y.clone());
}
} else {
let other_iter = rhs.broadcast_iter_unwrap(self.dim());
for (x, y) in self.iter_mut().zip(other_iter) {
*x = (x.clone()). $mth (y.clone());
}
}
}
#[doc=$doc]
pub fn $imth_scalar (&mut self, x: &A)
{
for elt in self.iter_mut() {
*elt = elt.clone(). $mth (x.clone());
}
}
}
#[doc=$doc]
impl<A, S, S2, D, E> $trt<ArrayBase<S2, E>> for ArrayBase<S, D>
where A: Clone + $trt<A, Output=A>,
S: DataMut<Elem=A>,
S2: Data<Elem=A>,
D: Dimension,
E: Dimension,
{
type Output = ArrayBase<S, D>;
fn $mth (mut self, rhs: ArrayBase<S2, E>) -> ArrayBase<S, D>
{
if self.shape() == rhs.shape() {
for (x, y) in self.iter_mut().zip(rhs.iter()) {
*x = x.clone(). $mth (y.clone());
}
} else {
let other_iter = rhs.broadcast_iter_unwrap(self.dim());
for (x, y) in self.iter_mut().zip(other_iter) {
*x = x.clone(). $mth (y.clone());
}
}
self
}
}
#[doc=$doc]
impl<'a, A, S, S2, D, E> $trt<&'a ArrayBase<S2, E>> for &'a ArrayBase<S, D>
where A: Clone + $trt<A, Output=A>,
S: Data<Elem=A>,
S2: Data<Elem=A>,
D: Dimension,
E: Dimension,
{
type Output = OwnedArray<A, D>;
fn $mth (self, rhs: &'a ArrayBase<S2, E>) -> OwnedArray<A, D>
{
let mut result = Vec::<A>::with_capacity(self.dim.size());
if self.shape() == rhs.shape() {
for (x, y) in self.iter().zip(rhs.iter()) {
result.push((x.clone()). $mth (y.clone()));
}
} else {
let other_iter = rhs.broadcast_iter_unwrap(self.dim());
for (x, y) in self.iter().zip(other_iter) {
result.push((x.clone()). $mth (y.clone()));
}
}
unsafe {
ArrayBase::from_vec_dim(self.dim.clone(), result)
}
}
}
);
);
impl_binary_op!(Add, add, iadd, iadd_scalar, "Addition");
impl_binary_op!(Sub, sub, isub, isub_scalar, "Subtraction");
impl_binary_op!(Mul, mul, imul, imul_scalar, "Multiplication");
impl_binary_op!(Div, div, idiv, idiv_scalar, "Divsion");
impl_binary_op!(Rem, rem, irem, irem_scalar, "Remainder");
impl_binary_op!(BitAnd, bitand, ibitand, ibitand_scalar, "Bit and");
impl_binary_op!(BitOr, bitor, ibitor, ibitor_scalar, "Bit or");
impl_binary_op!(BitXor, bitxor, ibitxor, ibitxor_scalar, "Bit xor");
impl_binary_op!(Shl, shl, ishl, ishl_scalar, "Shift left");
impl_binary_op!(Shr, shr, ishr, ishr_scalar, "Shift right");
#[cfg(feature = "assign_ops")]
mod assign_ops {
use super::*;
use std::ops::{
AddAssign,
SubAssign,
MulAssign,
DivAssign,
RemAssign,
BitAndAssign,
BitOrAssign,
BitXorAssign,
};
macro_rules! impl_assign_op {
($trt:ident, $method:ident, $doc:expr) => {
#[doc=$doc]
impl<'a, A, S, S2, D, E> $trt<&'a ArrayBase<S2, E>> for ArrayBase<S, D>
where A: Clone + $trt<A>,
S: DataMut<Elem=A>,
S2: Data<Elem=A>,
D: Dimension,
E: Dimension,
{
fn $method(&mut self, rhs: &ArrayBase<S2, E>) {
if self.shape() == rhs.shape() {
for (x, y) in self.iter_mut().zip(rhs.iter()) {
x.$method(y.clone());
}
} else {
let other_iter = rhs.broadcast_iter_unwrap(self.dim());
for (x, y) in self.iter_mut().zip(other_iter) {
x.$method(y.clone());
}
}
}
}
};
}
impl_assign_op!(AddAssign, add_assign,
"Implement `self += rhs` as elementwise addition (in place).\n");
impl_assign_op!(SubAssign, sub_assign,
"Implement `self -= rhs` as elementwise subtraction (in place).\n");
impl_assign_op!(MulAssign, mul_assign,
"Implement `self *= rhs` as elementwise multiplication (in place).\n");
impl_assign_op!(DivAssign, div_assign,
"Implement `self /= rhs` as elementwise division (in place).\n");
impl_assign_op!(RemAssign, rem_assign,
"Implement `self %= rhs` as elementwise remainder (in place).\n");
impl_assign_op!(BitAndAssign, bitand_assign,
"Implement `self &= rhs` as elementwise bit and (in place).\n");
impl_assign_op!(BitOrAssign, bitor_assign,
"Implement `self |= rhs` as elementwise bit or (in place).\n");
impl_assign_op!(BitXorAssign, bitxor_assign,
"Implement `self ^= rhs` as elementwise bit xor (in place).\n");
}
impl<A, S, D> ArrayBase<S, D>
where A: Clone + Neg<Output=A>,
S: DataMut<Elem=A>,
D: Dimension
{
pub fn ineg(&mut self)
{
for elt in self.iter_mut() {
*elt = elt.clone().neg()
}
}
}
impl<A, S, D> Neg for ArrayBase<S, D>
where A: Clone + Neg<Output=A>,
S: DataMut<Elem=A>,
D: Dimension
{
type Output = Self;
fn neg(mut self) -> Self {
self.ineg();
self
}
}
impl<A, S, D> ArrayBase<S, D>
where A: Clone + Not<Output=A>,
S: DataMut<Elem=A>,
D: Dimension
{
pub fn inot(&mut self)
{
for elt in self.iter_mut() {
*elt = elt.clone().not()
}
}
}
impl<A, S, D> Not for ArrayBase<S, D>
where A: Clone + Not<Output=A>,
S: DataMut<Elem=A>,
D: Dimension
{
type Output = Self;
fn not(mut self) -> Self {
self.inot();
self
}
}
pub struct Elements<'a, A: 'a, D> {
inner: Baseiter<'a, A, D>,
}
impl<'a, A, D> Elements<'a, A, D> where D: Clone
{
pub fn dim(&self) -> D
{
self.inner.dim.clone()
}
pub fn indexed(self) -> Indexed<Elements<'a, A, D>>
{
Indexed {
inner: self,
}
}
}
pub struct ElementsMut<'a, A: 'a, D> {
inner: Baseiter<'a, A, D>,
}
impl<'a, A, D> ElementsMut<'a, A, D> where D: Clone
{
pub fn dim(&self) -> D
{
self.inner.dim.clone()
}
pub fn indexed(self) -> Indexed<ElementsMut<'a, A, D>>
{
Indexed {
inner: self,
}
}
}
#[derive(Clone)]
pub struct Indexed<I> {
inner: I,
}