Skip to content

Commit 13fc915

Browse files
committed
Merge branch 'master' into index_type
Conflicts: src/hermite.rs src/matrix.rs src/square.rs
2 parents 7452d8c + b53fe39 commit 13fc915

File tree

12 files changed

+392
-33
lines changed

12 files changed

+392
-33
lines changed

.travis.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
language: rust
2+
sudo: required
3+
4+
rust:
5+
- stable
6+
- beta
7+
- nightly
8+
9+
os:
10+
- linux
11+
12+
cache: cargo
13+
14+
matrix:
15+
allow-failures:
16+
- rust: nightly
17+
18+
script:
19+
- cargo test -vv --no-default-features --features=$FEATURE
20+
21+
addons:
22+
apt:
23+
sources:
24+
- kubuntu-backports
25+
26+
packages:
27+
- cmake
28+
- gfortran

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "ndarray-linalg"
3-
version = "0.1.2"
3+
version = "0.1.3"
44
authors = ["Toshiki Teramura <[email protected]>"]
55

66
description = "Linear algebra package for rust-ndarray using LAPACK"

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
ndarray-linalg [![Crate](http://meritbadge.herokuapp.com/ndarray-linalg)](https://crates.io/crates/ndarray-linalg) [![docs.rs](https://docs.rs/ndarray-linalg/badge.svg)](https://docs.rs/ndarray-linalg) [![wercker status](https://app.wercker.com/status/a45df26fa97eab7debf53b32fc576b35/s/master "wercker status")](https://app.wercker.com/project/byKey/a45df26fa97eab7debf53b32fc576b35)
1+
ndarray-linalg [![Crate](http://meritbadge.herokuapp.com/ndarray-linalg)](https://crates.io/crates/ndarray-linalg) [![docs.rs](https://docs.rs/ndarray-linalg/badge.svg)](https://docs.rs/ndarray-linalg) [![Build Status](https://travis-ci.org/termoshtt/ndarray-linalg.svg?branch=master)](https://travis-ci.org/termoshtt/ndarray-linalg)
22
===============
33
Linear algebra package for [rust-ndarray](https://github.com/bluss/rust-ndarray) using LAPACK via [stainless-steel/lapack](https://github.com/stainless-steel/lapack)
44

src/cholesky.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
2+
use lapack::c::*;
3+
use error::LapackError;
4+
5+
pub trait ImplCholesky: Sized {
6+
fn cholesky(layout: Layout, n: usize, a: Vec<Self>) -> Result<Vec<Self>, LapackError>;
7+
}
8+
9+
macro_rules! impl_cholesky {
10+
($scalar:ty, $potrf:path) => {
11+
impl ImplCholesky for $scalar {
12+
fn cholesky(layout: Layout, n: usize, mut a: Vec<Self>) -> Result<Vec<Self>, LapackError> {
13+
let info = $potrf(layout, b'U', n as i32, &mut a, n as i32);
14+
if info == 0 {
15+
Ok(a)
16+
} else {
17+
Err(From::from(info))
18+
}
19+
}
20+
}
21+
}} // end macro_rules
22+
23+
impl_cholesky!(f64, dpotrf);
24+
impl_cholesky!(f32, spotrf);

src/hermite.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
//! Define trait for Hermite matrices
22
33
use ndarray::{Ix2, Array, LinalgScalar};
4+
use std::fmt::Debug;
45
use num_traits::float::Float;
6+
use lapack::c::Layout;
57

68
use matrix::Matrix;
79
use square::SquareMatrix;
@@ -11,17 +13,20 @@ use qr::ImplQR;
1113
use svd::ImplSVD;
1214
use norm::ImplNorm;
1315
use solve::ImplSolve;
16+
use cholesky::ImplCholesky;
1417

1518
/// Methods for Hermite matrix
1619
pub trait HermiteMatrix: SquareMatrix + Matrix {
1720
/// eigenvalue decomposition
1821
fn eigh(self) -> Result<(Self::Vector, Self), LinalgError>;
1922
/// symmetric square root of Hermite matrix
2023
fn ssqrt(self) -> Result<Self, LinalgError>;
24+
/// Cholesky factorization
25+
fn cholesky(self) -> Result<Self, LinalgError>;
2126
}
2227

2328
impl<A> HermiteMatrix for Array<A, Ix2>
24-
where A: ImplQR + ImplSVD + ImplNorm + ImplSolve + ImplEigh + LinalgScalar + Float
29+
where A: ImplQR + ImplSVD + ImplNorm + ImplSolve + ImplEigh + ImplCholesky + LinalgScalar + Float + Debug
2530
{
2631
fn eigh(self) -> Result<(Self::Vector, Self), LinalgError> {
2732
try!(self.check_square());
@@ -42,4 +47,21 @@ impl<A> HermiteMatrix for Array<A, Ix2>
4247
}
4348
Ok(v.dot(&res))
4449
}
50+
fn cholesky(self) -> Result<Self, LinalgError> {
51+
try!(self.check_square());
52+
println!("layout = {:?}", self.layout());
53+
let (n, _) = self.size();
54+
let layout = self.layout();
55+
let a = try!(ImplCholesky::cholesky(layout, n, self.into_raw_vec()));
56+
let mut c = match layout {
57+
Layout::RowMajor => Array::from_vec(a).into_shape((n, n)).unwrap(),
58+
Layout::ColumnMajor => Array::from_vec(a).into_shape((n, n)).unwrap().reversed_axes(),
59+
};
60+
for ((i, j), val) in c.indexed_iter_mut() {
61+
if i > j {
62+
*val = A::zero();
63+
}
64+
}
65+
Ok(c)
66+
}
4567
}

src/lib.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,24 @@
1010
//! - [operator norm for L1 norm](matrix/trait.Matrix.html#tymethod.norm_1)
1111
//! - [operator norm for L-inf norm](matrix/trait.Matrix.html#tymethod.norm_i)
1212
//! - [Frobeiuns norm](matrix/trait.Matrix.html#tymethod.norm_f)
13+
//! - [LU factorization](matrix/trait.Matrix.html#tymethod.lu)
1314
//!
1415
//! SquareMatrix
1516
//! -------------
1617
//! - [inverse of matrix](square/trait.SquareMatrix.html#tymethod.inv)
1718
//! - [trace of matrix](square/trait.SquareMatrix.html#tymethod.trace)
1819
//! - [WIP] eigenvalue
19-
//! - [WIP] LU factorization
2020
//!
2121
//! HermiteMatrix
2222
//! --------------
2323
//! - [eigenvalue analysis](hermite/trait.HermiteMatrix.html#tymethod.eigh)
2424
//! - [symmetric square root](hermite/trait.HermiteMatrix.html#tymethod.ssqrt)
25-
//! - [WIP] Cholesky factorization
25+
//! - [Cholesky factorization](hermite/trait.HermiteMatrix.html#tymethod.cholesky)
2626
2727
extern crate lapack;
28-
extern crate ndarray;
2928
extern crate num_traits;
29+
#[macro_use(s)]
30+
extern crate ndarray;
3031

3132
pub mod prelude;
3233
pub mod error;
@@ -40,3 +41,4 @@ pub mod svd;
4041
pub mod eigh;
4142
pub mod norm;
4243
pub mod solve;
44+
pub mod cholesky;

src/matrix.rs

Lines changed: 79 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,26 @@
11
//! Define trait for general matrix
22
33
use std::cmp::min;
4-
use ndarray::{Ix1, Ix2, Array, Axis, LinalgScalar};
4+
use std::fmt::Debug;
5+
use ndarray::prelude::*;
6+
use ndarray::LinalgScalar;
7+
use lapack::c::Layout;
58

69
use error::LapackError;
710
use qr::ImplQR;
811
use svd::ImplSVD;
912
use norm::ImplNorm;
13+
use solve::ImplSolve;
1014

1115
/// Methods for general matrices
1216
pub trait Matrix: Sized {
1317
type Scalar;
1418
type Vector;
19+
type Permutator;
1520
/// number of (rows, columns)
1621
fn size(&self) -> (usize, usize);
22+
/// Layout (C/Fortran) of matrix
23+
fn layout(&self) -> Layout;
1724
/// Operator norm for L-1 norm
1825
fn norm_1(&self) -> Self::Scalar;
1926
/// Operator norm for L-inf norm
@@ -24,16 +31,35 @@ pub trait Matrix: Sized {
2431
fn svd(self) -> Result<(Self, Self::Vector, Self), LapackError>;
2532
/// QR decomposition
2633
fn qr(self) -> Result<(Self, Self), LapackError>;
34+
/// LU decomposition
35+
fn lu(self) -> Result<(Self::Permutator, Self, Self), LapackError>;
36+
/// permutate matrix (inplace)
37+
fn permutate(&mut self, p: &Self::Permutator);
38+
/// permutate matrix (outplace)
39+
fn permutated(mut self, p: &Self::Permutator) -> Self {
40+
self.permutate(p);
41+
self
42+
}
2743
}
2844

2945
impl<A> Matrix for Array<A, Ix2>
30-
where A: ImplQR + ImplSVD + ImplNorm + LinalgScalar
46+
where A: ImplQR + ImplSVD + ImplNorm + ImplSolve + LinalgScalar + Debug
3147
{
3248
type Scalar = A;
33-
type Vector = Array<A, Ix1>;
49+
type Vector = Array<A, Ix>;
50+
type Permutator = Vec<i32>;
51+
3452
fn size(&self) -> (usize, usize) {
3553
(self.rows(), self.cols())
3654
}
55+
fn layout(&self) -> Layout {
56+
let strides = self.strides();
57+
if strides[0] < strides[1] {
58+
Layout::ColumnMajor
59+
} else {
60+
Layout::RowMajor
61+
}
62+
}
3763
fn norm_1(&self) -> Self::Scalar {
3864
let (m, n) = self.size();
3965
let strides = self.strides();
@@ -111,4 +137,54 @@ impl<A> Matrix for Array<A, Ix2>
111137
}
112138
Ok((qm, rm))
113139
}
140+
fn lu(self) -> Result<(Self::Permutator, Self, Self), LapackError> {
141+
let (n, m) = self.size();
142+
println!("n={}, m={}", n, m);
143+
let k = min(n, m);
144+
let (p, mut a) = match self.layout() {
145+
Layout::ColumnMajor => {
146+
println!("ColumnMajor");
147+
let (p, l) = ImplSolve::lu(self.layout(), n, m, self.clone().into_raw_vec())?;
148+
(p, Array::from_vec(l).into_shape((m, n)).unwrap().reversed_axes())
149+
}
150+
Layout::RowMajor => {
151+
println!("RowMajor");
152+
let (p, l) = ImplSolve::lu(self.layout(), n, m, self.clone().into_raw_vec())?;
153+
(p, Array::from_vec(l).into_shape((n, m)).unwrap())
154+
}
155+
};
156+
println!("a (after LU) = \n{:?}", &a);
157+
let mut lm = Array::zeros((n, k));
158+
for ((i, j), val) in lm.indexed_iter_mut() {
159+
if i > j {
160+
*val = a[(i, j)];
161+
} else if i == j {
162+
*val = A::one();
163+
}
164+
}
165+
for ((i, j), val) in a.indexed_iter_mut() {
166+
if i > j {
167+
*val = A::zero();
168+
}
169+
}
170+
let am = if n > k {
171+
a.slice(s![0..k as isize, ..]).to_owned()
172+
} else {
173+
a
174+
};
175+
println!("am = \n{:?}", am);
176+
Ok((p, lm, am))
177+
}
178+
fn permutate(&mut self, ipiv: &Self::Permutator) {
179+
let (_, m) = self.size();
180+
for (i, j_) in ipiv.iter().enumerate().rev() {
181+
let j = (j_ - 1) as usize;
182+
if i == j {
183+
continue;
184+
}
185+
for k in 0..m {
186+
self.swap((i, k), (j, k));
187+
}
188+
}
189+
}
114190
}

src/solve.rs

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,55 @@
11
//! Implement linear solver and inverse matrix
22
3-
use lapack::fortran::*;
4-
use num_traits::Zero;
3+
use lapack::c::*;
4+
use std::cmp::min;
55

66
use error::LapackError;
77

88
pub trait ImplSolve: Sized {
9-
fn inv(size: usize, mut a: Vec<Self>) -> Result<Vec<Self>, LapackError>;
9+
fn inv(layout: Layout, size: usize, a: Vec<Self>) -> Result<Vec<Self>, LapackError>;
10+
fn lu(layout: Layout,
11+
m: usize,
12+
n: usize,
13+
a: Vec<Self>)
14+
-> Result<(Vec<i32>, Vec<Self>), LapackError>;
1015
}
1116

1217
macro_rules! impl_solve {
13-
($scalar:ty, $getrf:path, $getri:path) => {
18+
($scalar:ty, $getrf:path, $getri:path, $laswp:path) => {
1419
impl ImplSolve for $scalar {
15-
fn inv(size: usize, mut a: Vec<Self>) -> Result<Vec<Self>, LapackError> {
20+
fn inv(layout: Layout, size: usize, mut a: Vec<Self>) -> Result<Vec<Self>, LapackError> {
1621
let n = size as i32;
1722
let lda = n;
1823
let mut ipiv = vec![0; size];
19-
let mut info = 0;
20-
$getrf(n, n, &mut a, lda, &mut ipiv, &mut info);
24+
let info = $getrf(layout, n, n, &mut a, lda, &mut ipiv);
2125
if info != 0 {
2226
return Err(From::from(info));
2327
}
24-
let lwork = n;
25-
let mut work = vec![Self::zero(); size];
26-
$getri(n, &mut a, lda, &mut ipiv, &mut work, lwork, &mut info);
28+
let info = $getri(layout, n, &mut a, lda, &mut ipiv);
2729
if info == 0 {
2830
Ok(a)
2931
} else {
3032
Err(From::from(info))
3133
}
3234
}
35+
fn lu(layout: Layout, m: usize, n: usize, mut a: Vec<Self>) -> Result<(Vec<i32>, Vec<Self>), LapackError> {
36+
let m = m as i32;
37+
let n = n as i32;
38+
let k = min(m, n);
39+
let lda = match layout {
40+
Layout::ColumnMajor => m,
41+
Layout::RowMajor => n,
42+
};
43+
let mut ipiv = vec![0; k as usize];
44+
let info = $getrf(layout, m, n, &mut a, lda, &mut ipiv);
45+
if info == 0 {
46+
Ok((ipiv, a))
47+
} else {
48+
Err(From::from(info))
49+
}
50+
}
3351
}
3452
}} // end macro_rules
3553

36-
impl_solve!(f64, dgetrf, dgetri);
37-
impl_solve!(f32, sgetrf, sgetri);
54+
impl_solve!(f64, dgetrf, dgetri, dlaswp);
55+
impl_solve!(f32, sgetrf, sgetri, slaswp);

src/square.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
//! Define trait for Hermite matrices
22
33
use ndarray::{Ix2, Array, LinalgScalar};
4+
use std::fmt::Debug;
45
use num_traits::float::Float;
56

67
use matrix::Matrix;
@@ -16,7 +17,6 @@ use solve::ImplSolve;
1617
/// but does not assure that the matrix is square.
1718
/// If not square, `NotSquareError` will be thrown.
1819
pub trait SquareMatrix: Matrix {
19-
// fn lu(self) -> (Self, Self);
2020
// fn eig(self) -> (Self::Vector, Self);
2121
/// inverse matrix
2222
fn inv(self) -> Result<Self, LinalgError>;
@@ -37,13 +37,13 @@ pub trait SquareMatrix: Matrix {
3737
}
3838

3939
impl<A> SquareMatrix for Array<A, Ix2>
40-
where A: ImplQR + ImplNorm + ImplSVD + ImplSolve + LinalgScalar + Float
40+
where A: ImplQR + ImplNorm + ImplSVD + ImplSolve + LinalgScalar + Float + Debug
4141
{
4242
fn inv(self) -> Result<Self, LinalgError> {
4343
try!(self.check_square());
4444
let (n, _) = self.size();
4545
let is_fortran_align = self.strides()[0] > self.strides()[1];
46-
let a = try!(ImplSolve::inv(n, self.into_raw_vec()));
46+
let a = try!(ImplSolve::inv(self.layout(), n, self.into_raw_vec()));
4747
let m = Array::from_vec(a).into_shape((n, n)).unwrap();
4848
if is_fortran_align {
4949
Ok(m)

0 commit comments

Comments
 (0)