Skip to content
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
21 changes: 14 additions & 7 deletions src/impl_constructors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,17 @@ impl<S, A, D> ArrayBase<S, D>
unsafe { Ok(Self::from_vec_dim_unchecked(dim, v)) }
}

/// Create an array from a vector (no copying needed) using fortran
/// memory order to interpret the data.
///
/// **Errors** if `dim` does not correspond to the number of elements in `v`.
pub fn from_vec_dim_f(dim: D, v: Vec<A>) -> Result<ArrayBase<S, D>, ShapeError> {
if dim.size_checked() != Some(v.len()) {
return Err(error::incompatible_shapes(&v.len(), &dim));
}
unsafe { Ok(Self::from_vec_dim_unchecked_f(dim, v)) }
}

/// Create an array from a vector (no copying needed).
///
/// Unsafe because dimension is unchecked, and must be correct.
Expand All @@ -216,14 +227,10 @@ impl<S, A, D> ArrayBase<S, D>
/// using fortran memory order to interpret the data.
///
/// Unsafe because dimension is unchecked, and must be correct.
pub unsafe fn from_vec_dim_unchecked_f(dim: D, mut v: Vec<A>) -> ArrayBase<S, D> {
pub unsafe fn from_vec_dim_unchecked_f(dim: D, v: Vec<A>) -> ArrayBase<S, D> {
debug_assert!(dim.size_checked() == Some(v.len()));
ArrayBase {
ptr: v.as_mut_ptr(),
data: DataOwned::new(v),
strides: dim.fortran_strides(),
dim: dim,
}
let strides = dim.fortran_strides();
Self::from_vec_dim_stride_unchecked(dim, strides, v)
}

/// Create an array from a vector and interpret it according to the
Expand Down
31 changes: 31 additions & 0 deletions src/impl_linalg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,11 @@ impl<A, S> ArrayBase<S, (Ix, Ix)>
self.subview_mut(Axis(0), index)
}

/// Return the number of rows (length of `Axis(0)`) in the two-dimensional array.
pub fn rows(&self) -> Ix {
self.shape().axis(Axis(0))
}

/// Return an array view of column `index`.
///
/// **Panics** if `index` is out of bounds.
Expand All @@ -157,6 +162,11 @@ impl<A, S> ArrayBase<S, (Ix, Ix)>
self.subview_mut(Axis(1), index)
}

/// Return the number of columns (length of `Axis(1)`) in the two-dimensional array.
pub fn cols(&self) -> Ix {
self.shape().axis(Axis(1))
}

/// Perform matrix multiplication of rectangular arrays `self` and `rhs`.
///
/// The array shapes must agree in the way that
Expand Down Expand Up @@ -228,6 +238,27 @@ impl<A, S> ArrayBase<S, (Ix, Ix)>
}
}

impl<A, S, D> ArrayBase<S, D>
where S: Data<Elem=A>,
D: Dimension,
{
/// Perform the operation `self += alpha * rhs` efficiently, where
/// `alpha` is a scalar and `rhs` is another array. This operation is
/// also known as `axpy` in BLAS.
///
/// If their shapes disagree, `rhs` is broadcast to the shape of `self`.
///
/// **Panics** if broadcasting isn’t possible.
pub fn scaled_add<S2, E>(&mut self, alpha: A, rhs: &ArrayBase<S2, E>)
where S: DataMut,
S2: Data<Elem=A>,
A: LinalgScalar,
E: Dimension,
{
self.zip_mut_with(rhs, move |y, &x| *y = *y + (alpha * x));
}
}

#[cfg(not(feature="blas"))]
use self::mat_mul_general as mat_mul_impl;

Expand Down
12 changes: 6 additions & 6 deletions src/impl_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1154,8 +1154,8 @@ impl<A, S, D> ArrayBase<S, D> where S: Data<Elem=A>, D: Dimension
/// [1., 2.]])
/// );
/// ```
pub fn mapv<B, F>(&self, mut f: F) -> OwnedArray<B, D>
where F: FnMut(A) -> B,
pub fn mapv<B, F>(&self, f: F) -> OwnedArray<B, D>
where F: Fn(A) -> B,
A: Clone,
{
self.map(move |x| f(x.clone()))
Expand All @@ -1167,7 +1167,7 @@ impl<A, S, D> ArrayBase<S, D> where S: Data<Elem=A>, D: Dimension
/// Elements are visited in arbitrary order.
pub fn mapv_into<F>(mut self, f: F) -> Self
where S: DataMut,
F: FnMut(A) -> A,
F: Fn(A) -> A,
A: Clone,
{
self.applyv(f);
Expand All @@ -1179,7 +1179,7 @@ impl<A, S, D> ArrayBase<S, D> where S: Data<Elem=A>, D: Dimension
/// Elements are visited in arbitrary order.
pub fn apply<F>(&mut self, f: F)
where S: DataMut,
F: FnMut(&mut A),
F: Fn(&mut A),
{
self.unordered_foreach_mut(f);
}
Expand All @@ -1200,9 +1200,9 @@ impl<A, S, D> ArrayBase<S, D> where S: Data<Elem=A>, D: Dimension
/// [0.36788, 7.38906]]), 1e-5)
/// );
/// ```
pub fn applyv<F>(&mut self, mut f: F)
pub fn applyv<F>(&mut self, f: F)
where S: DataMut,
F: FnMut(A) -> A,
F: Fn(A) -> A,
A: Clone,
{
self.unordered_foreach_mut(move |x| *x = f(x.clone()));
Expand Down
5 changes: 5 additions & 0 deletions src/stacking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ use error::{ShapeError, ErrorKind, from_kind};

/// Stack arrays along the given axis.
///
/// ***Errors*** if the arrays don't all have the same dimension
/// (may be made more flexible in the future).<br>
/// ***Errors*** if `arrays` is empty, if `axis` is out of bounds,
/// if the result is larger than is possible to represent.
///
/// ```
/// use ndarray::{arr2, Axis, stack};
///
Expand Down
18 changes: 10 additions & 8 deletions tests/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ fn test_add()
}

let B = A.clone();
A.iadd(&B);
A = A + &B;
assert_eq!(A[[0, 0]], 0);
assert_eq!(A[[0, 1]], 2);
assert_eq!(A[[1, 0]], 4);
Expand All @@ -132,7 +132,6 @@ fn test_multidim()
*elt = i as u8;
}
}
//println!("shape={:?}, strides={:?}", mat.shape(), mat.strides);
assert_eq!(mat.dim(), (2,3,4,5,6));
}

Expand All @@ -152,7 +151,7 @@ array([[[ 7, 6],
fn test_negative_stride_rcarray()
{
let mut mat = RcArray::zeros((2, 4, 2));
mat[(0, 0, 0)] = 1.0f32;
mat[[0, 0, 0]] = 1.0f32;
for (i, elt) in mat.iter_mut().enumerate() {
*elt = i as f32;
}
Expand All @@ -167,8 +166,8 @@ fn test_negative_stride_rcarray()
}
}
{
let vi = mat.slice(&[S, Si(0, None, -5), S]);
let seq = [6_f32, 7., 14., 15.];
let vi = mat.slice(s![.., ..;-5, ..]);
let seq = [6., 7., 14., 15.];
for (a, b) in vi.iter().zip(seq.iter()) {
assert_eq!(*a, *b);
}
Expand All @@ -178,7 +177,7 @@ fn test_negative_stride_rcarray()
#[test]
fn test_cow()
{
let mut mat = RcArray::<isize, _>::zeros((2,2));
let mut mat = RcArray::zeros((2,2));
mat[[0, 0]] = 1;
let n = mat.clone();
mat[[0, 1]] = 2;
Expand Down Expand Up @@ -343,10 +342,13 @@ fn iter_size_hint()
#[test]
fn zero_axes()
{
let a = arr1::<f32>(&[]);
let mut a = arr1::<f32>(&[]);
for _ in a.iter() {
assert!(false);
}
a.map(|_| assert!(false));
a.apply(|_| assert!(false));
a.visit(|_| assert!(false));
println!("{:?}", a);
let b = arr2::<f32, _>(&[[], [], [], []]);
println!("{:?}\n{:?}", b.shape(), b);
Expand Down Expand Up @@ -377,7 +379,7 @@ fn map1()
let b = a.map(|&x| (x / 3.) as isize);
assert_eq!(b, arr2(&[[0, 0], [1, 1]]));
// test map to reference with array's lifetime.
let c = a.map(|x| x).into_shared();
let c = a.map(|x| x);
assert_eq!(a[(0, 0)], *c[(0, 0)]);
}

Expand Down
15 changes: 15 additions & 0 deletions tests/oper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,3 +216,18 @@ fn mat_mul_order() {
assert_eq!(cc.strides()[1], 1);
assert_eq!(ff.strides()[0], 1);
}

#[test]
fn scaled_add() {
let a = range_mat(16, 15);
let mut b = range_mat(16, 15);
b.applyv(f32::exp);

let alpha = 0.2_f32;
let mut c = a.clone();
c.scaled_add(alpha, &b);

let d = alpha * &b + &a;
assert_eq!(c, d);

}