Skip to content

Commit e292e0c

Browse files
authored
Merge pull request #81 from termoshtt/simplify_solve_mod
Refactoring Factorized{H}
2 parents 5f8ca6b + d8b5f5c commit e292e0c

File tree

2 files changed

+93
-63
lines changed

2 files changed

+93
-63
lines changed

src/solve.rs

Lines changed: 46 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ pub use lapack_traits::{Pivot, Transpose};
7070
///
7171
/// If you plan to solve many equations with the same `A` matrix but different
7272
/// `b` vectors, it's faster to factor the `A` matrix once using the
73-
/// `Factorize` trait, and then solve using the `Factorized` struct.
73+
/// `Factorize` trait, and then solve using the `LUFactorized` struct.
7474
pub trait Solve<A: Scalar> {
7575
/// Solves a system of linear equations `A * x = b` where `A` is `self`, `b`
7676
/// is the argument, and `x` is the successful result.
@@ -125,15 +125,15 @@ pub trait Solve<A: Scalar> {
125125
}
126126

127127
/// Represents the LU factorization of a matrix `A` as `A = P*L*U`.
128-
pub struct Factorized<S: Data> {
128+
pub struct LUFactorized<S: Data> {
129129
/// The factors `L` and `U`; the unit diagonal elements of `L` are not
130130
/// stored.
131131
pub a: ArrayBase<S, Ix2>,
132132
/// The pivot indices that define the permutation matrix `P`.
133133
pub ipiv: Pivot,
134134
}
135135

136-
impl<A, S> Solve<A> for Factorized<S>
136+
impl<A, S> Solve<A> for LUFactorized<S>
137137
where
138138
A: Scalar,
139139
S: Data<Elem = A>,
@@ -213,46 +213,29 @@ where
213213
}
214214
}
215215

216-
impl<A, S> Factorized<S>
217-
where
218-
A: Scalar,
219-
S: DataMut<Elem = A>,
220-
{
221-
/// Computes the inverse of the factorized matrix.
222-
pub fn into_inverse(mut self) -> Result<ArrayBase<S, Ix2>> {
223-
unsafe {
224-
A::inv(
225-
self.a.square_layout()?,
226-
self.a.as_allocated_mut()?,
227-
&self.ipiv,
228-
)?
229-
};
230-
Ok(self.a)
231-
}
232-
}
233216

234217
/// An interface for computing LU factorizations of matrix refs.
235218
pub trait Factorize<S: Data> {
236219
/// Computes the LU factorization `A = P*L*U`, where `P` is a permutation
237220
/// matrix.
238-
fn factorize(&self) -> Result<Factorized<S>>;
221+
fn factorize(&self) -> Result<LUFactorized<S>>;
239222
}
240223

241224
/// An interface for computing LU factorizations of matrices.
242225
pub trait FactorizeInto<S: Data> {
243226
/// Computes the LU factorization `A = P*L*U`, where `P` is a permutation
244227
/// matrix.
245-
fn factorize_into(self) -> Result<Factorized<S>>;
228+
fn factorize_into(self) -> Result<LUFactorized<S>>;
246229
}
247230

248231
impl<A, S> FactorizeInto<S> for ArrayBase<S, Ix2>
249232
where
250233
A: Scalar,
251234
S: DataMut<Elem = A>,
252235
{
253-
fn factorize_into(mut self) -> Result<Factorized<S>> {
236+
fn factorize_into(mut self) -> Result<LUFactorized<S>> {
254237
let ipiv = unsafe { A::lu(self.layout()?, self.as_allocated_mut()?)? };
255-
Ok(Factorized {
238+
Ok(LUFactorized {
256239
a: self,
257240
ipiv: ipiv,
258241
})
@@ -264,10 +247,10 @@ where
264247
A: Scalar,
265248
Si: Data<Elem = A>,
266249
{
267-
fn factorize(&self) -> Result<Factorized<OwnedRepr<A>>> {
250+
fn factorize(&self) -> Result<LUFactorized<OwnedRepr<A>>> {
268251
let mut a: Array2<A> = replicate(self);
269252
let ipiv = unsafe { A::lu(a.layout()?, a.as_allocated_mut()?)? };
270-
Ok(Factorized { a: a, ipiv: ipiv })
253+
Ok(LUFactorized { a: a, ipiv: ipiv })
271254
}
272255
}
273256

@@ -285,6 +268,41 @@ pub trait InverseInto {
285268
fn inv_into(self) -> Result<Self::Output>;
286269
}
287270

271+
impl<A, S> InverseInto for LUFactorized<S>
272+
where
273+
A: Scalar,
274+
S: DataMut<Elem = A>,
275+
{
276+
type Output = ArrayBase<S, Ix2>;
277+
278+
fn inv_into(mut self) -> Result<ArrayBase<S, Ix2>> {
279+
unsafe {
280+
A::inv(
281+
self.a.square_layout()?,
282+
self.a.as_allocated_mut()?,
283+
&self.ipiv,
284+
)?
285+
};
286+
Ok(self.a)
287+
}
288+
}
289+
290+
impl<A, S> Inverse for LUFactorized<S>
291+
where
292+
A: Scalar,
293+
S: Data<Elem = A>,
294+
{
295+
type Output = Array2<A>;
296+
297+
fn inv(&self) -> Result<Array2<A>> {
298+
let f = LUFactorized {
299+
a: replicate(&self.a),
300+
ipiv: self.ipiv.clone(),
301+
};
302+
f.inv_into()
303+
}
304+
}
305+
288306
impl<A, S> InverseInto for ArrayBase<S, Ix2>
289307
where
290308
A: Scalar,
@@ -294,7 +312,7 @@ where
294312

295313
fn inv_into(self) -> Result<Self::Output> {
296314
let f = self.factorize_into()?;
297-
f.into_inverse()
315+
f.inv_into()
298316
}
299317
}
300318

@@ -307,6 +325,6 @@ where
307325

308326
fn inv(&self) -> Result<Self::Output> {
309327
let f = self.factorize()?;
310-
f.into_inverse()
328+
f.inv_into()
311329
}
312330
}

src/solveh.rs

Lines changed: 47 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ pub use lapack_traits::{Pivot, UPLO};
6363
/// If you plan to solve many equations with the same Hermitian (or real
6464
/// symmetric) coefficient matrix `A` but different `b` vectors, it's faster to
6565
/// factor the `A` matrix once using the `FactorizeH` trait, and then solve
66-
/// using the `FactorizedH` struct.
66+
/// using the `BKFactorized` struct.
6767
pub trait SolveH<A: Scalar> {
6868
/// Solves a system of linear equations `A * x = b` with Hermitian (or real
6969
/// symmetric) matrix `A`, where `A` is `self`, `b` is the argument, and
@@ -89,12 +89,12 @@ pub trait SolveH<A: Scalar> {
8989

9090
/// Represents the Bunch–Kaufman factorization of a Hermitian (or real
9191
/// symmetric) matrix as `A = P * U * D * U^H * P^T`.
92-
pub struct FactorizedH<S: Data> {
92+
pub struct BKFactorized<S: Data> {
9393
pub a: ArrayBase<S, Ix2>,
9494
pub ipiv: Pivot,
9595
}
9696

97-
impl<A, S> SolveH<A> for FactorizedH<S>
97+
impl<A, S> SolveH<A> for BKFactorized<S>
9898
where
9999
A: Scalar,
100100
S: Data<Elem = A>,
@@ -131,54 +131,30 @@ where
131131
}
132132

133133

134-
impl<A, S> FactorizedH<S>
135-
where
136-
A: Scalar,
137-
S: DataMut<Elem = A>,
138-
{
139-
/// Computes the inverse of the factorized matrix.
140-
///
141-
/// **Warning: The inverse is stored only in the upper triangular portion
142-
/// of the result matrix!** If you want the lower triangular portion to be
143-
/// correct, you must fill it in according to the results in the upper
144-
/// triangular portion.
145-
pub fn into_inverseh(mut self) -> Result<ArrayBase<S, Ix2>> {
146-
unsafe {
147-
A::invh(
148-
self.a.square_layout()?,
149-
UPLO::Upper,
150-
self.a.as_allocated_mut()?,
151-
&self.ipiv,
152-
)?
153-
};
154-
Ok(self.a)
155-
}
156-
}
157-
158134
/// An interface for computing the Bunch–Kaufman factorization of Hermitian (or
159135
/// real symmetric) matrix refs.
160136
pub trait FactorizeH<S: Data> {
161137
/// Computes the Bunch–Kaufman factorization of a Hermitian (or real
162138
/// symmetric) matrix.
163-
fn factorizeh(&self) -> Result<FactorizedH<S>>;
139+
fn factorizeh(&self) -> Result<BKFactorized<S>>;
164140
}
165141

166142
/// An interface for computing the Bunch–Kaufman factorization of Hermitian (or
167143
/// real symmetric) matrices.
168144
pub trait FactorizeHInto<S: Data> {
169145
/// Computes the Bunch–Kaufman factorization of a Hermitian (or real
170146
/// symmetric) matrix.
171-
fn factorizeh_into(self) -> Result<FactorizedH<S>>;
147+
fn factorizeh_into(self) -> Result<BKFactorized<S>>;
172148
}
173149

174150
impl<A, S> FactorizeHInto<S> for ArrayBase<S, Ix2>
175151
where
176152
A: Scalar,
177153
S: DataMut<Elem = A>,
178154
{
179-
fn factorizeh_into(mut self) -> Result<FactorizedH<S>> {
155+
fn factorizeh_into(mut self) -> Result<BKFactorized<S>> {
180156
let ipiv = unsafe { A::bk(self.layout()?, UPLO::Upper, self.as_allocated_mut()?)? };
181-
Ok(FactorizedH {
157+
Ok(BKFactorized {
182158
a: self,
183159
ipiv: ipiv,
184160
})
@@ -190,10 +166,10 @@ where
190166
A: Scalar,
191167
Si: Data<Elem = A>,
192168
{
193-
fn factorizeh(&self) -> Result<FactorizedH<OwnedRepr<A>>> {
169+
fn factorizeh(&self) -> Result<BKFactorized<OwnedRepr<A>>> {
194170
let mut a: Array2<A> = replicate(self);
195171
let ipiv = unsafe { A::bk(a.layout()?, UPLO::Upper, a.as_allocated_mut()?)? };
196-
Ok(FactorizedH { a: a, ipiv: ipiv })
172+
Ok(BKFactorized { a: a, ipiv: ipiv })
197173
}
198174
}
199175

@@ -221,6 +197,42 @@ pub trait InverseHInto {
221197
fn invh_into(self) -> Result<Self::Output>;
222198
}
223199

200+
impl<A, S> InverseHInto for BKFactorized<S>
201+
where
202+
A: Scalar,
203+
S: DataMut<Elem = A>,
204+
{
205+
type Output = ArrayBase<S, Ix2>;
206+
207+
fn invh_into(mut self) -> Result<ArrayBase<S, Ix2>> {
208+
unsafe {
209+
A::invh(
210+
self.a.square_layout()?,
211+
UPLO::Upper,
212+
self.a.as_allocated_mut()?,
213+
&self.ipiv,
214+
)?
215+
};
216+
Ok(self.a)
217+
}
218+
}
219+
220+
impl<A, S> InverseH for BKFactorized<S>
221+
where
222+
A: Scalar,
223+
S: Data<Elem = A>,
224+
{
225+
type Output = Array2<A>;
226+
227+
fn invh(&self) -> Result<Self::Output> {
228+
let f = BKFactorized {
229+
a: replicate(&self.a),
230+
ipiv: self.ipiv.clone(),
231+
};
232+
f.invh_into()
233+
}
234+
}
235+
224236
impl<A, S> InverseHInto for ArrayBase<S, Ix2>
225237
where
226238
A: Scalar,
@@ -230,7 +242,7 @@ where
230242

231243
fn invh_into(self) -> Result<Self::Output> {
232244
let f = self.factorizeh_into()?;
233-
f.into_inverseh()
245+
f.invh_into()
234246
}
235247
}
236248

@@ -243,6 +255,6 @@ where
243255

244256
fn invh(&self) -> Result<Self::Output> {
245257
let f = self.factorizeh()?;
246-
f.into_inverseh()
258+
f.invh_into()
247259
}
248260
}

0 commit comments

Comments
 (0)