Fixed some more blatant issues

This commit is contained in:
Violeta Hernández 2021-07-17 13:53:01 -05:00
parent fa1ed9683b
commit 7e1b2f81b3
5 changed files with 35 additions and 36 deletions

View File

@ -942,7 +942,8 @@ impl<T: Clone> OMatrix<T, Dynamic, Dynamic> {
where where
DefaultAllocator: Reallocator<T, Dynamic, Dynamic, Dynamic, Dynamic>, DefaultAllocator: Reallocator<T, Dynamic, Dynamic, Dynamic, Dynamic>,
{ {
// BEEEP!!!! BEEEEEEEP!!! // IMPORTANT TODO: this method is still UB, and we should decide how to
// update the API to take it into account.
let placeholder = unsafe { let placeholder = unsafe {
Matrix::new_uninitialized_generic(Dynamic::new(0), Dynamic::new(0)).assume_init() Matrix::new_uninitialized_generic(Dynamic::new(0), Dynamic::new(0)).assume_init()

View File

@ -5,7 +5,7 @@ use std::io::{Result as IOResult, Write};
use approx::{AbsDiffEq, RelativeEq, UlpsEq}; use approx::{AbsDiffEq, RelativeEq, UlpsEq};
use std::any::TypeId; use std::any::TypeId;
use std::cmp::Ordering; use std::cmp::Ordering;
use std::fmt; use std::fmt;use std::ptr;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem::{self, ManuallyDrop, MaybeUninit}; use std::mem::{self, ManuallyDrop, MaybeUninit};
@ -341,6 +341,7 @@ impl<T, R, C, S> Matrix<T, R, C, S> {
} }
} }
/// # Memory manipulation methods.
impl<T, R: Dim, C: Dim> OMatrix<T, R, C> impl<T, R: Dim, C: Dim> OMatrix<T, R, C>
where where
DefaultAllocator: Allocator<T, R, C>, DefaultAllocator: Allocator<T, R, C>,
@ -365,6 +366,7 @@ where
} }
} }
/// # More memory manipulation methods.
impl<T, R: Dim, C: Dim> OMatrix<MaybeUninit<T>, R, C> impl<T, R: Dim, C: Dim> OMatrix<MaybeUninit<T>, R, C>
where where
DefaultAllocator: Allocator<T, R, C>, DefaultAllocator: Allocator<T, R, C>,
@ -377,6 +379,18 @@ where
<DefaultAllocator as Allocator<T, R, C>>::assume_init(self.data), <DefaultAllocator as Allocator<T, R, C>>::assume_init(self.data),
) )
} }
/// Assumes a matrix's entries to be initialized, and drops them. This allows the
/// buffer to be safely reused.
pub fn reinitialize(&mut self) {
for i in 0..self.nrows() {
for j in 0..self.ncols() {
unsafe {
ptr::drop_in_place(self.get_unchecked_mut((i, j)));
}
}
}
}
} }
impl<T, R: Dim, C: Dim, S> Matrix<MaybeUninit<T>, R, C, S> { impl<T, R: Dim, C: Dim, S> Matrix<MaybeUninit<T>, R, C, S> {
@ -447,21 +461,6 @@ impl<T, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
unsafe { Self::from_data_statically_unchecked(data) } unsafe { Self::from_data_statically_unchecked(data) }
} }
/// Creates a new uninitialized matrix with the given uninitialized data
pub unsafe fn from_uninitialized_data(data: MaybeUninit<S>) -> MaybeUninit<Self> {
// BEEP BEEP this doesn't seem good
let res: Matrix<T, R, C, MaybeUninit<S>> = Matrix {
data,
_phantoms: PhantomData,
};
let res: MaybeUninit<Matrix<T, R, C, MaybeUninit<S>>> = MaybeUninit::new(res);
// safety: since we wrap the inner MaybeUninit in an outer MaybeUninit above, the fact that the `data` field is partially-uninitialized is still opaque.
// with s/transmute_copy/transmute/, rustc claims that `MaybeUninit<Matrix<T, R, C, MaybeUninit<S>>>` may be of a different size from `MaybeUninit<Matrix<T, R, C, S>>`
// but MaybeUninit's documentation says "MaybeUninit<T> is guaranteed to have the same size, alignment, and ABI as T", which implies those types should be the same size
let res: MaybeUninit<Matrix<T, R, C, S>> = mem::transmute_copy(&res);
res
}
/// The shape of this matrix returned as the tuple (number of rows, number of columns). /// The shape of this matrix returned as the tuple (number of rows, number of columns).
/// ///
/// # Examples: /// # Examples:
@ -941,24 +940,22 @@ impl<T, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
/// Folds a function `f` on each entry of `self`. /// Folds a function `f` on each entry of `self`.
#[inline] #[inline]
#[must_use] #[must_use]
pub fn fold<Acc>(&self, init: Acc, mut f: impl FnMut(Acc, T) -> Acc) -> Acc pub fn fold<Acc>(&self, mut init: Acc, mut f: impl FnMut(Acc, T) -> Acc) -> Acc
where where
T: Clone, T: Clone,
{ {
let (nrows, ncols) = self.data.shape(); let (nrows, ncols) = self.data.shape();
let mut res = init;
for j in 0..ncols.value() { for j in 0..ncols.value() {
for i in 0..nrows.value() { for i in 0..nrows.value() {
unsafe { unsafe {
let a = self.data.get_unchecked(i, j).clone(); let a = self.data.get_unchecked(i, j).clone();
res = f(res, a) init = f(init, a)
} }
} }
} }
res init
} }
/// Folds a function `f` on each pairs of entries from `self` and `rhs`. /// Folds a function `f` on each pairs of entries from `self` and `rhs`.
@ -967,7 +964,7 @@ impl<T, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
pub fn zip_fold<T2: Clone, R2: Dim, C2: Dim, S2, Acc>( pub fn zip_fold<T2: Clone, R2: Dim, C2: Dim, S2, Acc>(
&self, &self,
rhs: &Matrix<T2, R2, C2, S2>, rhs: &Matrix<T2, R2, C2, S2>,
init: Acc, mut init: Acc,
mut f: impl FnMut(Acc, T, T2) -> Acc, mut f: impl FnMut(Acc, T, T2) -> Acc,
) -> Acc ) -> Acc
where where
@ -976,7 +973,6 @@ impl<T, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
ShapeConstraint: SameNumberOfRows<R, R2> + SameNumberOfColumns<C, C2>, ShapeConstraint: SameNumberOfRows<R, R2> + SameNumberOfColumns<C, C2>,
{ {
let (nrows, ncols) = self.data.shape(); let (nrows, ncols) = self.data.shape();
let mut res = init;
assert_eq!( assert_eq!(
(nrows.value(), ncols.value()), (nrows.value(), ncols.value()),
@ -989,12 +985,12 @@ impl<T, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
unsafe { unsafe {
let a = self.data.get_unchecked(i, j).clone(); let a = self.data.get_unchecked(i, j).clone();
let b = rhs.data.get_unchecked(i, j).clone(); let b = rhs.data.get_unchecked(i, j).clone();
res = f(res, a, b) init = f(init, a, b)
} }
} }
} }
res init
} }
/// Replaces each component of `self` by the result of a closure `f` applied on it. /// Replaces each component of `self` by the result of a closure `f` applied on it.

View File

@ -59,7 +59,6 @@ impl<T, R: Dim, C: Dim, S: Storage<T, R, C>> Matrix<T, R, C, S> {
} }
/// Returns a column vector resulting from the folding of `f` on each column of this matrix. /// Returns a column vector resulting from the folding of `f` on each column of this matrix.
// BEEEEP!!!! Pretty sure there's something fishy here.
#[inline] #[inline]
#[must_use] #[must_use]
pub fn compress_columns( pub fn compress_columns(

View File

@ -42,23 +42,24 @@ where
// extra allocations. // extra allocations.
let (nrows, ncols) = self.data.shape(); let (nrows, ncols) = self.data.shape();
let mut multiplier = self.clone_owned(); let mut multiplier = self.clone_owned();
let mut buf = Matrix::new_uninitialized_generic(nrows, ncols);
// TODO: ACTUALLY MAKE BUF USEFUL! BEEEEEEEEP!!
// Exponentiation by squares. // Exponentiation by squares.
loop { loop {
if e % two == one { if e % two == one {
let mut buf = Matrix::new_uninitialized_generic(nrows, ncols);
self.mul_to(&multiplier, &mut buf); self.mul_to(&multiplier, &mut buf);
let buf = unsafe { buf.assume_init() }; unsafe {
self.copy_from(&buf); self.copy_from(&buf.assume_init_ref());
}
buf.reinitialize();
} }
e /= two; e /= two;
let mut buf = Matrix::new_uninitialized_generic(nrows, ncols);
multiplier.mul_to(&multiplier, &mut buf); multiplier.mul_to(&multiplier, &mut buf);
let buf = unsafe { buf.assume_init() }; unsafe {
multiplier.copy_from(&buf); multiplier.copy_from(&buf.assume_init_ref());
}
buf.reinitialize();
if e == zero { if e == zero {
return true; return true;

View File

@ -264,7 +264,9 @@ where
pub fn new_uninitialized_generic(nrows: R, ncols: C, nvals: usize) -> Self { pub fn new_uninitialized_generic(nrows: R, ncols: C, nvals: usize) -> Self {
let mut i = Vec::with_capacity(nvals); let mut i = Vec::with_capacity(nvals);
//BEEP BEEP!!!! UNDEFINED BEHAVIOR ALERT!!! BEEP BEEEP!!! // IMPORTANT TODO: this method is still UB, and we should decide how to
// update the API to take it into account.
unsafe { unsafe {
i.set_len(nvals); i.set_len(nvals);
} }