prevent constructing `MatrixSliceMutMN` for which disjoint indices may alias the same linear index

Fixes #486.
This commit is contained in:
Jack Wrenn 2019-04-09 14:39:36 -04:00 committed by Sébastien Crozet
parent 049957ff55
commit 306f096c64
3 changed files with 34 additions and 0 deletions

View File

@ -37,6 +37,7 @@ generic-array = "0.12"
rand = { version = "0.6", default-features = false } rand = { version = "0.6", default-features = false }
num-traits = { version = "0.2", default-features = false } num-traits = { version = "0.2", default-features = false }
num-complex = { version = "0.2", default-features = false } num-complex = { version = "0.2", default-features = false }
num-rational = { version = "0.2", default-features = false }
approx = { version = "0.3", default-features = false } approx = { version = "0.3", default-features = false }
alga = { version = "0.9", default-features = false } alga = { version = "0.9", default-features = false }
matrixmultiply = { version = "0.2", optional = true } matrixmultiply = { version = "0.2", optional = true }

View File

@ -2,6 +2,7 @@ use crate::base::dimension::{Dim, DimName, Dynamic, U1};
use crate::base::matrix_slice::{SliceStorage, SliceStorageMut}; use crate::base::matrix_slice::{SliceStorage, SliceStorageMut};
use crate::base::{MatrixSliceMN, MatrixSliceMutMN, Scalar}; use crate::base::{MatrixSliceMN, MatrixSliceMutMN, Scalar};
use num_rational::Ratio;
/* /*
* *
* Slice constructors. * Slice constructors.
@ -107,6 +108,37 @@ impl<'a, N: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim>
"Matrix slice: input data buffer to small." "Matrix slice: input data buffer to small."
); );
assert!({
let nrows = nrows.value();
let ncols = ncols.value();
let rstride = rstride.value();
let cstride = cstride.value();
// `Storage::linear_index`
let index = |i, j| (i * rstride) + (j * cstride);
// The final condition of each arm is an expression in the form:
// index(i₀, j₀) != index(i₁, j₁)
// If this expression is `false`, then the values (i₀, j₀)
// and (i₁, j₁) are concrete examples of indices that would
// collide if the matrix was actually constructed.
nrows * ncols <= 1 ||
match (rstride, cstride) {
(0, 0) => index(0, 0) != index(nrows - 1, ncols - 1),
(0, _) => nrows <= 1 || index(0, 0) != index(nrows - 1, 0),
(_, 0) => ncols <= 1 || index(0, 0) != index(0, ncols - 1),
(_, _) => {
let ratio = Ratio::new(rstride, cstride);
let numer = *ratio.numer();
let denom = *ratio.denom();
nrows <= denom || ncols <= numer
|| index(0, numer) != index(denom, 0)
}
}
},
"Matrix slice: dimensions and strides result in aliased indices.");
unsafe { unsafe {
Self::from_slice_with_strides_generic_unchecked(data, 0, nrows, ncols, rstride, cstride) Self::from_slice_with_strides_generic_unchecked(data, 0, nrows, ncols, rstride, cstride)
} }

View File

@ -112,6 +112,7 @@ extern crate generic_array;
extern crate matrixmultiply; extern crate matrixmultiply;
extern crate num_complex; extern crate num_complex;
extern crate num_traits as num; extern crate num_traits as num;
extern crate num_rational;
extern crate rand; extern crate rand;
extern crate typenum; extern crate typenum;