diff --git a/.travis.yml b/.travis.yml
index 16e2fbde..ac5dcd74 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,6 +11,12 @@ matrix:
allow_failures:
- rust: nightly
- rust: beta
+addons:
+ apt:
+ packages:
+ - gfortran
+ - libblas3gf
+ - liblapack3gf
script:
- rustc --version
- cargo --version
@@ -19,3 +25,8 @@ script:
- cargo build --verbose --features serde-serialize
- cargo build --verbose --features abomonation-serialize
- cargo test --verbose --features "arbitrary serde-serialize abomonation-serialize"
+ - cd nalgebra-lapack; cargo test --verbose
+
+env:
+ matrix:
+ - CARGO_FEATURE_SYSTEM_NETLIB=1 CARGO_FEATURE_EXCLUDE_LAPACKE=1 CARGO_FEATURE_EXCLUDE_CBLAS=1
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2a9575d0..9cdabd87 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,20 +4,117 @@ documented here.
This project adheres to [Semantic Versioning](http://semver.org/).
-## [0.13.0] - WIP
+
+## [0.13.0]
+
+The **nalgebra-lapack** crate has been updated. This now includes a broad range
+matrix decompositions using LAPACK bindings.
+
+### Breaking semantic change
+ * The implementation of slicing with steps now matches the documentation.
+ Before, step identified the number to add to pass from one column/row index
+ to the next one. This made 0 step invalid. Now (and on the documentation so
+ far), the step is the number of ignored row/columns between each
+ row/column. Thus, a step of 0 means that no row/column is ignored. For
+ example, a step of, say, 3 on previous versions should now bet set to 2.
+
+### Modified
+ * The trait `Axpy` has been replaced by a metod `.axpy`.
+ * The alias `MatrixNM` is now deprecated. Use `MatrixMN` instead (we
+ reordered M and N to be in alphabetical order).
+ * In-place componentwise multiplication and division
+ `.component_mul_mut(...)` and `.component_div_mut(...)` have bee deprecated
+ for a future renaming. Use `.component_mul_assign(...)` and
+ `.component_div_assign(...)` instead.
+
### Added
+ * `alga::general::Real` is now re-exported by nalgebra.
+ elements.)
+ * `::zeros(...)` that creates a matrix filled with zeroes.
+ * `::from_partial_diagonal(...)` that creates a matrix from diagonal elements.
+ The matrix can be rectangular. If not enough elements are provided, the rest
+ of the diagonal is set to 0.
+ * `.conjugate_transpose()` computes the transposed conjugate of a
+ complex matrix.
+ * `.conjugate_transpose_to(...)` computes the transposed conjugate of a
+ complex matrix. The result written into a user-provided matrix.
+ * `.transpose_to(...)` is the same as `.transpose()` but stores the result in
+ the provided matrix.
+ * `.conjugate_transpose_to(...)` is the same as `.conjugate_transpose()` but
+ stores the result in the provided matrix.
+ * Implements `IntoIterator` for `&Matrix`, `&mut Matrix` and `Matrix`.
+ * `.mul_to(...)` multiplies two matrices and stores the result to the given buffer.
+ * `.tr_mul_to(...)` left-multiplies `self.transpose()` to another matrix and stores the result to the given buffer.
+ * `.add_scalar(...)` that adds a scalar to each component of a matrix.
+ * `.add_scalar_mut(...)` that adds in-place a scalar to each component of a matrix.
* `.kronecker(a, b)` computes the kronecker product (i.e. matrix tensor
product) of two matrices.
- * `.set_row(i, row)` sets the i-th row of the matrix.
- * `.set_column(j, column)` sets the i-th column of the matrix.
+ * `.apply(f)` replaces each component of a matrix with the results of the
+ closure `f` called on each of them.
+Pure Rust implementation of some Blas operations:
+
+ * `.iamax()` retuns the index of the maximum value of a vector.
+ * `.axpy(...)` computes `self = a * x + b * self`.
+ * `.gemv(...)` computes `self = alpha * a * x + beta * self` with a matrix and vector `a` and `x`.
+ * `.ger(...)` computes `self = alpha * x^t * y + beta * self` where `x` and `y` are vectors.
+ * `.gemm(...)` computes `self = alpha * a * b + beta * self` where `a` and `b` are matrices.
+ * `.gemv_symm(...)` is the same as `.gemv` except that `self` is assumed symmetric.
+ * `.ger_symm(...)` is the same as `.ger` except that `self` is assumed symmetric.
+
+New slicing methods:
+ * `.rows_range(...)` that retrieves a reference to a range of rows.
+ * `.rows_range_mut(...)` that retrieves a mutable reference to a range of rows.
+ * `.columns_range(...)` that retrieves a reference to a range of columns.
+ * `.columns_range_mut(...)` that retrieves a mutable reference to a range of columns.
+
+Matrix decompositions implemented in pure Rust:
+ * Cholesky, SVD, LU, QR, Hessenberg, Schur, Symmetric eigendecompositions,
+ Bidiagonal, Symmetric tridiagonal
+ * Computation of householder reflectors and givens rotations.
+
+Matrix edition:
+ * `.upper_triangle()` extracts the upper triangle of a matrix, including the diagonal.
+ * `.lower_triangle()` extracts the lower triangle of a matrix, including the diagonal.
+ * `.fill(...)` fills the matrix with a single value.
+ * `.fill_with_identity(...)` fills the matrix with the identity.
+ * `.fill_diagonal(...)` fills the matrix diagonal with a single value.
+ * `.fill_row(...)` fills a selected matrix row with a single value.
+ * `.fill_column(...)` fills a selected matrix column with a single value.
+ * `.set_diagonal(...)` sets the matrix diagonal.
+ * `.set_row(...)` sets a selected row.
+ * `.set_column(...)` sets a selected column.
+ * `.fill_lower_triangle(...)` fills some sub-diagonals bellow the main diagonal with a value.
+ * `.fill_upper_triangle(...)` fills some sub-diagonals above the main diagonal with a value.
+ * `.swap_rows(...)` swaps two rows.
+ * `.swap_columns(...)` swaps two columns.
+
+Column removal:
+ * `.remove_column(...)` removes one column.
+ * `.remove_fixed_columns(...)` removes `D` columns.
+ * `.remove_columns(...)` removes a number of columns known at run-time.
+
+Row removal:
+ * `.remove_row(...)` removes one row.
+ * `.remove_fixed_rows(...)` removes `D` rows.
+ * `.remove_rows(...)` removes a number of rows known at run-time.
+
+Column insertion:
+ * `.insert_column(...)` adds one column at the given position.
+ * `.insert_fixed_columns(...)` adds `D` columns at the given position.
+ * `.insert_columns(...)` adds at the given position a number of columns known at run-time.
+
+Row insertion:
+ * `.insert_row(...)` adds one row at the given position.
+ * `.insert_fixed_rows(...)` adds `D` rows at the given position.
+ * `.insert_rows(...)` adds at the given position a number of rows known at run-time.
## [0.12.0]
The main change of this release is the update of the dependency serde to 1.0.
### Added
- * `.trace()` that computes the trace of a matrix (i.e., the sum of its
- diagonal elements.)
+ * `.trace()` that computes the trace of a matrix (the sum of its diagonal
+ elements.)
## [0.11.0]
The [website](http://nalgebra.org) has been fully rewritten and gives a good
diff --git a/Cargo.toml b/Cargo.toml
index 9110c8c1..7551baae 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -16,22 +16,23 @@ name = "nalgebra"
path = "src/lib.rs"
[features]
-arbitrary = [ "quickcheck" ]
+arbitrary = [ "quickcheck" ]
serde-serialize = [ "serde", "serde_derive", "num-complex/serde" ]
abomonation-serialize = [ "abomonation" ]
+debug = [ ]
[dependencies]
-typenum = "1.4"
-generic-array = "0.8"
-rand = "0.3"
-num-traits = "0.1"
-num-complex = "0.1"
-approx = "0.1"
-alga = "0.5"
-serde = { version = "1.0", optional = true }
-serde_derive = { version = "1.0", optional = true }
+typenum = "1.7"
+generic-array = "0.8"
+rand = "0.3"
+num-traits = "0.1"
+num-complex = "0.1"
+approx = "0.1"
+alga = "0.5"
+matrixmultiply = "0.1"
+serde = { version = "1.0", optional = true }
+serde_derive = { version = "1.0", optional = true }
abomonation = { version = "0.4", optional = true }
-# clippy = "*"
[dependencies.quickcheck]
optional = true
@@ -39,3 +40,6 @@ version = "0.4"
[dev-dependencies]
serde_json = "1.0"
+
+[workspace]
+members = [ "nalgebra-lapack" ]
diff --git a/Makefile b/Makefile
index b0eb255d..ad1fafcc 100644
--- a/Makefile
+++ b/Makefile
@@ -1,11 +1,11 @@
all:
- CARGO_INCREMENTAL=1 cargo build --features "arbitrary serde-serialize"
+ cargo check --features "debug arbitrary serde-serialize"
doc:
- CARGO_INCREMENTAL=1 cargo doc --no-deps --features "arbitrary serde-serialize"
+ cargo doc --no-deps --features "debug arbitrary serde-serialize"
bench:
cargo bench
test:
- cargo test --features "arbitrary serde-serialize"
+ cargo test --features "debug arbitrary serde-serialize"
diff --git a/README.md b/README.md
index c7eeeabb..49815cb2 100644
--- a/README.md
+++ b/README.md
@@ -24,3 +24,13 @@
Linear algebra library
for the Rust programming language.
+
+-----
+
+
+ Click this button if you which to donate to support the development of nalgebra:
+
+
+
+
+
diff --git a/benches/common/macros.rs b/benches/common/macros.rs
index 74b0e0cc..55d6ba3c 100644
--- a/benches/common/macros.rs
+++ b/benches/common/macros.rs
@@ -4,20 +4,12 @@ macro_rules! bench_binop(
($name: ident, $t1: ty, $t2: ty, $binop: ident) => {
#[bench]
fn $name(bh: &mut Bencher) {
- const LEN: usize = 1 << 13;
-
let mut rng = IsaacRng::new_unseeded();
-
- let elems1: Vec<$t1> = (0usize .. LEN).map(|_| rng.gen::<$t1>()).collect();
- let elems2: Vec<$t2> = (0usize .. LEN).map(|_| rng.gen::<$t2>()).collect();
- let mut i = 0;
+ let a = rng.gen::<$t1>();
+ let b = rng.gen::<$t2>();
bh.iter(|| {
- i = (i + 1) & (LEN - 1);
-
- unsafe {
- test::black_box(elems1.get_unchecked(i).$binop(*elems2.get_unchecked(i)))
- }
+ a.$binop(b)
})
}
}
@@ -27,43 +19,27 @@ macro_rules! bench_binop_ref(
($name: ident, $t1: ty, $t2: ty, $binop: ident) => {
#[bench]
fn $name(bh: &mut Bencher) {
- const LEN: usize = 1 << 13;
-
let mut rng = IsaacRng::new_unseeded();
-
- let elems1: Vec<$t1> = (0usize .. LEN).map(|_| rng.gen::<$t1>()).collect();
- let elems2: Vec<$t2> = (0usize .. LEN).map(|_| rng.gen::<$t2>()).collect();
- let mut i = 0;
+ let a = rng.gen::<$t1>();
+ let b = rng.gen::<$t2>();
bh.iter(|| {
- i = (i + 1) & (LEN - 1);
-
- unsafe {
- test::black_box(elems1.get_unchecked(i).$binop(elems2.get_unchecked(i)))
- }
+ a.$binop(&b)
})
}
}
);
-macro_rules! bench_binop_na(
- ($name: ident, $t1: ty, $t2: ty, $binop: ident) => {
+macro_rules! bench_binop_fn(
+ ($name: ident, $t1: ty, $t2: ty, $binop: path) => {
#[bench]
fn $name(bh: &mut Bencher) {
- const LEN: usize = 1 << 13;
-
let mut rng = IsaacRng::new_unseeded();
-
- let elems1: Vec<$t1> = (0usize .. LEN).map(|_| rng.gen::<$t1>()).collect();
- let elems2: Vec<$t2> = (0usize .. LEN).map(|_| rng.gen::<$t2>()).collect();
- let mut i = 0;
+ let a = rng.gen::<$t1>();
+ let b = rng.gen::<$t2>();
bh.iter(|| {
- i = (i + 1) & (LEN - 1);
-
- unsafe {
- test::black_box(na::$binop(elems1.get_unchecked(i), elems2.get_unchecked(i)))
- }
+ $binop(&a, &b)
})
}
}
diff --git a/benches/core/matrix.rs b/benches/core/matrix.rs
new file mode 100644
index 00000000..442adafe
--- /dev/null
+++ b/benches/core/matrix.rs
@@ -0,0 +1,192 @@
+use rand::{IsaacRng, Rng};
+use test::{self, Bencher};
+use na::{Vector2, Vector3, Vector4, Matrix2, Matrix3, Matrix4,
+ MatrixN, U10,
+ DMatrix, DVector};
+use std::ops::{Add, Sub, Mul, Div};
+
+#[path="../common/macros.rs"]
+mod macros;
+
+bench_binop!(mat2_mul_m, Matrix2, Matrix2, mul);
+bench_binop!(mat3_mul_m, Matrix3, Matrix3, mul);
+bench_binop!(mat4_mul_m, Matrix4, Matrix4, mul);
+
+bench_binop_ref!(mat2_tr_mul_m, Matrix2, Matrix2, tr_mul);
+bench_binop_ref!(mat3_tr_mul_m, Matrix3, Matrix3, tr_mul);
+bench_binop_ref!(mat4_tr_mul_m, Matrix4, Matrix4, tr_mul);
+
+bench_binop!(mat2_add_m, Matrix2, Matrix2, add);
+bench_binop!(mat3_add_m, Matrix3, Matrix3, add);
+bench_binop!(mat4_add_m, Matrix4, Matrix4, add);
+
+bench_binop!(mat2_sub_m, Matrix2, Matrix2, sub);
+bench_binop!(mat3_sub_m, Matrix3, Matrix3, sub);
+bench_binop!(mat4_sub_m, Matrix4, Matrix4, sub);
+
+bench_binop!(mat2_mul_v, Matrix2, Vector2, mul);
+bench_binop!(mat3_mul_v, Matrix3, Vector3, mul);
+bench_binop!(mat4_mul_v, Matrix4, Vector4, mul);
+
+bench_binop_ref!(mat2_tr_mul_v, Matrix2, Vector2, tr_mul);
+bench_binop_ref!(mat3_tr_mul_v, Matrix3, Vector3, tr_mul);
+bench_binop_ref!(mat4_tr_mul_v, Matrix4, Vector4, tr_mul);
+
+bench_binop!(mat2_mul_s, Matrix2, f32, mul);
+bench_binop!(mat3_mul_s, Matrix3, f32, mul);
+bench_binop!(mat4_mul_s, Matrix4, f32, mul);
+
+bench_binop!(mat2_div_s, Matrix2, f32, div);
+bench_binop!(mat3_div_s, Matrix3, f32, div);
+bench_binop!(mat4_div_s, Matrix4, f32, div);
+
+bench_unop!(mat2_inv, Matrix2, try_inverse);
+bench_unop!(mat3_inv, Matrix3, try_inverse);
+bench_unop!(mat4_inv, Matrix4, try_inverse);
+
+bench_unop!(mat2_transpose, Matrix2, transpose);
+bench_unop!(mat3_transpose, Matrix3, transpose);
+bench_unop!(mat4_transpose, Matrix4, transpose);
+
+#[bench]
+fn mat_div_scalar(b: &mut Bencher) {
+ let a = DMatrix::from_row_slice(1000, 1000, &vec![2.0;1000000]);
+ let n = 42.0;
+
+ b.iter(|| {
+ let mut aa = a.clone();
+ let mut b = aa.slice_mut((0, 0), (1000, 1000));
+ b /= n
+ })
+}
+
+#[bench]
+fn mat100_add_mat100(bench: &mut Bencher) {
+ let a = DMatrix::::new_random(100, 100);
+ let b = DMatrix::::new_random(100, 100);
+
+ bench.iter(|| { &a + &b })
+}
+
+#[bench]
+fn mat4_mul_mat4(bench: &mut Bencher) {
+ let a = DMatrix::::new_random(4, 4);
+ let b = DMatrix::::new_random(4, 4);
+
+ bench.iter(|| { &a * &b })
+}
+
+#[bench]
+fn mat5_mul_mat5(bench: &mut Bencher) {
+ let a = DMatrix::::new_random(5, 5);
+ let b = DMatrix::::new_random(5, 5);
+
+ bench.iter(|| { &a * &b })
+}
+
+#[bench]
+fn mat6_mul_mat6(bench: &mut Bencher) {
+ let a = DMatrix::::new_random(6, 6);
+ let b = DMatrix::::new_random(6, 6);
+
+ bench.iter(|| { &a * &b })
+}
+
+#[bench]
+fn mat7_mul_mat7(bench: &mut Bencher) {
+ let a = DMatrix::::new_random(7, 7);
+ let b = DMatrix::::new_random(7, 7);
+
+ bench.iter(|| { &a * &b })
+}
+
+#[bench]
+fn mat8_mul_mat8(bench: &mut Bencher) {
+ let a = DMatrix::::new_random(8, 8);
+ let b = DMatrix::::new_random(8, 8);
+
+ bench.iter(|| { &a * &b })
+}
+
+#[bench]
+fn mat9_mul_mat9(bench: &mut Bencher) {
+ let a = DMatrix::::new_random(9, 9);
+ let b = DMatrix::::new_random(9, 9);
+
+ bench.iter(|| { &a * &b })
+}
+
+#[bench]
+fn mat10_mul_mat10(bench: &mut Bencher) {
+ let a = DMatrix::::new_random(10, 10);
+ let b = DMatrix::::new_random(10, 10);
+
+ bench.iter(|| { &a * &b })
+}
+
+#[bench]
+fn mat10_mul_mat10_static(bench: &mut Bencher) {
+ let a = MatrixN::::new_random();
+ let b = MatrixN::::new_random();
+
+ bench.iter(|| { &a * &b })
+}
+
+#[bench]
+fn mat100_mul_mat100(bench: &mut Bencher) {
+ let a = DMatrix::::new_random(100, 100);
+ let b = DMatrix::::new_random(100, 100);
+
+ bench.iter(|| { &a * &b })
+}
+
+#[bench]
+fn mat500_mul_mat500(bench: &mut Bencher) {
+ let a = DMatrix::::from_element(500, 500, 5f64);
+ let b = DMatrix::::from_element(500, 500, 6f64);
+
+ bench.iter(|| { &a * &b })
+}
+
+#[bench]
+fn copy_from(bench: &mut Bencher) {
+ let a = DMatrix::::new_random(1000, 1000);
+ let mut b = DMatrix::::new_random(1000, 1000);
+
+ bench.iter(|| {
+ b.copy_from(&a);
+ })
+}
+
+#[bench]
+fn axpy(bench: &mut Bencher) {
+ let x = DVector::::from_element(100000, 2.0);
+ let mut y = DVector::::from_element(100000, 3.0);
+ let a = 42.0;
+
+ bench.iter(|| {
+ y.axpy(a, &x, 1.0);
+ })
+}
+
+#[bench]
+fn tr_mul_to(bench: &mut Bencher) {
+ let a = DMatrix::::new_random(1000, 1000);
+ let b = DVector::::new_random(1000);
+ let mut c = DVector::from_element(1000, 0.0);
+
+ bench.iter(|| {
+ a.tr_mul_to(&b, &mut c)
+ })
+}
+
+#[bench]
+fn mat_mul_mat(bench: &mut Bencher) {
+ let a = DMatrix::::new_random(100, 100);
+ let b = DMatrix::::new_random(100, 100);
+ let mut ab = DMatrix::::from_element(100, 100, 0.0);
+
+ bench.iter(|| {
+ test::black_box(a.mul_to(&b, &mut ab));
+ })
+}
diff --git a/benches/core/mod.rs b/benches/core/mod.rs
new file mode 100644
index 00000000..9699a728
--- /dev/null
+++ b/benches/core/mod.rs
@@ -0,0 +1,2 @@
+mod matrix;
+mod vector;
diff --git a/benches/core/vector.rs b/benches/core/vector.rs
new file mode 100644
index 00000000..fb94de36
--- /dev/null
+++ b/benches/core/vector.rs
@@ -0,0 +1,128 @@
+use rand::{IsaacRng, Rng};
+use test::{self, Bencher};
+use typenum::U10000;
+use na::{Vector2, Vector3, Vector4, VectorN, DVector};
+use std::ops::{Add, Sub, Mul, Div};
+
+#[path="../common/macros.rs"]
+mod macros;
+
+bench_binop!(vec2_add_v_f32, Vector2, Vector2, add);
+bench_binop!(vec3_add_v_f32, Vector3, Vector3, add);
+bench_binop!(vec4_add_v_f32, Vector4, Vector4, add);
+
+bench_binop!(vec2_add_v_f64, Vector2, Vector2, add);
+bench_binop!(vec3_add_v_f64, Vector3, Vector3, add);
+bench_binop!(vec4_add_v_f64, Vector4, Vector4, add);
+
+bench_binop!(vec2_sub_v, Vector2, Vector2, sub);
+bench_binop!(vec3_sub_v, Vector3, Vector3, sub);
+bench_binop!(vec4_sub_v, Vector4, Vector4, sub);
+
+bench_binop!(vec2_mul_s, Vector2, f32, mul);
+bench_binop!(vec3_mul_s, Vector3, f32, mul);
+bench_binop!(vec4_mul_s, Vector4, f32, mul);
+
+bench_binop!(vec2_div_s, Vector2, f32, div);
+bench_binop!(vec3_div_s, Vector3, f32, div);
+bench_binop!(vec4_div_s, Vector4, f32, div);
+
+bench_binop_ref!(vec2_dot_f32, Vector2, Vector2, dot);
+bench_binop_ref!(vec3_dot_f32, Vector3, Vector3, dot);
+bench_binop_ref!(vec4_dot_f32, Vector4, Vector4, dot);
+
+bench_binop_ref!(vec2_dot_f64, Vector2, Vector2, dot);
+bench_binop_ref!(vec3_dot_f64, Vector3, Vector3, dot);
+bench_binop_ref!(vec4_dot_f64, Vector4, Vector4, dot);
+
+bench_binop_ref!(vec3_cross, Vector3, Vector3, cross);
+
+bench_unop!(vec2_norm, Vector2, norm);
+bench_unop!(vec3_norm, Vector3, norm);
+bench_unop!(vec4_norm, Vector4, norm);
+
+bench_unop!(vec2_normalize, Vector2, normalize);
+bench_unop!(vec3_normalize, Vector3, normalize);
+bench_unop!(vec4_normalize, Vector4, normalize);
+
+bench_binop_ref!(vec10000_dot_f64, VectorN, VectorN, dot);
+bench_binop_ref!(vec10000_dot_f32, VectorN, VectorN, dot);
+
+#[bench]
+fn vec10000_axpy_f64(bh: &mut Bencher) {
+ let mut rng = IsaacRng::new_unseeded();
+ let mut a = DVector::new_random(10000);
+ let b = DVector::new_random(10000);
+ let n = rng.gen::();
+
+ bh.iter(|| {
+ a.axpy(n, &b, 1.0)
+ })
+}
+
+#[bench]
+fn vec10000_axpy_beta_f64(bh: &mut Bencher) {
+ let mut rng = IsaacRng::new_unseeded();
+ let mut a = DVector::new_random(10000);
+ let b = DVector::new_random(10000);
+ let n = rng.gen::();
+ let beta = rng.gen::();
+
+ bh.iter(|| {
+ a.axpy(n, &b, beta)
+ })
+}
+
+#[bench]
+fn vec10000_axpy_f64_slice(bh: &mut Bencher) {
+ let mut rng = IsaacRng::new_unseeded();
+ let mut a = DVector::new_random(10000);
+ let b = DVector::new_random(10000);
+ let n = rng.gen::();
+
+ bh.iter(|| {
+ let mut a = a.fixed_rows_mut::(0);
+ let b = b.fixed_rows::(0);
+
+ a.axpy(n, &b, 1.0)
+ })
+}
+
+#[bench]
+fn vec10000_axpy_f64_static(bh: &mut Bencher) {
+ let mut rng = IsaacRng::new_unseeded();
+ let mut a = VectorN::::new_random();
+ let b = VectorN::::new_random();
+ let n = rng.gen::();
+
+ // NOTE: for some reasons, it is much faster if the arument are boxed (Box::new(VectorN...)).
+ bh.iter(|| {
+ a.axpy(n, &b, 1.0)
+ })
+}
+
+
+#[bench]
+fn vec10000_axpy_f32(bh: &mut Bencher) {
+ let mut rng = IsaacRng::new_unseeded();
+ let mut a = DVector::new_random(10000);
+ let b = DVector::new_random(10000);
+ let n = rng.gen::();
+
+ bh.iter(|| {
+ a.axpy(n, &b, 1.0)
+ })
+}
+
+#[bench]
+fn vec10000_axpy_beta_f32(bh: &mut Bencher) {
+ let mut rng = IsaacRng::new_unseeded();
+ let mut a = DVector::new_random(10000);
+ let b = DVector::new_random(10000);
+ let n = rng.gen::();
+ let beta = rng.gen::();
+
+ bh.iter(|| {
+ a.axpy(n, &b, beta)
+ })
+}
diff --git a/benches/geometry/mod.rs b/benches/geometry/mod.rs
new file mode 100644
index 00000000..0f9eb371
--- /dev/null
+++ b/benches/geometry/mod.rs
@@ -0,0 +1 @@
+mod quaternion;
diff --git a/benches/geometry/quaternion.rs b/benches/geometry/quaternion.rs
new file mode 100644
index 00000000..0740ee63
--- /dev/null
+++ b/benches/geometry/quaternion.rs
@@ -0,0 +1,22 @@
+use rand::{IsaacRng, Rng};
+use test::{self, Bencher};
+use na::{Quaternion, UnitQuaternion, Vector3};
+use std::ops::{Add, Sub, Mul, Div};
+
+#[path="../common/macros.rs"]
+mod macros;
+
+bench_binop!(quaternion_add_q, Quaternion, Quaternion, add);
+bench_binop!(quaternion_sub_q, Quaternion, Quaternion, sub);
+bench_binop!(quaternion_mul_q, Quaternion, Quaternion, mul);
+
+bench_binop!(unit_quaternion_mul_v, UnitQuaternion, Vector3, mul);
+
+bench_binop!(quaternion_mul_s, Quaternion, f32, mul);
+bench_binop!(quaternion_div_s, Quaternion, f32, div);
+
+bench_unop!(quaternion_inv, Quaternion, try_inverse);
+bench_unop!(unit_quaternion_inv, UnitQuaternion, inverse);
+
+// bench_unop_self!(quaternion_conjugate, Quaternion, conjugate);
+// bench_unop!(quaternion_normalize, Quaternion, normalize);
diff --git a/benches/lib.rs b/benches/lib.rs
new file mode 100644
index 00000000..5f5ad373
--- /dev/null
+++ b/benches/lib.rs
@@ -0,0 +1,21 @@
+#![feature(test)]
+#![allow(unused_macros)]
+
+extern crate test;
+extern crate rand;
+extern crate typenum;
+extern crate nalgebra as na;
+
+
+use rand::{Rng, IsaacRng};
+use na::DMatrix;
+
+
+mod core;
+mod linalg;
+mod geometry;
+
+fn reproductible_dmatrix(nrows: usize, ncols: usize) -> DMatrix {
+ let mut rng = IsaacRng::new_unseeded();
+ DMatrix::::from_fn(nrows, ncols, |_, _| rng.gen())
+}
diff --git a/benches/linalg/bidiagonal.rs b/benches/linalg/bidiagonal.rs
new file mode 100644
index 00000000..e35ae109
--- /dev/null
+++ b/benches/linalg/bidiagonal.rs
@@ -0,0 +1,75 @@
+use test::{self, Bencher};
+use na::{Matrix4, DMatrix, Bidiagonal};
+
+#[path="../common/macros.rs"]
+mod macros;
+
+// Without unpack.
+#[bench]
+fn bidiagonalize_100x100(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(100, 100);
+ bh.iter(|| test::black_box(Bidiagonal::new(m.clone())))
+}
+
+#[bench]
+fn bidiagonalize_100x500(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(100, 500);
+ bh.iter(|| test::black_box(Bidiagonal::new(m.clone())))
+}
+
+#[bench]
+fn bidiagonalize_4x4(bh: &mut Bencher) {
+ let m = Matrix4::::new_random();
+ bh.iter(|| test::black_box(Bidiagonal::new(m.clone())))
+}
+
+#[bench]
+fn bidiagonalize_500x100(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(500, 100);
+ bh.iter(|| test::black_box(Bidiagonal::new(m.clone())))
+}
+
+#[bench]
+fn bidiagonalize_500x500(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(500, 500);
+ bh.iter(|| test::black_box(Bidiagonal::new(m.clone())))
+}
+
+
+// With unpack.
+#[bench]
+fn bidiagonalize_unpack_100x100(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(100, 100);
+ bh.iter(|| {
+ let bidiag = Bidiagonal::new(m.clone());
+ let _ = bidiag.unpack();
+ })
+}
+
+#[bench]
+fn bidiagonalize_unpack_100x500(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(100, 500);
+ bh.iter(|| {
+ let bidiag = Bidiagonal::new(m.clone());
+ let _ = bidiag.unpack();
+ })
+}
+
+#[bench]
+fn bidiagonalize_unpack_500x100(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(500, 100);
+ bh.iter(|| {
+ let bidiag = Bidiagonal::new(m.clone());
+ let _ = bidiag.unpack();
+ })
+}
+
+#[bench]
+fn bidiagonalize_unpack_500x500(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(500, 500);
+ bh.iter(|| {
+ let bidiag = Bidiagonal::new(m.clone());
+ let _ = bidiag.unpack();
+ })
+}
+
diff --git a/benches/linalg/cholesky.rs b/benches/linalg/cholesky.rs
new file mode 100644
index 00000000..6337c226
--- /dev/null
+++ b/benches/linalg/cholesky.rs
@@ -0,0 +1,109 @@
+use test::{self, Bencher};
+use na::{DMatrix, DVector, Cholesky};
+
+#[bench]
+fn cholesky_100x100(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(100, 100);
+ let m = &m * m.transpose();
+
+ bh.iter(|| test::black_box(Cholesky::new(m.clone())))
+}
+
+#[bench]
+fn cholesky_500x500(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(500, 500);
+ let m = &m * m.transpose();
+
+ bh.iter(|| test::black_box(Cholesky::new(m.clone())))
+}
+
+// With unpack.
+#[bench]
+fn cholesky_decompose_unpack_100x100(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(100, 100);
+ let m = &m * m.transpose();
+
+ bh.iter(|| {
+ let chol = Cholesky::new(m.clone()).unwrap();
+ let _ = chol.unpack();
+ })
+}
+#[bench]
+fn cholesky_decompose_unpack_500x500(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(500, 500);
+ let m = &m * m.transpose();
+
+ bh.iter(|| {
+ let chol = Cholesky::new(m.clone()).unwrap();
+ let _ = chol.unpack();
+ })
+}
+
+#[bench]
+fn cholesky_solve_10x10(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(10, 10);
+ let m = &m * m.transpose();
+ let v = DVector::::new_random(10);
+ let chol = Cholesky::new(m.clone()).unwrap();
+
+ bh.iter(|| {
+ let _ = chol.solve(&v);
+ })
+}
+
+#[bench]
+fn cholesky_solve_100x100(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(100, 100);
+ let m = &m * m.transpose();
+ let v = DVector::::new_random(100);
+ let chol = Cholesky::new(m.clone()).unwrap();
+
+ bh.iter(|| {
+ let _ = chol.solve(&v);
+ })
+}
+
+#[bench]
+fn cholesky_solve_500x500(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(500, 500);
+ let m = &m * m.transpose();
+ let v = DVector::::new_random(500);
+ let chol = Cholesky::new(m.clone()).unwrap();
+
+ bh.iter(|| {
+ let _ = chol.solve(&v);
+ })
+}
+
+#[bench]
+fn cholesky_inverse_10x10(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(10, 10);
+ let m = &m * m.transpose();
+ let chol = Cholesky::new(m.clone()).unwrap();
+
+ bh.iter(|| {
+ let _ = chol.inverse();
+ })
+}
+
+#[bench]
+fn cholesky_inverse_100x100(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(100, 100);
+ let m = &m * m.transpose();
+ let chol = Cholesky::new(m.clone()).unwrap();
+
+ bh.iter(|| {
+ let _ = chol.inverse();
+ })
+}
+
+#[bench]
+fn cholesky_inverse_500x500(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(500, 500);
+ let m = &m * m.transpose();
+ let chol = Cholesky::new(m.clone()).unwrap();
+
+ bh.iter(|| {
+ let _ = chol.inverse();
+ })
+}
diff --git a/benches/linalg/eigen.rs b/benches/linalg/eigen.rs
new file mode 100644
index 00000000..54aa77a5
--- /dev/null
+++ b/benches/linalg/eigen.rs
@@ -0,0 +1,30 @@
+use test::Bencher;
+use na::{DMatrix, Eigen};
+
+#[bench]
+fn eigen_100x100(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(100, 100);
+
+ bh.iter(|| Eigen::new(m.clone(), 1.0e-7, 0))
+}
+
+#[bench]
+fn eigen_500x500(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(500, 500);
+
+ bh.iter(|| Eigen::new(m.clone(), 1.0e-7, 0))
+}
+
+#[bench]
+fn eigenvalues_100x100(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(100, 100);
+
+ bh.iter(|| m.clone().eigenvalues(1.0e-7, 0))
+}
+
+#[bench]
+fn eigenvalues_500x500(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(500, 500);
+
+ bh.iter(|| m.clone().eigenvalues(1.0e-7, 0))
+}
diff --git a/benches/linalg/full_piv_lu.rs b/benches/linalg/full_piv_lu.rs
new file mode 100644
index 00000000..e98e13dd
--- /dev/null
+++ b/benches/linalg/full_piv_lu.rs
@@ -0,0 +1,114 @@
+use test::{self, Bencher};
+use na::{DMatrix, DVector, FullPivLU};
+
+// Without unpack.
+#[bench]
+fn full_piv_lu_decompose_10x10(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(10, 10);
+ bh.iter(|| test::black_box(FullPivLU::new(m.clone())))
+}
+
+#[bench]
+fn full_piv_lu_decompose_100x100(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(100, 100);
+ bh.iter(|| test::black_box(FullPivLU::new(m.clone())))
+}
+
+#[bench]
+fn full_piv_lu_decompose_500x500(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(500, 500);
+ bh.iter(|| test::black_box(FullPivLU::new(m.clone())))
+}
+
+#[bench]
+fn full_piv_lu_solve_10x10(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(10, 10);
+ let lu = FullPivLU::new(m.clone());
+
+ bh.iter(|| {
+ let mut b = DVector::::from_element(10, 1.0);
+ lu.solve(&mut b);
+ })
+}
+
+#[bench]
+fn full_piv_lu_solve_100x100(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(100, 100);
+ let lu = FullPivLU::new(m.clone());
+
+ bh.iter(|| {
+ let mut b = DVector::::from_element(100, 1.0);
+ lu.solve(&mut b);
+ })
+}
+
+#[bench]
+fn full_piv_lu_solve_500x500(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(500, 500);
+ let lu = FullPivLU::new(m.clone());
+
+ bh.iter(|| {
+ let mut b = DVector::::from_element(500, 1.0);
+ lu.solve(&mut b);
+ })
+}
+
+#[bench]
+fn full_piv_lu_inverse_10x10(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(10, 10);
+ let lu = FullPivLU::new(m.clone());
+
+ bh.iter(|| {
+ test::black_box(lu.try_inverse())
+ })
+}
+
+#[bench]
+fn full_piv_lu_inverse_100x100(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(100, 100);
+ let lu = FullPivLU::new(m.clone());
+
+ bh.iter(|| {
+ test::black_box(lu.try_inverse())
+ })
+}
+
+#[bench]
+fn full_piv_lu_inverse_500x500(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(500, 500);
+ let lu = FullPivLU::new(m.clone());
+
+ bh.iter(|| {
+ test::black_box(lu.try_inverse())
+ })
+}
+
+#[bench]
+fn full_piv_lu_determinant_10x10(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(10, 10);
+ let lu = FullPivLU::new(m.clone());
+
+ bh.iter(|| {
+ test::black_box(lu.determinant())
+ })
+}
+
+#[bench]
+fn full_piv_lu_determinant_100x100(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(100, 100);
+ let lu = FullPivLU::new(m.clone());
+
+ bh.iter(|| {
+ test::black_box(lu.determinant())
+ })
+}
+
+#[bench]
+fn full_piv_lu_determinant_500x500(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(500, 500);
+ let lu = FullPivLU::new(m.clone());
+
+ bh.iter(|| {
+ test::black_box(lu.determinant())
+ })
+}
diff --git a/benches/linalg/hessenberg.rs b/benches/linalg/hessenberg.rs
new file mode 100644
index 00000000..90e00b98
--- /dev/null
+++ b/benches/linalg/hessenberg.rs
@@ -0,0 +1,60 @@
+use test::{self, Bencher};
+use na::{Matrix4, DMatrix, Hessenberg};
+
+#[path="../common/macros.rs"]
+mod macros;
+
+// Without unpack.
+#[bench]
+fn hessenberg_decompose_4x4(bh: &mut Bencher) {
+ let m = Matrix4::::new_random();
+ bh.iter(|| test::black_box(Hessenberg::new(m.clone())))
+}
+
+#[bench]
+fn hessenberg_decompose_100x100(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(100, 100);
+ bh.iter(|| test::black_box(Hessenberg::new(m.clone())))
+}
+
+#[bench]
+fn hessenberg_decompose_200x200(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(200, 200);
+ bh.iter(|| test::black_box(Hessenberg::new(m.clone())))
+}
+
+
+#[bench]
+fn hessenberg_decompose_500x500(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(500, 500);
+ bh.iter(|| test::black_box(Hessenberg::new(m.clone())))
+}
+
+
+// With unpack.
+#[bench]
+fn hessenberg_decompose_unpack_100x100(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(100, 100);
+ bh.iter(|| {
+ let hess = Hessenberg::new(m.clone());
+ let _ = hess.unpack();
+ })
+}
+
+#[bench]
+fn hessenberg_decompose_unpack_200x200(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(200, 200);
+ bh.iter(|| {
+ let hess = Hessenberg::new(m.clone());
+ let _ = hess.unpack();
+ })
+}
+
+#[bench]
+fn hessenberg_decompose_unpack_500x500(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(500, 500);
+ bh.iter(|| {
+ let hess = Hessenberg::new(m.clone());
+ let _ = hess.unpack();
+ })
+}
diff --git a/benches/linalg/lu.rs b/benches/linalg/lu.rs
new file mode 100644
index 00000000..33cbb3a5
--- /dev/null
+++ b/benches/linalg/lu.rs
@@ -0,0 +1,114 @@
+use test::{self, Bencher};
+use na::{DMatrix, DVector, LU};
+
+// Without unpack.
+#[bench]
+fn lu_decompose_10x10(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(10, 10);
+ bh.iter(|| test::black_box(LU::new(m.clone())))
+}
+
+#[bench]
+fn lu_decompose_100x100(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(100, 100);
+ bh.iter(|| test::black_box(LU::new(m.clone())))
+}
+
+#[bench]
+fn lu_decompose_500x500(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(500, 500);
+ bh.iter(|| test::black_box(LU::new(m.clone())))
+}
+
+#[bench]
+fn lu_solve_10x10(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(10, 10);
+ let lu = LU::new(m.clone());
+
+ bh.iter(|| {
+ let mut b = DVector::::from_element(10, 1.0);
+ lu.solve(&mut b);
+ })
+}
+
+#[bench]
+fn lu_solve_100x100(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(100, 100);
+ let lu = LU::new(m.clone());
+
+ bh.iter(|| {
+ let mut b = DVector::::from_element(100, 1.0);
+ lu.solve(&mut b);
+ })
+}
+
+#[bench]
+fn lu_solve_500x500(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(500, 500);
+ let lu = LU::new(m.clone());
+
+ bh.iter(|| {
+ let mut b = DVector::::from_element(500, 1.0);
+ lu.solve(&mut b);
+ })
+}
+
+#[bench]
+fn lu_inverse_10x10(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(10, 10);
+ let lu = LU::new(m.clone());
+
+ bh.iter(|| {
+ test::black_box(lu.try_inverse())
+ })
+}
+
+#[bench]
+fn lu_inverse_100x100(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(100, 100);
+ let lu = LU::new(m.clone());
+
+ bh.iter(|| {
+ test::black_box(lu.try_inverse())
+ })
+}
+
+#[bench]
+fn lu_inverse_500x500(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(500, 500);
+ let lu = LU::new(m.clone());
+
+ bh.iter(|| {
+ test::black_box(lu.try_inverse())
+ })
+}
+
+#[bench]
+fn lu_determinant_10x10(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(10, 10);
+ let lu = LU::new(m.clone());
+
+ bh.iter(|| {
+ test::black_box(lu.determinant())
+ })
+}
+
+#[bench]
+fn lu_determinant_100x100(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(100, 100);
+ let lu = LU::new(m.clone());
+
+ bh.iter(|| {
+ test::black_box(lu.determinant())
+ })
+}
+
+#[bench]
+fn lu_determinant_500x500(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(500, 500);
+ let lu = LU::new(m.clone());
+
+ bh.iter(|| {
+ test::black_box(lu.determinant())
+ })
+}
diff --git a/benches/linalg/mod.rs b/benches/linalg/mod.rs
new file mode 100644
index 00000000..c2cc4ade
--- /dev/null
+++ b/benches/linalg/mod.rs
@@ -0,0 +1,11 @@
+mod solve;
+mod cholesky;
+mod qr;
+mod hessenberg;
+mod bidiagonal;
+mod lu;
+mod full_piv_lu;
+mod svd;
+mod schur;
+mod symmetric_eigen;
+// mod eigen;
diff --git a/benches/linalg/qr.rs b/benches/linalg/qr.rs
new file mode 100644
index 00000000..a2d455ea
--- /dev/null
+++ b/benches/linalg/qr.rs
@@ -0,0 +1,137 @@
+use test::{self, Bencher};
+use na::{Matrix4, DMatrix, DVector, QR};
+
+#[path="../common/macros.rs"]
+mod macros;
+
+// Without unpack.
+#[bench]
+fn qr_decompose_100x100(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(100, 100);
+ bh.iter(|| test::black_box(QR::new(m.clone())))
+}
+
+#[bench]
+fn qr_decompose_100x500(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(100, 500);
+ bh.iter(|| test::black_box(QR::new(m.clone())))
+}
+
+#[bench]
+fn qr_decompose_4x4(bh: &mut Bencher) {
+ let m = Matrix4::::new_random();
+ bh.iter(|| test::black_box(QR::new(m.clone())))
+}
+
+#[bench]
+fn qr_decompose_500x100(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(500, 100);
+ bh.iter(|| test::black_box(QR::new(m.clone())))
+}
+
+#[bench]
+fn qr_decompose_500x500(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(500, 500);
+ bh.iter(|| test::black_box(QR::new(m.clone())))
+}
+
+
+// With unpack.
+#[bench]
+fn qr_decompose_unpack_100x100(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(100, 100);
+ bh.iter(|| {
+ let qr = QR::new(m.clone());
+ let _ = qr.unpack();
+ })
+}
+
+#[bench]
+fn qr_decompose_unpack_100x500(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(100, 500);
+ bh.iter(|| {
+ let qr = QR::new(m.clone());
+ let _ = qr.unpack();
+ })
+}
+
+#[bench]
+fn qr_decompose_unpack_500x100(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(500, 100);
+ bh.iter(|| {
+ let qr = QR::new(m.clone());
+ let _ = qr.unpack();
+ })
+}
+
+#[bench]
+fn qr_decompose_unpack_500x500(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(500, 500);
+ bh.iter(|| {
+ let qr = QR::new(m.clone());
+ let _ = qr.unpack();
+ })
+}
+
+#[bench]
+fn qr_solve_10x10(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(10, 10);
+ let qr = QR::new(m.clone());
+
+ bh.iter(|| {
+ let mut b = DVector::::from_element(10, 1.0);
+ qr.solve(&mut b);
+ })
+}
+
+#[bench]
+fn qr_solve_100x100(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(100, 100);
+ let qr = QR::new(m.clone());
+
+ bh.iter(|| {
+ let mut b = DVector::::from_element(100, 1.0);
+ qr.solve(&mut b);
+ })
+}
+
+#[bench]
+fn qr_solve_500x500(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(500, 500);
+ let qr = QR::new(m.clone());
+
+ bh.iter(|| {
+ let mut b = DVector::::from_element(500, 1.0);
+ qr.solve(&mut b);
+ })
+}
+
+#[bench]
+fn qr_inverse_10x10(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(10, 10);
+ let qr = QR::new(m.clone());
+
+ bh.iter(|| {
+ test::black_box(qr.try_inverse())
+ })
+}
+
+#[bench]
+fn qr_inverse_100x100(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(100, 100);
+ let qr = QR::new(m.clone());
+
+ bh.iter(|| {
+ test::black_box(qr.try_inverse())
+ })
+}
+
+#[bench]
+fn qr_inverse_500x500(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(500, 500);
+ let qr = QR::new(m.clone());
+
+ bh.iter(|| {
+ test::black_box(qr.try_inverse())
+ })
+}
diff --git a/benches/linalg/schur.rs b/benches/linalg/schur.rs
new file mode 100644
index 00000000..0b16d0c1
--- /dev/null
+++ b/benches/linalg/schur.rs
@@ -0,0 +1,51 @@
+use test::{self, Bencher};
+use na::{Matrix4, RealSchur};
+
+#[bench]
+fn schur_decompose_4x4(bh: &mut Bencher) {
+ let m = Matrix4::::new_random();
+ bh.iter(|| test::black_box(RealSchur::new(m.clone())))
+}
+
+#[bench]
+fn schur_decompose_10x10(bh: &mut Bencher) {
+ let m = ::reproductible_dmatrix(10, 10);
+ bh.iter(|| test::black_box(RealSchur::new(m.clone())))
+}
+
+
+#[bench]
+fn schur_decompose_100x100(bh: &mut Bencher) {
+ let m = ::reproductible_dmatrix(100, 100);
+ bh.iter(|| test::black_box(RealSchur::new(m.clone())))
+}
+
+#[bench]
+fn schur_decompose_200x200(bh: &mut Bencher) {
+ let m = ::reproductible_dmatrix(200, 200);
+ bh.iter(|| test::black_box(RealSchur::new(m.clone())))
+}
+
+#[bench]
+fn eigenvalues_4x4(bh: &mut Bencher) {
+ let m = Matrix4::::new_random();
+ bh.iter(|| test::black_box(m.complex_eigenvalues()))
+}
+
+#[bench]
+fn eigenvalues_10x10(bh: &mut Bencher) {
+ let m = ::reproductible_dmatrix(10, 10);
+ bh.iter(|| test::black_box(m.complex_eigenvalues()))
+}
+
+#[bench]
+fn eigenvalues_100x100(bh: &mut Bencher) {
+ let m = ::reproductible_dmatrix(100, 100);
+ bh.iter(|| test::black_box(m.complex_eigenvalues()))
+}
+
+#[bench]
+fn eigenvalues_200x200(bh: &mut Bencher) {
+ let m = ::reproductible_dmatrix(200, 200);
+ bh.iter(|| test::black_box(m.complex_eigenvalues()))
+}
diff --git a/benches/linalg/solve.rs b/benches/linalg/solve.rs
new file mode 100644
index 00000000..3362549a
--- /dev/null
+++ b/benches/linalg/solve.rs
@@ -0,0 +1,82 @@
+use test::Bencher;
+use na::{DMatrix, DVector};
+
+#[bench]
+fn solve_l_triangular_100x100(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(100, 100);
+ let v = DVector::::new_random(100);
+
+ bh.iter(|| {
+ let _ = m.solve_lower_triangular(&v);
+ })
+}
+
+#[bench]
+fn solve_l_triangular_1000x1000(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(1000, 1000);
+ let v = DVector::::new_random(1000);
+
+ bh.iter(|| {
+ let _ = m.solve_lower_triangular(&v);
+ })
+}
+
+#[bench]
+fn tr_solve_l_triangular_100x100(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(100, 100);
+ let v = DVector::::new_random(100);
+
+ bh.iter(|| {
+ let _ = m.tr_solve_lower_triangular(&v);
+ })
+}
+
+#[bench]
+fn tr_solve_l_triangular_1000x1000(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(1000, 1000);
+ let v = DVector::::new_random(1000);
+
+ bh.iter(|| {
+ let _ = m.tr_solve_lower_triangular(&v);
+ })
+}
+
+#[bench]
+fn solve_u_triangular_100x100(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(100, 100);
+ let v = DVector::::new_random(100);
+
+ bh.iter(|| {
+ let _ = m.solve_upper_triangular(&v);
+ })
+}
+
+#[bench]
+fn solve_u_triangular_1000x1000(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(1000, 1000);
+ let v = DVector::::new_random(1000);
+
+ bh.iter(|| {
+ let _ = m.solve_upper_triangular(&v);
+ })
+}
+
+#[bench]
+fn tr_solve_u_triangular_100x100(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(100, 100);
+ let v = DVector::::new_random(100);
+
+ bh.iter(|| {
+ let _ = m.tr_solve_upper_triangular(&v);
+ })
+}
+
+#[bench]
+fn tr_solve_u_triangular_1000x1000(bh: &mut Bencher) {
+ let m = DMatrix::::new_random(1000, 1000);
+ let v = DVector::