Skip to content

Commit e6d03a5

Browse files
committed
Introduce alternative vec_uninit2, and replace vec_uninit in eig.rs
1 parent e35bdbb commit e6d03a5

File tree

2 files changed

+42
-19
lines changed

2 files changed

+42
-19
lines changed

lax/src/eig.rs

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,14 @@ macro_rules! impl_eig_complex {
4141
} else {
4242
(EigenVectorFlag::Not, EigenVectorFlag::Not)
4343
};
44-
let mut eigs = unsafe { vec_uninit(n as usize) };
45-
let mut rwork: Vec<Self::Real> = unsafe { vec_uninit(2 * n as usize) };
44+
let mut eigs: Vec<MaybeUninit<Self>> = unsafe { vec_uninit2(n as usize) };
45+
let mut rwork: Vec<MaybeUninit<Self::Real>> =
46+
unsafe { vec_uninit2(2 * n as usize) };
4647

47-
let mut vl: Option<Vec<Self>> =
48-
jobvl.then(|| unsafe { vec_uninit((n * n) as usize) });
49-
let mut vr: Option<Vec<Self>> =
50-
jobvr.then(|| unsafe { vec_uninit((n * n) as usize) });
48+
let mut vl: Option<Vec<MaybeUninit<Self>>> =
49+
jobvl.then(|| unsafe { vec_uninit2((n * n) as usize) });
50+
let mut vr: Option<Vec<MaybeUninit<Self>>> =
51+
jobvr.then(|| unsafe { vec_uninit2((n * n) as usize) });
5152

5253
// calc work size
5354
let mut info = 0;
@@ -74,7 +75,7 @@ macro_rules! impl_eig_complex {
7475

7576
// actal ev
7677
let lwork = work_size[0].to_usize().unwrap();
77-
let mut work: Vec<Self> = unsafe { vec_uninit(lwork) };
78+
let mut work: Vec<MaybeUninit<Self>> = unsafe { vec_uninit2(lwork) };
7879
let lwork = lwork as i32;
7980
unsafe {
8081
$ev(
@@ -96,10 +97,14 @@ macro_rules! impl_eig_complex {
9697
};
9798
info.as_lapack_result()?;
9899

100+
let eigs = unsafe { eigs.assume_init() };
101+
let vr = unsafe { vr.map(|v| v.assume_init()) };
102+
let mut vl = unsafe { vl.map(|v| v.assume_init()) };
103+
99104
// Hermite conjugate
100105
if jobvl.is_calc() {
101106
for c in vl.as_mut().unwrap().iter_mut() {
102-
c.im = -c.im
107+
c.im = -c.im;
103108
}
104109
}
105110

@@ -145,13 +150,13 @@ macro_rules! impl_eig_real {
145150
} else {
146151
(EigenVectorFlag::Not, EigenVectorFlag::Not)
147152
};
148-
let mut eig_re: Vec<Self> = unsafe { vec_uninit(n as usize) };
149-
let mut eig_im: Vec<Self> = unsafe { vec_uninit(n as usize) };
153+
let mut eig_re: Vec<MaybeUninit<Self>> = unsafe { vec_uninit2(n as usize) };
154+
let mut eig_im: Vec<MaybeUninit<Self>> = unsafe { vec_uninit2(n as usize) };
150155

151-
let mut vl: Option<Vec<Self>> =
152-
jobvl.then(|| unsafe { vec_uninit((n * n) as usize) });
153-
let mut vr: Option<Vec<Self>> =
154-
jobvr.then(|| unsafe { vec_uninit((n * n) as usize) });
156+
let mut vl: Option<Vec<MaybeUninit<Self>>> =
157+
jobvl.then(|| unsafe { vec_uninit2((n * n) as usize) });
158+
let mut vr: Option<Vec<MaybeUninit<Self>>> =
159+
jobvr.then(|| unsafe { vec_uninit2((n * n) as usize) });
155160

156161
// calc work size
157162
let mut info = 0;
@@ -178,7 +183,7 @@ macro_rules! impl_eig_real {
178183

179184
// actual ev
180185
let lwork = work_size[0].to_usize().unwrap();
181-
let mut work: Vec<Self> = unsafe { vec_uninit(lwork) };
186+
let mut work: Vec<MaybeUninit<Self>> = unsafe { vec_uninit2(lwork) };
182187
let lwork = lwork as i32;
183188
unsafe {
184189
$ev(
@@ -200,6 +205,11 @@ macro_rules! impl_eig_real {
200205
};
201206
info.as_lapack_result()?;
202207

208+
let eig_re = unsafe { eig_re.assume_init() };
209+
let eig_im = unsafe { eig_im.assume_init() };
210+
let vl = unsafe { vl.map(|v| v.assume_init()) };
211+
let vr = unsafe { vr.map(|v| v.assume_init()) };
212+
203213
// reconstruct eigenvalues
204214
let eigs: Vec<Self::Complex> = eig_re
205215
.iter()
@@ -228,14 +238,14 @@ macro_rules! impl_eig_real {
228238

229239
let n = n as usize;
230240
let v = vr.or(vl).unwrap();
231-
let mut eigvecs = unsafe { vec_uninit(n * n) };
241+
let mut eigvecs: Vec<MaybeUninit<Self::Complex>> = unsafe { vec_uninit2(n * n) };
232242
let mut col = 0;
233243
while col < n {
234244
if eig_im[col] == 0. {
235245
// The corresponding eigenvalue is real.
236246
for row in 0..n {
237247
let re = v[row + col * n];
238-
eigvecs[row + col * n] = Self::complex(re, 0.);
248+
eigvecs[row + col * n].write(Self::complex(re, 0.));
239249
}
240250
col += 1;
241251
} else {
@@ -247,12 +257,13 @@ macro_rules! impl_eig_real {
247257
if jobvl.is_calc() {
248258
im = -im;
249259
}
250-
eigvecs[row + col * n] = Self::complex(re, im);
251-
eigvecs[row + (col + 1) * n] = Self::complex(re, -im);
260+
eigvecs[row + col * n].write(Self::complex(re, im));
261+
eigvecs[row + (col + 1) * n].write(Self::complex(re, -im));
252262
}
253263
col += 2;
254264
}
255265
}
266+
let eigvecs = unsafe { eigvecs.assume_init() };
256267

257268
Ok((eigs, eigvecs))
258269
}

lax/src/lib.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,3 +281,15 @@ unsafe fn vec_uninit<T: Sized>(n: usize) -> Vec<T> {
281281
v.set_len(n);
282282
v
283283
}
284+
285+
/// Create a vector without initialization
286+
///
287+
/// Safety
288+
/// ------
289+
/// - Memory is not initialized. Do not read the memory before write.
290+
///
291+
unsafe fn vec_uninit2<T: Sized>(n: usize) -> Vec<MaybeUninit<T>> {
292+
let mut v = Vec::with_capacity(n);
293+
v.set_len(n);
294+
v
295+
}

0 commit comments

Comments
 (0)