Skip to content

Commit e7e8275

Browse files
committed
Introduce alternative vec_uninit2, and replace vec_uninit in eig.rs
1 parent 3d2814d commit e7e8275

File tree

2 files changed

+47
-21
lines changed

2 files changed

+47
-21
lines changed

lax/src/eig.rs

Lines changed: 35 additions & 21 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(
@@ -99,11 +100,19 @@ macro_rules! impl_eig_complex {
99100
// Hermite conjugate
100101
if jobvl.is_calc() {
101102
for c in vl.as_mut().unwrap().iter_mut() {
102-
c.im = -c.im
103+
let value = unsafe { c.assume_init_mut() };
104+
value.im = -value.im;
103105
}
104106
}
105107

106-
Ok((eigs, vr.or(vl).unwrap_or(Vec::new())))
108+
unsafe {
109+
Ok((
110+
eigs.assume_init(),
111+
vr.map(|v| v.assume_init())
112+
.or(vl.map(|v| v.assume_init()))
113+
.unwrap_or(Vec::new()),
114+
))
115+
}
107116
}
108117
}
109118
};
@@ -145,13 +154,13 @@ macro_rules! impl_eig_real {
145154
} else {
146155
(EigenVectorFlag::Not, EigenVectorFlag::Not)
147156
};
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) };
157+
let mut eig_re: Vec<MaybeUninit<Self>> = unsafe { vec_uninit2(n as usize) };
158+
let mut eig_im: Vec<MaybeUninit<Self>> = unsafe { vec_uninit2(n as usize) };
150159

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) });
160+
let mut vl: Option<Vec<MaybeUninit<Self>>> =
161+
jobvl.then(|| unsafe { vec_uninit2((n * n) as usize) });
162+
let mut vr: Option<Vec<MaybeUninit<Self>>> =
163+
jobvr.then(|| unsafe { vec_uninit2((n * n) as usize) });
155164

156165
// calc work size
157166
let mut info = 0;
@@ -178,7 +187,7 @@ macro_rules! impl_eig_real {
178187

179188
// actual ev
180189
let lwork = work_size[0].to_usize().unwrap();
181-
let mut work: Vec<Self> = unsafe { vec_uninit(lwork) };
190+
let mut work: Vec<MaybeUninit<Self>> = unsafe { vec_uninit2(lwork) };
182191
let lwork = lwork as i32;
183192
unsafe {
184193
$ev(
@@ -200,6 +209,11 @@ macro_rules! impl_eig_real {
200209
};
201210
info.as_lapack_result()?;
202211

212+
let eig_re = unsafe { eig_re.assume_init() };
213+
let eig_im = unsafe { eig_im.assume_init() };
214+
let vl = unsafe { vl.map(|v| v.assume_init()) };
215+
let vr = unsafe { vr.map(|v| v.assume_init()) };
216+
203217
// reconstruct eigenvalues
204218
let eigs: Vec<Self::Complex> = eig_re
205219
.iter()
@@ -228,14 +242,14 @@ macro_rules! impl_eig_real {
228242

229243
let n = n as usize;
230244
let v = vr.or(vl).unwrap();
231-
let mut eigvecs = unsafe { vec_uninit(n * n) };
245+
let mut eigvecs: Vec<MaybeUninit<Self::Complex>> = unsafe { vec_uninit2(n * n) };
232246
let mut col = 0;
233247
while col < n {
234248
if eig_im[col] == 0. {
235249
// The corresponding eigenvalue is real.
236250
for row in 0..n {
237251
let re = v[row + col * n];
238-
eigvecs[row + col * n] = Self::complex(re, 0.);
252+
eigvecs[row + col * n].write(Self::complex(re, 0.));
239253
}
240254
col += 1;
241255
} else {
@@ -247,14 +261,14 @@ macro_rules! impl_eig_real {
247261
if jobvl.is_calc() {
248262
im = -im;
249263
}
250-
eigvecs[row + col * n] = Self::complex(re, im);
251-
eigvecs[row + (col + 1) * n] = Self::complex(re, -im);
264+
eigvecs[row + col * n].write(Self::complex(re, im));
265+
eigvecs[row + (col + 1) * n].write(Self::complex(re, -im));
252266
}
253267
col += 2;
254268
}
255269
}
256270

257-
Ok((eigs, eigvecs))
271+
unsafe { Ok((eigs, eigvecs.assume_init())) }
258272
}
259273
}
260274
};

lax/src/lib.rs

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

0 commit comments

Comments
 (0)