2017-02-13 01:17:09 +08:00
|
|
|
|
//! The default matrix data storage allocator.
|
|
|
|
|
//!
|
|
|
|
|
//! This will use stack-allocated buffers for matrices with dimensions known at compile-time, and
|
|
|
|
|
//! heap-allocated buffers for matrices with at least one dimension unknown at compile-time.
|
|
|
|
|
|
2017-08-03 01:37:44 +08:00
|
|
|
|
use std::cmp;
|
2018-05-19 23:15:15 +08:00
|
|
|
|
use std::mem;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
use std::ops::Mul;
|
2018-05-19 23:15:15 +08:00
|
|
|
|
use std::ptr;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
2018-05-24 23:17:34 +08:00
|
|
|
|
#[cfg(all(feature = "alloc", not(feature = "std")))]
|
|
|
|
|
use alloc::Vec;
|
|
|
|
|
|
2016-12-05 05:44:42 +08:00
|
|
|
|
use generic_array::ArrayLength;
|
2018-05-19 23:15:15 +08:00
|
|
|
|
use typenum::Prod;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
2018-05-19 23:15:15 +08:00
|
|
|
|
use base::allocator::{Allocator, Reallocator};
|
2018-05-27 03:02:24 +08:00
|
|
|
|
#[cfg(any(feature = "alloc", feature = "std"))]
|
|
|
|
|
use base::dimension::Dynamic;
|
|
|
|
|
use base::dimension::{Dim, DimName};
|
2018-05-19 23:15:15 +08:00
|
|
|
|
use base::matrix_array::MatrixArray;
|
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
|
|
|
|
use base::matrix_vec::MatrixVec;
|
|
|
|
|
use base::storage::{Storage, StorageMut};
|
|
|
|
|
use base::Scalar;
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*
|
|
|
|
|
* Allocator.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
/// An allocator based on `GenericArray` and `MatrixVec` for statically-sized and dynamically-sized
|
|
|
|
|
/// matrices respectively.
|
|
|
|
|
pub struct DefaultAllocator;
|
|
|
|
|
|
|
|
|
|
// Static - Static
|
|
|
|
|
impl<N, R, C> Allocator<N, R, C> for DefaultAllocator
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
|
|
|
|
N: Scalar,
|
|
|
|
|
R: DimName,
|
|
|
|
|
C: DimName,
|
|
|
|
|
R::Value: Mul<C::Value>,
|
|
|
|
|
Prod<R::Value, C::Value>: ArrayLength<N>,
|
|
|
|
|
{
|
2016-12-05 05:44:42 +08:00
|
|
|
|
type Buffer = MatrixArray<N, R, C>;
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
unsafe fn allocate_uninitialized(_: R, _: C) -> Self::Buffer {
|
|
|
|
|
mem::uninitialized()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
2018-02-02 19:26:35 +08:00
|
|
|
|
fn allocate_from_iterator<I: IntoIterator<Item = N>>(
|
|
|
|
|
nrows: R,
|
|
|
|
|
ncols: C,
|
|
|
|
|
iter: I,
|
|
|
|
|
) -> Self::Buffer {
|
2016-12-05 05:44:42 +08:00
|
|
|
|
let mut res = unsafe { Self::allocate_uninitialized(nrows, ncols) };
|
|
|
|
|
let mut count = 0;
|
|
|
|
|
|
|
|
|
|
for (res, e) in res.iter_mut().zip(iter.into_iter()) {
|
|
|
|
|
*res = e;
|
|
|
|
|
count += 1;
|
|
|
|
|
}
|
|
|
|
|
|
2018-02-02 19:26:35 +08:00
|
|
|
|
assert!(
|
|
|
|
|
count == nrows.value() * ncols.value(),
|
|
|
|
|
"Matrix init. from iterator: iterator not long enough."
|
|
|
|
|
);
|
2016-12-05 05:44:42 +08:00
|
|
|
|
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Dynamic - Static
|
|
|
|
|
// Dynamic - Dynamic
|
2018-05-19 23:15:15 +08:00
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
2016-12-05 05:44:42 +08:00
|
|
|
|
impl<N: Scalar, C: Dim> Allocator<N, Dynamic, C> for DefaultAllocator {
|
|
|
|
|
type Buffer = MatrixVec<N, Dynamic, C>;
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
unsafe fn allocate_uninitialized(nrows: Dynamic, ncols: C) -> Self::Buffer {
|
|
|
|
|
let mut res = Vec::new();
|
|
|
|
|
let length = nrows.value() * ncols.value();
|
|
|
|
|
res.reserve_exact(length);
|
|
|
|
|
res.set_len(length);
|
|
|
|
|
|
|
|
|
|
MatrixVec::new(nrows, ncols, res)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
2018-02-02 19:26:35 +08:00
|
|
|
|
fn allocate_from_iterator<I: IntoIterator<Item = N>>(
|
|
|
|
|
nrows: Dynamic,
|
|
|
|
|
ncols: C,
|
|
|
|
|
iter: I,
|
|
|
|
|
) -> Self::Buffer {
|
2016-12-05 05:44:42 +08:00
|
|
|
|
let it = iter.into_iter();
|
|
|
|
|
let res: Vec<N> = it.collect();
|
|
|
|
|
assert!(res.len() == nrows.value() * ncols.value(),
|
|
|
|
|
"Allocation from iterator error: the iterator did not yield the correct number of elements.");
|
|
|
|
|
|
|
|
|
|
MatrixVec::new(nrows, ncols, res)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Static - Dynamic
|
2018-05-19 23:15:15 +08:00
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
2016-12-05 05:44:42 +08:00
|
|
|
|
impl<N: Scalar, R: DimName> Allocator<N, R, Dynamic> for DefaultAllocator {
|
|
|
|
|
type Buffer = MatrixVec<N, R, Dynamic>;
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
unsafe fn allocate_uninitialized(nrows: R, ncols: Dynamic) -> Self::Buffer {
|
|
|
|
|
let mut res = Vec::new();
|
|
|
|
|
let length = nrows.value() * ncols.value();
|
|
|
|
|
res.reserve_exact(length);
|
|
|
|
|
res.set_len(length);
|
|
|
|
|
|
|
|
|
|
MatrixVec::new(nrows, ncols, res)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
2018-02-02 19:26:35 +08:00
|
|
|
|
fn allocate_from_iterator<I: IntoIterator<Item = N>>(
|
|
|
|
|
nrows: R,
|
|
|
|
|
ncols: Dynamic,
|
|
|
|
|
iter: I,
|
|
|
|
|
) -> Self::Buffer {
|
2016-12-05 05:44:42 +08:00
|
|
|
|
let it = iter.into_iter();
|
|
|
|
|
let res: Vec<N> = it.collect();
|
|
|
|
|
assert!(res.len() == nrows.value() * ncols.value(),
|
|
|
|
|
"Allocation from iterator error: the iterator did not yield the correct number of elements.");
|
|
|
|
|
|
|
|
|
|
MatrixVec::new(nrows, ncols, res)
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-08-03 01:37:44 +08:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
*
|
|
|
|
|
* Reallocator.
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
// Anything -> Static × Static
|
|
|
|
|
impl<N: Scalar, RFrom, CFrom, RTo, CTo> Reallocator<N, RFrom, CFrom, RTo, CTo> for DefaultAllocator
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
|
|
|
|
RFrom: Dim,
|
|
|
|
|
CFrom: Dim,
|
|
|
|
|
RTo: DimName,
|
|
|
|
|
CTo: DimName,
|
|
|
|
|
Self: Allocator<N, RFrom, CFrom>,
|
|
|
|
|
RTo::Value: Mul<CTo::Value>,
|
|
|
|
|
Prod<RTo::Value, CTo::Value>: ArrayLength<N>,
|
|
|
|
|
{
|
2017-08-03 01:37:44 +08:00
|
|
|
|
#[inline]
|
2018-02-02 19:26:35 +08:00
|
|
|
|
unsafe fn reallocate_copy(
|
|
|
|
|
rto: RTo,
|
|
|
|
|
cto: CTo,
|
|
|
|
|
buf: <Self as Allocator<N, RFrom, CFrom>>::Buffer,
|
|
|
|
|
) -> MatrixArray<N, RTo, CTo> {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
let mut res = <Self as Allocator<N, RTo, CTo>>::allocate_uninitialized(rto, cto);
|
|
|
|
|
|
|
|
|
|
let (rfrom, cfrom) = buf.shape();
|
|
|
|
|
|
|
|
|
|
let len_from = rfrom.value() * cfrom.value();
|
2018-02-02 19:26:35 +08:00
|
|
|
|
let len_to = rto.value() * cto.value();
|
2017-08-03 01:37:44 +08:00
|
|
|
|
ptr::copy_nonoverlapping(buf.ptr(), res.ptr_mut(), cmp::min(len_from, len_to));
|
|
|
|
|
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Static × Static -> Dynamic × Any
|
2018-05-19 23:15:15 +08:00
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
2017-08-03 01:37:44 +08:00
|
|
|
|
impl<N: Scalar, RFrom, CFrom, CTo> Reallocator<N, RFrom, CFrom, Dynamic, CTo> for DefaultAllocator
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
|
|
|
|
RFrom: DimName,
|
|
|
|
|
CFrom: DimName,
|
|
|
|
|
CTo: Dim,
|
|
|
|
|
RFrom::Value: Mul<CFrom::Value>,
|
|
|
|
|
Prod<RFrom::Value, CFrom::Value>: ArrayLength<N>,
|
|
|
|
|
{
|
2017-08-03 01:37:44 +08:00
|
|
|
|
#[inline]
|
2018-02-02 19:26:35 +08:00
|
|
|
|
unsafe fn reallocate_copy(
|
|
|
|
|
rto: Dynamic,
|
|
|
|
|
cto: CTo,
|
|
|
|
|
buf: MatrixArray<N, RFrom, CFrom>,
|
|
|
|
|
) -> MatrixVec<N, Dynamic, CTo> {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
let mut res = <Self as Allocator<N, Dynamic, CTo>>::allocate_uninitialized(rto, cto);
|
|
|
|
|
|
|
|
|
|
let (rfrom, cfrom) = buf.shape();
|
|
|
|
|
|
|
|
|
|
let len_from = rfrom.value() * cfrom.value();
|
2018-02-02 19:26:35 +08:00
|
|
|
|
let len_to = rto.value() * cto.value();
|
2017-08-03 01:37:44 +08:00
|
|
|
|
ptr::copy_nonoverlapping(buf.ptr(), res.ptr_mut(), cmp::min(len_from, len_to));
|
|
|
|
|
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Static × Static -> Static × Dynamic
|
2018-05-19 23:15:15 +08:00
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
2017-08-03 01:37:44 +08:00
|
|
|
|
impl<N: Scalar, RFrom, CFrom, RTo> Reallocator<N, RFrom, CFrom, RTo, Dynamic> for DefaultAllocator
|
2018-02-02 19:26:35 +08:00
|
|
|
|
where
|
|
|
|
|
RFrom: DimName,
|
|
|
|
|
CFrom: DimName,
|
|
|
|
|
RTo: DimName,
|
|
|
|
|
RFrom::Value: Mul<CFrom::Value>,
|
|
|
|
|
Prod<RFrom::Value, CFrom::Value>: ArrayLength<N>,
|
|
|
|
|
{
|
2017-08-03 01:37:44 +08:00
|
|
|
|
#[inline]
|
2018-02-02 19:26:35 +08:00
|
|
|
|
unsafe fn reallocate_copy(
|
|
|
|
|
rto: RTo,
|
|
|
|
|
cto: Dynamic,
|
|
|
|
|
buf: MatrixArray<N, RFrom, CFrom>,
|
|
|
|
|
) -> MatrixVec<N, RTo, Dynamic> {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
let mut res = <Self as Allocator<N, RTo, Dynamic>>::allocate_uninitialized(rto, cto);
|
|
|
|
|
|
|
|
|
|
let (rfrom, cfrom) = buf.shape();
|
|
|
|
|
|
|
|
|
|
let len_from = rfrom.value() * cfrom.value();
|
2018-02-02 19:26:35 +08:00
|
|
|
|
let len_to = rto.value() * cto.value();
|
2017-08-03 01:37:44 +08:00
|
|
|
|
ptr::copy_nonoverlapping(buf.ptr(), res.ptr_mut(), cmp::min(len_from, len_to));
|
|
|
|
|
|
|
|
|
|
res
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// All conversion from a dynamic buffer to a dynamic buffer.
|
2018-05-19 23:15:15 +08:00
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
2018-02-02 19:26:35 +08:00
|
|
|
|
impl<N: Scalar, CFrom: Dim, CTo: Dim> Reallocator<N, Dynamic, CFrom, Dynamic, CTo>
|
2018-05-19 23:15:15 +08:00
|
|
|
|
for DefaultAllocator
|
|
|
|
|
{
|
2017-08-03 01:37:44 +08:00
|
|
|
|
#[inline]
|
2018-02-02 19:26:35 +08:00
|
|
|
|
unsafe fn reallocate_copy(
|
|
|
|
|
rto: Dynamic,
|
|
|
|
|
cto: CTo,
|
|
|
|
|
buf: MatrixVec<N, Dynamic, CFrom>,
|
|
|
|
|
) -> MatrixVec<N, Dynamic, CTo> {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
let new_buf = buf.resize(rto.value() * cto.value());
|
|
|
|
|
MatrixVec::new(rto, cto, new_buf)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-19 23:15:15 +08:00
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
2018-02-02 19:26:35 +08:00
|
|
|
|
impl<N: Scalar, CFrom: Dim, RTo: DimName> Reallocator<N, Dynamic, CFrom, RTo, Dynamic>
|
2018-05-19 23:15:15 +08:00
|
|
|
|
for DefaultAllocator
|
|
|
|
|
{
|
2017-08-03 01:37:44 +08:00
|
|
|
|
#[inline]
|
2018-02-02 19:26:35 +08:00
|
|
|
|
unsafe fn reallocate_copy(
|
|
|
|
|
rto: RTo,
|
|
|
|
|
cto: Dynamic,
|
|
|
|
|
buf: MatrixVec<N, Dynamic, CFrom>,
|
|
|
|
|
) -> MatrixVec<N, RTo, Dynamic> {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
let new_buf = buf.resize(rto.value() * cto.value());
|
|
|
|
|
MatrixVec::new(rto, cto, new_buf)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-19 23:15:15 +08:00
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
2018-02-02 19:26:35 +08:00
|
|
|
|
impl<N: Scalar, RFrom: DimName, CTo: Dim> Reallocator<N, RFrom, Dynamic, Dynamic, CTo>
|
2018-05-19 23:15:15 +08:00
|
|
|
|
for DefaultAllocator
|
|
|
|
|
{
|
2017-08-03 01:37:44 +08:00
|
|
|
|
#[inline]
|
2018-02-02 19:26:35 +08:00
|
|
|
|
unsafe fn reallocate_copy(
|
|
|
|
|
rto: Dynamic,
|
|
|
|
|
cto: CTo,
|
|
|
|
|
buf: MatrixVec<N, RFrom, Dynamic>,
|
|
|
|
|
) -> MatrixVec<N, Dynamic, CTo> {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
let new_buf = buf.resize(rto.value() * cto.value());
|
|
|
|
|
MatrixVec::new(rto, cto, new_buf)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-19 23:15:15 +08:00
|
|
|
|
#[cfg(any(feature = "std", feature = "alloc"))]
|
2018-02-02 19:26:35 +08:00
|
|
|
|
impl<N: Scalar, RFrom: DimName, RTo: DimName> Reallocator<N, RFrom, Dynamic, RTo, Dynamic>
|
2018-05-19 23:15:15 +08:00
|
|
|
|
for DefaultAllocator
|
|
|
|
|
{
|
2017-08-03 01:37:44 +08:00
|
|
|
|
#[inline]
|
2018-02-02 19:26:35 +08:00
|
|
|
|
unsafe fn reallocate_copy(
|
|
|
|
|
rto: RTo,
|
|
|
|
|
cto: Dynamic,
|
|
|
|
|
buf: MatrixVec<N, RFrom, Dynamic>,
|
|
|
|
|
) -> MatrixVec<N, RTo, Dynamic> {
|
2017-08-03 01:37:44 +08:00
|
|
|
|
let new_buf = buf.resize(rto.value() * cto.value());
|
|
|
|
|
MatrixVec::new(rto, cto, new_buf)
|
|
|
|
|
}
|
|
|
|
|
}
|