Skip to content

Commit dfd42c3

Browse files
committed
Split LAPACK error into Computational failure and invalid value
1 parent 700fcec commit dfd42c3

File tree

16 files changed

+145
-170
lines changed

16 files changed

+145
-170
lines changed

ndarray-linalg/src/error.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,17 @@ pub enum LinalgError {
1212
#[error("Not square: rows({}) != cols({})", rows, cols)]
1313
NotSquare { rows: i32, cols: i32 },
1414

15-
/// LAPACK subroutine returns non-zero code
16-
#[error("LAPACK: return_code = {}", return_code)]
17-
Lapack { return_code: i32 },
15+
#[error(
16+
"Invalid value for LAPACK subroutine {}-th argument",
17+
-return_code
18+
)]
19+
LapackInvalidValue { return_code: i32 },
20+
21+
#[error(
22+
"Comutational failure in LAPACK subroutine: return_code = {}",
23+
return_code
24+
)]
25+
LapackComputationalFailure { return_code: i32 },
1826

1927
/// Strides of the array is not supported
2028
#[error("invalid stride: s0={}, s1={}", s0, s1)]

ndarray-linalg/src/lapack/cholesky.rs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
//! Cholesky decomposition
22
3-
use crate::error::*;
4-
use crate::layout::MatrixLayout;
5-
use crate::types::*;
6-
7-
use super::{into_result, UPLO};
3+
use super::*;
4+
use crate::{error::*, layout::MatrixLayout, types::*};
85

96
pub trait Cholesky_: Sized {
107
/// Cholesky: wrapper of `*potrf`
@@ -25,14 +22,14 @@ macro_rules! impl_cholesky {
2522
impl Cholesky_ for $scalar {
2623
unsafe fn cholesky(l: MatrixLayout, uplo: UPLO, a: &mut [Self]) -> Result<()> {
2724
let (n, _) = l.size();
28-
let info = $trf(l.lapacke_layout(), uplo as u8, n, a, n);
29-
into_result(info, ())
25+
$trf(l.lapacke_layout(), uplo as u8, n, a, n).as_lapack_result()?;
26+
Ok(())
3027
}
3128

3229
unsafe fn inv_cholesky(l: MatrixLayout, uplo: UPLO, a: &mut [Self]) -> Result<()> {
3330
let (n, _) = l.size();
34-
let info = $tri(l.lapacke_layout(), uplo as u8, n, a, l.lda());
35-
into_result(info, ())
31+
$tri(l.lapacke_layout(), uplo as u8, n, a, l.lda()).as_lapack_result()?;
32+
Ok(())
3633
}
3734

3835
unsafe fn solve_cholesky(
@@ -44,8 +41,9 @@ macro_rules! impl_cholesky {
4441
let (n, _) = l.size();
4542
let nrhs = 1;
4643
let ldb = 1;
47-
let info = $trs(l.lapacke_layout(), uplo as u8, n, nrhs, a, l.lda(), b, ldb);
48-
into_result(info, ())
44+
$trs(l.lapacke_layout(), uplo as u8, n, nrhs, a, l.lda(), b, ldb)
45+
.as_lapack_result()?;
46+
Ok(())
4947
}
5048
}
5149
};

ndarray-linalg/src/lapack/eig.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
//! Eigenvalue decomposition for general matrices
22
3+
use super::*;
4+
use crate::{error::*, layout::MatrixLayout, types::*};
35
use num_traits::Zero;
46

5-
use crate::error::*;
6-
use crate::layout::MatrixLayout;
7-
use crate::types::*;
8-
9-
use super::into_result;
10-
117
/// Wraps `*geev` for real/complex
128
pub trait Eig_: Scalar {
139
unsafe fn eig(
@@ -30,7 +26,7 @@ macro_rules! impl_eig_complex {
3026
let mut w = vec![Self::Complex::zero(); n as usize];
3127
let mut vl = Vec::new();
3228
let mut vr = vec![Self::Complex::zero(); (n * n) as usize];
33-
let info = $ev(
29+
$ev(
3430
l.lapacke_layout(),
3531
b'N',
3632
jobvr,
@@ -42,8 +38,9 @@ macro_rules! impl_eig_complex {
4238
n,
4339
&mut vr,
4440
n,
45-
);
46-
into_result(info, (w, vr))
41+
)
42+
.as_lapack_result()?;
43+
Ok((w, vr))
4744
}
4845
}
4946
};
@@ -82,6 +79,7 @@ macro_rules! impl_eig_real {
8279
.zip(wi.iter())
8380
.map(|(&r, &i)| Self::Complex::new(r, i))
8481
.collect();
82+
8583
// If the j-th eigenvalue is real, then
8684
// eigenvector = [ vr[j], vr[j+n], vr[j+2*n], ... ].
8785
//
@@ -121,7 +119,8 @@ macro_rules! impl_eig_real {
121119
})
122120
.collect();
123121

124-
into_result(info, (w, v))
122+
info.as_lapack_result()?;
123+
Ok((w, v))
125124
}
126125
}
127126
};

ndarray-linalg/src/lapack/eigh.rs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
//! Eigenvalue decomposition for Hermite matrices
22
3+
use super::*;
4+
use crate::{error::*, layout::MatrixLayout, types::*};
35
use num_traits::Zero;
46

5-
use crate::error::*;
6-
use crate::layout::MatrixLayout;
7-
use crate::types::*;
8-
9-
use super::{into_result, UPLO};
10-
117
/// Wraps `*syev` for real and `*heev` for complex
128
pub trait Eigh_: Scalar {
139
unsafe fn eigh(
@@ -37,8 +33,9 @@ macro_rules! impl_eigh {
3733
let (n, _) = l.size();
3834
let jobz = if calc_v { b'V' } else { b'N' };
3935
let mut w = vec![Self::Real::zero(); n as usize];
40-
let info = $ev(l.lapacke_layout(), jobz, uplo as u8, n, &mut a, n, &mut w);
41-
into_result(info, w)
36+
$ev(l.lapacke_layout(), jobz, uplo as u8, n, &mut a, n, &mut w)
37+
.as_lapack_result()?;
38+
Ok(w)
4239
}
4340

4441
unsafe fn eigh_generalized(
@@ -51,7 +48,7 @@ macro_rules! impl_eigh {
5148
let (n, _) = l.size();
5249
let jobz = if calc_v { b'V' } else { b'N' };
5350
let mut w = vec![Self::Real::zero(); n as usize];
54-
let info = $evg(
51+
$evg(
5552
l.lapacke_layout(),
5653
1,
5754
jobz,
@@ -62,8 +59,9 @@ macro_rules! impl_eigh {
6259
&mut b,
6360
n,
6461
&mut w,
65-
);
66-
into_result(info, w)
62+
)
63+
.as_lapack_result()?;
64+
Ok(w)
6765
}
6866
}
6967
};

ndarray-linalg/src/lapack/least_squares.rs

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
//! Least squares
22
3+
use super::*;
4+
use crate::{error::*, layout::MatrixLayout, types::*};
35
use ndarray::{ErrorKind, ShapeError};
46
use num_traits::Zero;
57

6-
use crate::error::*;
7-
use crate::layout::MatrixLayout;
8-
use crate::types::*;
9-
10-
use super::into_result;
11-
128
/// Result of LeastSquares
139
pub struct LeastSquaresOutput<A: Scalar> {
1410
/// singular values
@@ -53,7 +49,7 @@ macro_rules! impl_least_squares {
5349
let mut singular_values: Vec<Self::Real> = vec![Self::Real::zero(); k as usize];
5450
let mut rank: i32 = 0;
5551

56-
let status = $gelsd(
52+
$gelsd(
5753
a_layout.lapacke_layout(),
5854
m,
5955
n,
@@ -67,15 +63,13 @@ macro_rules! impl_least_squares {
6763
&mut singular_values,
6864
rcond,
6965
&mut rank,
70-
);
71-
72-
into_result(
73-
status,
74-
LeastSquaresOutput {
75-
singular_values,
76-
rank,
77-
},
7866
)
67+
.as_lapack_result()?;
68+
69+
Ok(LeastSquaresOutput {
70+
singular_values,
71+
rank,
72+
})
7973
}
8074

8175
unsafe fn least_squares_nrhs(
@@ -99,7 +93,7 @@ macro_rules! impl_least_squares {
9993
let mut singular_values: Vec<Self::Real> = vec![Self::Real::zero(); k as usize];
10094
let mut rank: i32 = 0;
10195

102-
let status = $gelsd(
96+
$gelsd(
10397
a_layout.lapacke_layout(),
10498
m,
10599
n,
@@ -111,15 +105,12 @@ macro_rules! impl_least_squares {
111105
&mut singular_values,
112106
rcond,
113107
&mut rank,
114-
);
115-
116-
into_result(
117-
status,
118-
LeastSquaresOutput {
119-
singular_values,
120-
rank,
121-
},
122108
)
109+
.as_lapack_result()?;
110+
Ok(LeastSquaresOutput {
111+
singular_values,
112+
rank,
113+
})
123114
}
124115
}
125116
};

ndarray-linalg/src/lapack/mod.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,19 @@ impl Lapack for f64 {}
5454
impl Lapack for c32 {}
5555
impl Lapack for c64 {}
5656

57-
pub fn into_result<T>(return_code: i32, val: T) -> Result<T> {
58-
if return_code == 0 {
59-
Ok(val)
60-
} else {
61-
Err(LinalgError::Lapack { return_code })
57+
trait AsLapackResult {
58+
fn as_lapack_result(self) -> Result<()>;
59+
}
60+
61+
impl AsLapackResult for i32 {
62+
fn as_lapack_result(self) -> Result<()> {
63+
if self > 0 {
64+
return Err(LinalgError::LapackComputationalFailure { return_code: self });
65+
}
66+
if self < 0 {
67+
return Err(LinalgError::LapackInvalidValue { return_code: self });
68+
}
69+
Ok(())
6270
}
6371
}
6472

ndarray-linalg/src/lapack/qr.rs

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,10 @@
11
//! QR decomposition
22
3+
use super::*;
4+
use crate::{error::*, layout::MatrixLayout, types::*};
35
use num_traits::Zero;
46
use std::cmp::min;
57

6-
use crate::error::*;
7-
use crate::layout::MatrixLayout;
8-
use crate::types::*;
9-
10-
use super::into_result;
11-
128
/// Wraps `*geqrf` and `*orgqr` (`*ungqr` for complex numbers)
139
pub trait QR_: Sized {
1410
unsafe fn householder(l: MatrixLayout, a: &mut [Self]) -> Result<Vec<Self>>;
@@ -23,15 +19,15 @@ macro_rules! impl_qr {
2319
let (row, col) = l.size();
2420
let k = min(row, col);
2521
let mut tau = vec![Self::zero(); k as usize];
26-
let info = $qrf(l.lapacke_layout(), row, col, &mut a, l.lda(), &mut tau);
27-
into_result(info, tau)
22+
$qrf(l.lapacke_layout(), row, col, &mut a, l.lda(), &mut tau).as_lapack_result()?;
23+
Ok(tau)
2824
}
2925

3026
unsafe fn q(l: MatrixLayout, mut a: &mut [Self], tau: &[Self]) -> Result<()> {
3127
let (row, col) = l.size();
3228
let k = min(row, col);
33-
let info = $gqr(l.lapacke_layout(), row, k, k, &mut a, l.lda(), &tau);
34-
into_result(info, ())
29+
$gqr(l.lapacke_layout(), row, k, k, &mut a, l.lda(), &tau).as_lapack_result()?;
30+
Ok(())
3531
}
3632

3733
unsafe fn qr(l: MatrixLayout, a: &mut [Self]) -> Result<Vec<Self>> {

ndarray-linalg/src/lapack/solve.rs

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,9 @@
11
//! Solve linear problem using LU decomposition
22
3+
use super::*;
4+
use crate::{error::*, layout::MatrixLayout, types::*};
35
use num_traits::Zero;
46

5-
use crate::error::*;
6-
use crate::layout::MatrixLayout;
7-
use crate::types::*;
8-
9-
use super::NormType;
10-
use super::{into_result, Pivot, Transpose};
11-
127
/// Wraps `*getrf`, `*getri`, and `*getrs`
138
pub trait Solve_: Scalar + Sized {
149
/// Computes the LU factorization of a general `m x n` matrix `a` using
@@ -41,29 +36,30 @@ macro_rules! impl_solve {
4136
let (row, col) = l.size();
4237
let k = ::std::cmp::min(row, col);
4338
let mut ipiv = vec![0; k as usize];
44-
let info = $getrf(l.lapacke_layout(), row, col, a, l.lda(), &mut ipiv);
45-
into_result(info, ipiv)
39+
$getrf(l.lapacke_layout(), row, col, a, l.lda(), &mut ipiv).as_lapack_result()?;
40+
Ok(ipiv)
4641
}
4742

4843
unsafe fn inv(l: MatrixLayout, a: &mut [Self], ipiv: &Pivot) -> Result<()> {
4944
let (n, _) = l.size();
50-
let info = $getri(l.lapacke_layout(), n, a, l.lda(), ipiv);
51-
into_result(info, ())
45+
$getri(l.lapacke_layout(), n, a, l.lda(), ipiv).as_lapack_result()?;
46+
Ok(())
5247
}
5348

5449
unsafe fn rcond(l: MatrixLayout, a: &[Self], anorm: Self::Real) -> Result<Self::Real> {
5550
let (n, _) = l.size();
5651
let mut rcond = Self::Real::zero();
57-
let info = $gecon(
52+
$gecon(
5853
l.lapacke_layout(),
5954
NormType::One as u8,
6055
n,
6156
a,
6257
l.lda(),
6358
anorm,
6459
&mut rcond,
65-
);
66-
into_result(info, rcond)
60+
)
61+
.as_lapack_result()?;
62+
Ok(rcond)
6763
}
6864

6965
unsafe fn solve(
@@ -76,7 +72,7 @@ macro_rules! impl_solve {
7672
let (n, _) = l.size();
7773
let nrhs = 1;
7874
let ldb = 1;
79-
let info = $getrs(
75+
$getrs(
8076
l.lapacke_layout(),
8177
t as u8,
8278
n,
@@ -86,8 +82,9 @@ macro_rules! impl_solve {
8682
ipiv,
8783
b,
8884
ldb,
89-
);
90-
into_result(info, ())
85+
)
86+
.as_lapack_result()?;
87+
Ok(())
9188
}
9289
}
9390
};

0 commit comments

Comments
 (0)