Skip to content

Commit 87107be

Browse files
authored
Merge pull request #334 from rust-ndarray/safe-lax-vec-uninit
Safe `lax::vec_uninit`
2 parents f7356c7 + 4737b9c commit 87107be

File tree

14 files changed

+116
-110
lines changed

14 files changed

+116
-110
lines changed

lax/src/alloc.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
use cauchy::*;
2+
use std::mem::MaybeUninit;
3+
4+
/// Helper for getting pointer of slice
5+
pub(crate) trait AsPtr: Sized {
6+
type Elem;
7+
fn as_ptr(vec: &[Self]) -> *const Self::Elem;
8+
fn as_mut_ptr(vec: &mut [Self]) -> *mut Self::Elem;
9+
}
10+
11+
macro_rules! impl_as_ptr {
12+
($target:ty, $elem:ty) => {
13+
impl AsPtr for $target {
14+
type Elem = $elem;
15+
fn as_ptr(vec: &[Self]) -> *const Self::Elem {
16+
vec.as_ptr() as *const _
17+
}
18+
fn as_mut_ptr(vec: &mut [Self]) -> *mut Self::Elem {
19+
vec.as_mut_ptr() as *mut _
20+
}
21+
}
22+
};
23+
}
24+
impl_as_ptr!(i32, i32);
25+
impl_as_ptr!(f32, f32);
26+
impl_as_ptr!(f64, f64);
27+
impl_as_ptr!(c32, lapack_sys::__BindgenComplex<f32>);
28+
impl_as_ptr!(c64, lapack_sys::__BindgenComplex<f64>);
29+
impl_as_ptr!(MaybeUninit<i32>, i32);
30+
impl_as_ptr!(MaybeUninit<f32>, f32);
31+
impl_as_ptr!(MaybeUninit<f64>, f64);
32+
impl_as_ptr!(MaybeUninit<c32>, lapack_sys::__BindgenComplex<f32>);
33+
impl_as_ptr!(MaybeUninit<c64>, lapack_sys::__BindgenComplex<f64>);
34+
35+
pub(crate) trait VecAssumeInit {
36+
type Target;
37+
unsafe fn assume_init(self) -> Self::Target;
38+
}
39+
40+
impl<T> VecAssumeInit for Vec<MaybeUninit<T>> {
41+
type Target = Vec<T>;
42+
unsafe fn assume_init(self) -> Self::Target {
43+
// FIXME use Vec::into_raw_parts instead after stablized
44+
// https://doc.rust-lang.org/std/vec/struct.Vec.html#method.into_raw_parts
45+
let mut me = std::mem::ManuallyDrop::new(self);
46+
Vec::from_raw_parts(me.as_mut_ptr() as *mut T, me.len(), me.capacity())
47+
}
48+
}
49+
50+
/// Create a vector without initialization
51+
///
52+
/// Safety
53+
/// ------
54+
/// - Memory is not initialized. Do not read the memory before write.
55+
///
56+
pub(crate) fn vec_uninit<T: Sized>(n: usize) -> Vec<MaybeUninit<T>> {
57+
let mut v = Vec::with_capacity(n);
58+
unsafe {
59+
v.set_len(n);
60+
}
61+
v
62+
}

lax/src/eig.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,13 @@ macro_rules! impl_eig_complex {
4848
} else {
4949
(JobEv::None, JobEv::None)
5050
};
51-
let mut eigs: Vec<MaybeUninit<Self>> = unsafe { vec_uninit(n as usize) };
52-
let mut rwork: Vec<MaybeUninit<Self::Real>> = unsafe { vec_uninit(2 * n as usize) };
51+
let mut eigs: Vec<MaybeUninit<Self>> = vec_uninit(n as usize);
52+
let mut rwork: Vec<MaybeUninit<Self::Real>> = vec_uninit(2 * n as usize);
5353

5454
let mut vl: Option<Vec<MaybeUninit<Self>>> =
55-
jobvl.then(|| unsafe { vec_uninit((n * n) as usize) });
55+
jobvl.then(|| vec_uninit((n * n) as usize));
5656
let mut vr: Option<Vec<MaybeUninit<Self>>> =
57-
jobvr.then(|| unsafe { vec_uninit((n * n) as usize) });
57+
jobvr.then(|| vec_uninit((n * n) as usize));
5858

5959
// calc work size
6060
let mut info = 0;
@@ -81,7 +81,7 @@ macro_rules! impl_eig_complex {
8181

8282
// actal ev
8383
let lwork = work_size[0].to_usize().unwrap();
84-
let mut work: Vec<MaybeUninit<Self>> = unsafe { vec_uninit(lwork) };
84+
let mut work: Vec<MaybeUninit<Self>> = vec_uninit(lwork);
8585
let lwork = lwork as i32;
8686
unsafe {
8787
$ev(
@@ -156,13 +156,13 @@ macro_rules! impl_eig_real {
156156
} else {
157157
(JobEv::None, JobEv::None)
158158
};
159-
let mut eig_re: Vec<MaybeUninit<Self>> = unsafe { vec_uninit(n as usize) };
160-
let mut eig_im: Vec<MaybeUninit<Self>> = unsafe { vec_uninit(n as usize) };
159+
let mut eig_re: Vec<MaybeUninit<Self>> = vec_uninit(n as usize);
160+
let mut eig_im: Vec<MaybeUninit<Self>> = vec_uninit(n as usize);
161161

162162
let mut vl: Option<Vec<MaybeUninit<Self>>> =
163-
jobvl.then(|| unsafe { vec_uninit((n * n) as usize) });
163+
jobvl.then(|| vec_uninit((n * n) as usize));
164164
let mut vr: Option<Vec<MaybeUninit<Self>>> =
165-
jobvr.then(|| unsafe { vec_uninit((n * n) as usize) });
165+
jobvr.then(|| vec_uninit((n * n) as usize));
166166

167167
// calc work size
168168
let mut info = 0;
@@ -189,7 +189,7 @@ macro_rules! impl_eig_real {
189189

190190
// actual ev
191191
let lwork = work_size[0].to_usize().unwrap();
192-
let mut work: Vec<MaybeUninit<Self>> = unsafe { vec_uninit(lwork) };
192+
let mut work: Vec<MaybeUninit<Self>> = vec_uninit(lwork);
193193
let lwork = lwork as i32;
194194
unsafe {
195195
$ev(
@@ -244,7 +244,7 @@ macro_rules! impl_eig_real {
244244

245245
let n = n as usize;
246246
let v = vr.or(vl).unwrap();
247-
let mut eigvecs: Vec<MaybeUninit<Self::Complex>> = unsafe { vec_uninit(n * n) };
247+
let mut eigvecs: Vec<MaybeUninit<Self::Complex>> = vec_uninit(n * n);
248248
let mut col = 0;
249249
while col < n {
250250
if eig_im[col] == 0. {

lax/src/eigh.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,10 @@ macro_rules! impl_eigh {
5858
assert_eq!(layout.len(), layout.lda());
5959
let n = layout.len();
6060
let jobz = if calc_v { JobEv::All } else { JobEv::None };
61-
let mut eigs: Vec<MaybeUninit<Self::Real>> = unsafe { vec_uninit(n as usize) };
61+
let mut eigs: Vec<MaybeUninit<Self::Real>> = vec_uninit(n as usize);
6262

6363
$(
64-
let mut $rwork_ident: Vec<MaybeUninit<Self::Real>> = unsafe { vec_uninit(3 * n as usize - 2 as usize) };
64+
let mut $rwork_ident: Vec<MaybeUninit<Self::Real>> = vec_uninit(3 * n as usize - 2 as usize);
6565
)*
6666

6767
// calc work size
@@ -85,7 +85,7 @@ macro_rules! impl_eigh {
8585

8686
// actual ev
8787
let lwork = work_size[0].to_usize().unwrap();
88-
let mut work: Vec<MaybeUninit<Self>> = unsafe { vec_uninit(lwork) };
88+
let mut work: Vec<MaybeUninit<Self>> = vec_uninit(lwork);
8989
let lwork = lwork as i32;
9090
unsafe {
9191
$ev(
@@ -117,10 +117,10 @@ macro_rules! impl_eigh {
117117
assert_eq!(layout.len(), layout.lda());
118118
let n = layout.len();
119119
let jobz = if calc_v { JobEv::All } else { JobEv::None };
120-
let mut eigs: Vec<MaybeUninit<Self::Real>> = unsafe { vec_uninit(n as usize) };
120+
let mut eigs: Vec<MaybeUninit<Self::Real>> = vec_uninit(n as usize);
121121

122122
$(
123-
let mut $rwork_ident: Vec<MaybeUninit<Self::Real>> = unsafe { vec_uninit(3 * n as usize - 2) };
123+
let mut $rwork_ident: Vec<MaybeUninit<Self::Real>> = vec_uninit(3 * n as usize - 2);
124124
)*
125125

126126
// calc work size
@@ -147,7 +147,7 @@ macro_rules! impl_eigh {
147147

148148
// actual evg
149149
let lwork = work_size[0].to_usize().unwrap();
150-
let mut work: Vec<MaybeUninit<Self>> = unsafe { vec_uninit(lwork) };
150+
let mut work: Vec<MaybeUninit<Self>> = vec_uninit(lwork);
151151
let lwork = lwork as i32;
152152
unsafe {
153153
$evg(

lax/src/layout.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ pub fn transpose<T: Copy>(layout: MatrixLayout, input: &[T]) -> (MatrixLayout, V
202202
let n = n as usize;
203203
assert_eq!(input.len(), m * n);
204204

205-
let mut out: Vec<MaybeUninit<T>> = unsafe { vec_uninit(m * n) };
205+
let mut out: Vec<MaybeUninit<T>> = vec_uninit(m * n);
206206

207207
match layout {
208208
MatrixLayout::C { .. } => {

lax/src/least_squares.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ macro_rules! impl_least_squares {
9191
};
9292

9393
let rcond: Self::Real = -1.;
94-
let mut singular_values: Vec<MaybeUninit<Self::Real>> = unsafe { vec_uninit( k as usize) };
94+
let mut singular_values: Vec<MaybeUninit<Self::Real>> = vec_uninit( k as usize);
9595
let mut rank: i32 = 0;
9696

9797
// eval work size
@@ -124,12 +124,12 @@ macro_rules! impl_least_squares {
124124

125125
// calc
126126
let lwork = work_size[0].to_usize().unwrap();
127-
let mut work: Vec<MaybeUninit<Self>> = unsafe { vec_uninit(lwork) };
127+
let mut work: Vec<MaybeUninit<Self>> = vec_uninit(lwork);
128128
let liwork = iwork_size[0].to_usize().unwrap();
129-
let mut iwork: Vec<MaybeUninit<i32>> = unsafe { vec_uninit(liwork) };
129+
let mut iwork: Vec<MaybeUninit<i32>> = vec_uninit(liwork);
130130
$(
131131
let lrwork = $rwork[0].to_usize().unwrap();
132-
let mut $rwork: Vec<MaybeUninit<Self::Real>> = unsafe { vec_uninit(lrwork) };
132+
let mut $rwork: Vec<MaybeUninit<Self::Real>> = vec_uninit(lrwork);
133133
)*
134134
unsafe {
135135
$gelsd(

lax/src/lib.rs

Lines changed: 2 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ pub mod error;
8484
pub mod flags;
8585
pub mod layout;
8686

87+
mod alloc;
8788
mod cholesky;
8889
mod eig;
8990
mod eigh;
@@ -113,6 +114,7 @@ pub use self::svddc::*;
113114
pub use self::triangular::*;
114115
pub use self::tridiagonal::*;
115116

117+
use self::alloc::*;
116118
use cauchy::*;
117119
use std::mem::MaybeUninit;
118120

@@ -140,61 +142,3 @@ impl Lapack for f32 {}
140142
impl Lapack for f64 {}
141143
impl Lapack for c32 {}
142144
impl Lapack for c64 {}
143-
144-
/// Helper for getting pointer of slice
145-
pub(crate) trait AsPtr: Sized {
146-
type Elem;
147-
fn as_ptr(vec: &[Self]) -> *const Self::Elem;
148-
fn as_mut_ptr(vec: &mut [Self]) -> *mut Self::Elem;
149-
}
150-
151-
macro_rules! impl_as_ptr {
152-
($target:ty, $elem:ty) => {
153-
impl AsPtr for $target {
154-
type Elem = $elem;
155-
fn as_ptr(vec: &[Self]) -> *const Self::Elem {
156-
vec.as_ptr() as *const _
157-
}
158-
fn as_mut_ptr(vec: &mut [Self]) -> *mut Self::Elem {
159-
vec.as_mut_ptr() as *mut _
160-
}
161-
}
162-
};
163-
}
164-
impl_as_ptr!(i32, i32);
165-
impl_as_ptr!(f32, f32);
166-
impl_as_ptr!(f64, f64);
167-
impl_as_ptr!(c32, lapack_sys::__BindgenComplex<f32>);
168-
impl_as_ptr!(c64, lapack_sys::__BindgenComplex<f64>);
169-
impl_as_ptr!(MaybeUninit<i32>, i32);
170-
impl_as_ptr!(MaybeUninit<f32>, f32);
171-
impl_as_ptr!(MaybeUninit<f64>, f64);
172-
impl_as_ptr!(MaybeUninit<c32>, lapack_sys::__BindgenComplex<f32>);
173-
impl_as_ptr!(MaybeUninit<c64>, lapack_sys::__BindgenComplex<f64>);
174-
175-
pub(crate) trait VecAssumeInit {
176-
type Target;
177-
unsafe fn assume_init(self) -> Self::Target;
178-
}
179-
180-
impl<T> VecAssumeInit for Vec<MaybeUninit<T>> {
181-
type Target = Vec<T>;
182-
unsafe fn assume_init(self) -> Self::Target {
183-
// FIXME use Vec::into_raw_parts instead after stablized
184-
// https://doc.rust-lang.org/std/vec/struct.Vec.html#method.into_raw_parts
185-
let mut me = std::mem::ManuallyDrop::new(self);
186-
Vec::from_raw_parts(me.as_mut_ptr() as *mut T, me.len(), me.capacity())
187-
}
188-
}
189-
190-
/// Create a vector without initialization
191-
///
192-
/// Safety
193-
/// ------
194-
/// - Memory is not initialized. Do not read the memory before write.
195-
///
196-
unsafe fn vec_uninit<T: Sized>(n: usize) -> Vec<MaybeUninit<T>> {
197-
let mut v = Vec::with_capacity(n);
198-
v.set_len(n);
199-
v
200-
}

lax/src/opnorm.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ macro_rules! impl_opnorm {
1919
MatrixLayout::C { .. } => t.transpose(),
2020
};
2121
let mut work: Vec<MaybeUninit<Self::Real>> = if matches!(t, NormType::Infinity) {
22-
unsafe { vec_uninit(m as usize) }
22+
vec_uninit(m as usize)
2323
} else {
2424
Vec::new()
2525
};

lax/src/qr.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ macro_rules! impl_qr {
2525
let m = l.lda();
2626
let n = l.len();
2727
let k = m.min(n);
28-
let mut tau = unsafe { vec_uninit(k as usize) };
28+
let mut tau = vec_uninit(k as usize);
2929

3030
// eval work size
3131
let mut info = 0;
@@ -62,7 +62,7 @@ macro_rules! impl_qr {
6262

6363
// calc
6464
let lwork = work_size[0].to_usize().unwrap();
65-
let mut work: Vec<MaybeUninit<Self>> = unsafe { vec_uninit(lwork) };
65+
let mut work: Vec<MaybeUninit<Self>> = vec_uninit(lwork);
6666
unsafe {
6767
match l {
6868
MatrixLayout::F { .. } => {
@@ -136,7 +136,7 @@ macro_rules! impl_qr {
136136

137137
// calc
138138
let lwork = work_size[0].to_usize().unwrap();
139-
let mut work: Vec<MaybeUninit<Self>> = unsafe { vec_uninit(lwork) };
139+
let mut work: Vec<MaybeUninit<Self>> = vec_uninit(lwork);
140140
unsafe {
141141
match l {
142142
MatrixLayout::F { .. } => $gqr(

lax/src/rcond.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ macro_rules! impl_rcond_real {
1717
let mut rcond = Self::Real::zero();
1818
let mut info = 0;
1919

20-
let mut work: Vec<MaybeUninit<Self>> = unsafe { vec_uninit(4 * n as usize) };
21-
let mut iwork: Vec<MaybeUninit<i32>> = unsafe { vec_uninit(n as usize) };
20+
let mut work: Vec<MaybeUninit<Self>> = vec_uninit(4 * n as usize);
21+
let mut iwork: Vec<MaybeUninit<i32>> = vec_uninit(n as usize);
2222
let norm_type = match l {
2323
MatrixLayout::C { .. } => NormType::Infinity,
2424
MatrixLayout::F { .. } => NormType::One,
@@ -54,8 +54,8 @@ macro_rules! impl_rcond_complex {
5454
let (n, _) = l.size();
5555
let mut rcond = Self::Real::zero();
5656
let mut info = 0;
57-
let mut work: Vec<MaybeUninit<Self>> = unsafe { vec_uninit(2 * n as usize) };
58-
let mut rwork: Vec<MaybeUninit<Self::Real>> = unsafe { vec_uninit(2 * n as usize) };
57+
let mut work: Vec<MaybeUninit<Self>> = vec_uninit(2 * n as usize);
58+
let mut rwork: Vec<MaybeUninit<Self::Real>> = vec_uninit(2 * n as usize);
5959
let norm_type = match l {
6060
MatrixLayout::C { .. } => NormType::Infinity,
6161
MatrixLayout::F { .. } => NormType::One,

lax/src/solve.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ macro_rules! impl_solve {
7575
return Ok(Vec::new());
7676
}
7777
let k = ::std::cmp::min(row, col);
78-
let mut ipiv = unsafe { vec_uninit(k as usize) };
78+
let mut ipiv = vec_uninit(k as usize);
7979
let mut info = 0;
8080
unsafe {
8181
$getrf(
@@ -117,7 +117,7 @@ macro_rules! impl_solve {
117117

118118
// actual
119119
let lwork = work_size[0].to_usize().unwrap();
120-
let mut work: Vec<MaybeUninit<Self>> = unsafe { vec_uninit(lwork) };
120+
let mut work: Vec<MaybeUninit<Self>> = vec_uninit(lwork);
121121
unsafe {
122122
$getri(
123123
&l.len(),

lax/src/solveh.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ macro_rules! impl_solveh {
5858
impl Solveh_ for $scalar {
5959
fn bk(l: MatrixLayout, uplo: UPLO, a: &mut [Self]) -> Result<Pivot> {
6060
let (n, _) = l.size();
61-
let mut ipiv = unsafe { vec_uninit(n as usize) };
61+
let mut ipiv = vec_uninit(n as usize);
6262
if n == 0 {
6363
return Ok(Vec::new());
6464
}
@@ -82,7 +82,7 @@ macro_rules! impl_solveh {
8282

8383
// actual
8484
let lwork = work_size[0].to_usize().unwrap();
85-
let mut work: Vec<MaybeUninit<Self>> = unsafe { vec_uninit(lwork) };
85+
let mut work: Vec<MaybeUninit<Self>> = vec_uninit(lwork);
8686
unsafe {
8787
$trf(
8888
uplo.as_ptr(),
@@ -103,7 +103,7 @@ macro_rules! impl_solveh {
103103
fn invh(l: MatrixLayout, uplo: UPLO, a: &mut [Self], ipiv: &Pivot) -> Result<()> {
104104
let (n, _) = l.size();
105105
let mut info = 0;
106-
let mut work: Vec<MaybeUninit<Self>> = unsafe { vec_uninit(n as usize) };
106+
let mut work: Vec<MaybeUninit<Self>> = vec_uninit(n as usize);
107107
unsafe {
108108
$tri(
109109
uplo.as_ptr(),

0 commit comments

Comments
 (0)