diff --git a/main/ejml-ddense/benchmarks/src/org/ejml/dense/block/decompose/chol/BenchmarkDecompositionCholesky_DDRB.java b/main/ejml-ddense/benchmarks/src/org/ejml/dense/block/decompose/chol/BenchmarkDecompositionCholesky_DDRB.java index ada892b79..b31f2baf1 100644 --- a/main/ejml-ddense/benchmarks/src/org/ejml/dense/block/decompose/chol/BenchmarkDecompositionCholesky_DDRB.java +++ b/main/ejml-ddense/benchmarks/src/org/ejml/dense/block/decompose/chol/BenchmarkDecompositionCholesky_DDRB.java @@ -21,6 +21,7 @@ import org.ejml.data.DMatrixRBlock; import org.ejml.dense.block.MatrixOps_DDRB; import org.ejml.dense.block.decomposition.chol.CholeskyOuterForm_DDRB; +import org.ejml.dense.block.decomposition.chol.CholeskyOuterForm_MT_DDRB; import org.ejml.dense.row.RandomMatrices_DDRM; import org.ejml.interfaces.decomposition.CholeskyDecomposition_F64; import org.openjdk.jmh.annotations.*; @@ -48,12 +49,14 @@ public class BenchmarkDecompositionCholesky_DDRB { public DMatrixRBlock A, A_template, L; CholeskyDecomposition_F64 cholesky; + CholeskyDecomposition_F64 choleskyMT; @Setup public void setup() { Random rand = new Random(234); cholesky = new CholeskyOuterForm_DDRB(lower); + choleskyMT = new CholeskyOuterForm_MT_DDRB(lower); A = MatrixOps_DDRB.convert(RandomMatrices_DDRM.symmetricPosDef(size, rand)); A_template = A.copy(); L = new DMatrixRBlock(1, 1); @@ -64,13 +67,18 @@ public void reset() { A.setTo(A_template); } - @Benchmark - public void decompose() { + @Benchmark public void outer() { if (!cholesky.decompose(A)) throw new RuntimeException("FAILED?!"); cholesky.getT(L); } + @Benchmark public void outer_MT() { + if (!choleskyMT.decompose(A)) + throw new RuntimeException("FAILED?!"); + choleskyMT.getT(L); + } + public static void main( String[] args ) throws RunnerException { Options opt = new OptionsBuilder() .include(BenchmarkDecompositionCholesky_DDRB.class.getSimpleName()) diff --git a/main/ejml-ddense/benchmarks/src/org/ejml/dense/block/decompose/chol/BenchmarkDecompositionCholesky_MT_DDRB.java b/main/ejml-ddense/benchmarks/src/org/ejml/dense/block/decompose/chol/BenchmarkDecompositionCholesky_MT_DDRB.java deleted file mode 100644 index fc563685d..000000000 --- a/main/ejml-ddense/benchmarks/src/org/ejml/dense/block/decompose/chol/BenchmarkDecompositionCholesky_MT_DDRB.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2026, Peter Abeles. All Rights Reserved. - * - * This file is part of Efficient Java Matrix Library (EJML). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.ejml.dense.block.decompose.chol; - -import org.ejml.data.DMatrixRBlock; -import org.ejml.dense.block.MatrixOps_DDRB; -import org.ejml.dense.block.decomposition.chol.CholeskyOuterForm_MT_DDRB; -import org.ejml.dense.row.RandomMatrices_DDRM; -import org.ejml.interfaces.decomposition.CholeskyDecomposition_F64; -import org.openjdk.jmh.annotations.*; -import org.openjdk.jmh.runner.Runner; -import org.openjdk.jmh.runner.RunnerException; -import org.openjdk.jmh.runner.options.Options; -import org.openjdk.jmh.runner.options.OptionsBuilder; - -import java.util.Random; -import java.util.concurrent.TimeUnit; - -@BenchmarkMode(Mode.AverageTime) -@OutputTimeUnit(TimeUnit.MILLISECONDS) -@Warmup(iterations = 2) -@Measurement(iterations = 3) -@State(Scope.Benchmark) -@Fork(value = 1) -public class BenchmarkDecompositionCholesky_MT_DDRB { - @Param({"200", "4000"}) - public int size; - - @Param({"true", "false"}) - public boolean lower; - - public DMatrixRBlock A, A_template, L; - - CholeskyDecomposition_F64 cholesky; - - @Setup public void setup() { - Random rand = new Random(234); - - cholesky = new CholeskyOuterForm_MT_DDRB(lower); - A = MatrixOps_DDRB.convert(RandomMatrices_DDRM.symmetricPosDef(size, rand)); - A_template = A.copy(); - L = new DMatrixRBlock(1, 1); - } - - @Setup(Level.Invocation) public void reset() { - A.setTo(A_template); - } - - @Benchmark public void decompose() { - if (!cholesky.decompose(A)) - throw new RuntimeException("FAILED?!"); - cholesky.getT(L); - } - - public static void main( String[] args ) throws RunnerException { - Options opt = new OptionsBuilder() - .include(BenchmarkDecompositionCholesky_MT_DDRB.class.getSimpleName()) - .build(); - - new Runner(opt).run(); - } -} diff --git a/main/ejml-ddense/benchmarks/src/org/ejml/dense/block/decompose/hessenberg/BenchmarkDecompositionHessenberg_DDRB.java b/main/ejml-ddense/benchmarks/src/org/ejml/dense/block/decompose/hessenberg/BenchmarkDecompositionHessenberg_DDRB.java index 19ec27a12..35f73964e 100644 --- a/main/ejml-ddense/benchmarks/src/org/ejml/dense/block/decompose/hessenberg/BenchmarkDecompositionHessenberg_DDRB.java +++ b/main/ejml-ddense/benchmarks/src/org/ejml/dense/block/decompose/hessenberg/BenchmarkDecompositionHessenberg_DDRB.java @@ -21,6 +21,7 @@ import org.ejml.data.DMatrixRBlock; import org.ejml.dense.block.MatrixOps_DDRB; import org.ejml.dense.block.decomposition.hessenberg.TridiagonalDecompositionHouseholder_DDRB; +import org.ejml.dense.block.decomposition.hessenberg.TridiagonalDecompositionHouseholder_MT_DDRB; import org.ejml.dense.row.RandomMatrices_DDRM; import org.openjdk.jmh.annotations.*; import org.openjdk.jmh.runner.Runner; @@ -39,18 +40,21 @@ @Fork(value = 1) public class BenchmarkDecompositionHessenberg_DDRB { // @Param({"100", "500", "1000", "5000", "10000"}) - @Param({"2000"}) + @Param({"500", "2000"}) public int size; - public DMatrixRBlock S, S_template; + public DMatrixRBlock S, S_template,Q, R; - TridiagonalDecompositionHouseholder_DDRB tridiagonal = new TridiagonalDecompositionHouseholder_DDRB(); + TridiagonalDecompositionHouseholder_DDRB house = new TridiagonalDecompositionHouseholder_DDRB(); + TridiagonalDecompositionHouseholder_MT_DDRB houseMT = new TridiagonalDecompositionHouseholder_MT_DDRB(); @Setup public void setup() { Random rand = new Random(234); S = MatrixOps_DDRB.convert(RandomMatrices_DDRM.symmetric(size, -1, 1, rand)); S_template = S.copy(); + Q = new DMatrixRBlock(1, 1); + R = new DMatrixRBlock(1, 1); } @Setup(Level.Invocation) public void reset() { @@ -58,8 +62,20 @@ public class BenchmarkDecompositionHessenberg_DDRB { } @Benchmark public void tridiagonal() { - if (!tridiagonal.decompose(S)) + if (!house.decompose(S)) throw new RuntimeException("Decomposition failed?"); + // transposed and not exercise different paths + house.getQ(Q, false); + house.getQ(Q, true); + house.getT(R); + } + + @Benchmark public void tridiagonal_MT() { + if (!houseMT.decompose(S)) + throw new RuntimeException("Decomposition failed?"); + houseMT.getQ(Q, false); + houseMT.getQ(Q, true); + houseMT.getT(R); } public static void main( String[] args ) throws RunnerException { diff --git a/main/ejml-ddense/benchmarks/src/org/ejml/dense/block/decompose/hessenberg/BenchmarkDecompositionHessenberg_MT_DDRB.java b/main/ejml-ddense/benchmarks/src/org/ejml/dense/block/decompose/hessenberg/BenchmarkDecompositionHessenberg_MT_DDRB.java deleted file mode 100644 index 9093093cd..000000000 --- a/main/ejml-ddense/benchmarks/src/org/ejml/dense/block/decompose/hessenberg/BenchmarkDecompositionHessenberg_MT_DDRB.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2026, Peter Abeles. All Rights Reserved. - * - * This file is part of Efficient Java Matrix Library (EJML). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.ejml.dense.block.decompose.hessenberg; - -import org.ejml.data.DMatrixRBlock; -import org.ejml.dense.block.MatrixOps_DDRB; -import org.ejml.dense.block.decomposition.hessenberg.TridiagonalDecompositionHouseholder_MT_DDRB; -import org.ejml.dense.row.RandomMatrices_DDRM; -import org.openjdk.jmh.annotations.*; -import org.openjdk.jmh.runner.Runner; -import org.openjdk.jmh.runner.RunnerException; -import org.openjdk.jmh.runner.options.Options; -import org.openjdk.jmh.runner.options.OptionsBuilder; - -import java.util.Random; -import java.util.concurrent.TimeUnit; - -@BenchmarkMode(Mode.AverageTime) -@OutputTimeUnit(TimeUnit.MILLISECONDS) -@Warmup(iterations = 2) -@Measurement(iterations = 3) -@State(Scope.Benchmark) -@Fork(value = 1) -public class BenchmarkDecompositionHessenberg_MT_DDRB { - // @Param({"100", "500", "1000", "5000", "10000"}) - @Param({"2000"}) - public int size; - - public DMatrixRBlock S, S_template; - - TridiagonalDecompositionHouseholder_MT_DDRB tridiagonal = new TridiagonalDecompositionHouseholder_MT_DDRB(); - - @Setup public void setup() { - Random rand = new Random(234); - - S = MatrixOps_DDRB.convert(RandomMatrices_DDRM.symmetric(size, -1, 1, rand)); - S_template = S.copy(); - } - - @Setup(Level.Invocation) public void reset() { - S.setTo(S_template); - } - - @Benchmark public void tridiagonal() { - if (!tridiagonal.decompose(S)) - throw new RuntimeException("Decomposition failed?"); - } - - public static void main( String[] args ) throws RunnerException { - Options opt = new OptionsBuilder() - .include(BenchmarkDecompositionHessenberg_MT_DDRB.class.getSimpleName()) - .build(); - - new Runner(opt).run(); - } -} diff --git a/main/ejml-ddense/benchmarks/src/org/ejml/dense/block/decompose/qr/BenchmarkDecompositionQR_DDRB.java b/main/ejml-ddense/benchmarks/src/org/ejml/dense/block/decompose/qr/BenchmarkDecompositionQR_DDRB.java index 1f8d803c1..00e87d3b5 100644 --- a/main/ejml-ddense/benchmarks/src/org/ejml/dense/block/decompose/qr/BenchmarkDecompositionQR_DDRB.java +++ b/main/ejml-ddense/benchmarks/src/org/ejml/dense/block/decompose/qr/BenchmarkDecompositionQR_DDRB.java @@ -21,6 +21,7 @@ import org.ejml.data.DMatrixRBlock; import org.ejml.dense.block.MatrixOps_DDRB; import org.ejml.dense.block.decomposition.qr.QRDecompositionHouseholder_DDRB; +import org.ejml.dense.block.decomposition.qr.QRDecompositionHouseholder_MT_DDRB; import org.ejml.interfaces.decomposition.QRDecomposition; import org.openjdk.jmh.annotations.*; import org.openjdk.jmh.runner.Runner; @@ -42,25 +43,41 @@ public class BenchmarkDecompositionQR_DDRB { @Param({"1000", "2000"}) public int size; - public DMatrixRBlock A, A_template; + public DMatrixRBlock A, A_template, Q, R; - QRDecomposition qr = new QRDecompositionHouseholder_DDRB(); + QRDecomposition house = new QRDecompositionHouseholder_DDRB(); + QRDecomposition houseMT = new QRDecompositionHouseholder_MT_DDRB(); - @Setup - public void setup() { + @Setup public void setup() { Random rand = new Random(234); A = MatrixOps_DDRB.createRandom(size*4, size/4, -1, 1, rand); A_template = A.copy(); + + Q = new DMatrixRBlock(1, 1); + R = new DMatrixRBlock(1, 1); } @Setup(Level.Invocation) public void reset() { A.setTo(A_template); } - @Benchmark public void decompose() { - if (!qr.decompose(A)) + @Benchmark public void householder() { + if (!house.decompose(A)) + throw new RuntimeException("FAILED?!"); + + // get Q and R to fully exercise the code. Compact format to avoid having Q dominate + house.getQ(Q, true); + house.getR(R, true); + } + + @Benchmark public void householder_MT() { + if (!houseMT.decompose(A)) throw new RuntimeException("FAILED?!"); + + // get Q and R to fully exercise the code. Compact format to avoid having Q dominate + houseMT.getQ(Q, true); + houseMT.getR(R, true); } public static void main( String[] args ) throws RunnerException { diff --git a/main/ejml-ddense/benchmarks/src/org/ejml/dense/block/decompose/qr/BenchmarkDecompositionQR_MT_DDRB.java b/main/ejml-ddense/benchmarks/src/org/ejml/dense/block/decompose/qr/BenchmarkDecompositionQR_MT_DDRB.java deleted file mode 100644 index 8c9e94310..000000000 --- a/main/ejml-ddense/benchmarks/src/org/ejml/dense/block/decompose/qr/BenchmarkDecompositionQR_MT_DDRB.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2026, Peter Abeles. All Rights Reserved. - * - * This file is part of Efficient Java Matrix Library (EJML). - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.ejml.dense.block.decompose.qr; - -import org.ejml.data.DMatrixRBlock; -import org.ejml.dense.block.MatrixOps_DDRB; -import org.ejml.dense.block.decomposition.qr.QRDecompositionHouseholder_MT_DDRB; -import org.ejml.interfaces.decomposition.QRDecomposition; -import org.openjdk.jmh.annotations.*; -import org.openjdk.jmh.runner.Runner; -import org.openjdk.jmh.runner.RunnerException; -import org.openjdk.jmh.runner.options.Options; -import org.openjdk.jmh.runner.options.OptionsBuilder; - -import java.util.Random; -import java.util.concurrent.TimeUnit; - -@BenchmarkMode(Mode.AverageTime) -@OutputTimeUnit(TimeUnit.MILLISECONDS) -@Warmup(iterations = 2) -@Measurement(iterations = 3) -@State(Scope.Benchmark) -@Fork(value = 1) -public class BenchmarkDecompositionQR_MT_DDRB { - @Param({"1000", "2000"}) - public int size; - - public DMatrixRBlock A, A_template; - - QRDecomposition qr = new QRDecompositionHouseholder_MT_DDRB(); - - @Setup - public void setup() { - Random rand = new Random(234); - - A = MatrixOps_DDRB.createRandom(size*4, size/4, -1, 1, rand); - A_template = A.copy(); - } - - @Setup(Level.Invocation) public void reset() { - A.setTo(A_template); - } - - @Benchmark public void decompose() { - if (!qr.decompose(A)) - throw new RuntimeException("FAILED?!"); - } - - public static void main( String[] args ) throws RunnerException { - Options opt = new OptionsBuilder() - .include(BenchmarkDecompositionQR_MT_DDRB.class.getSimpleName()) - .build(); - - new Runner(opt).run(); - } -} diff --git a/main/ejml-ddense/src/org/ejml/dense/block/decomposition/hessenberg/TridiagonalDecompositionHouseholder_DDRB.java b/main/ejml-ddense/src/org/ejml/dense/block/decomposition/hessenberg/TridiagonalDecompositionHouseholder_DDRB.java index 8df07143b..2bdd26fb7 100644 --- a/main/ejml-ddense/src/org/ejml/dense/block/decomposition/hessenberg/TridiagonalDecompositionHouseholder_DDRB.java +++ b/main/ejml-ddense/src/org/ejml/dense/block/decomposition/hessenberg/TridiagonalDecompositionHouseholder_DDRB.java @@ -65,9 +65,9 @@ public DMatrixRBlock getT( @Nullable DMatrixRBlock T ) { if (T == null) { T = new DMatrixRBlock(A.numRows, A.numCols, A.blockLength); } else { - if (T.numRows != A.numRows || T.numCols != A.numCols) - throw new IllegalArgumentException("T must have the same dimensions as the input matrix"); - + if (T.blockLength != A.blockLength) + throw new RuntimeException("Block lengths don't match"); + T.reshape(A.numRows, A.numCols); CommonOps_DDRM.fill(T, 0); } diff --git a/main/ejml-ddense/src/org/ejml/dense/block/decomposition/qr/QRDecompositionHouseholder_DDRB.java b/main/ejml-ddense/src/org/ejml/dense/block/decomposition/qr/QRDecompositionHouseholder_DDRB.java index b2accd6c8..a08bd8083 100644 --- a/main/ejml-ddense/src/org/ejml/dense/block/decomposition/qr/QRDecompositionHouseholder_DDRB.java +++ b/main/ejml-ddense/src/org/ejml/dense/block/decomposition/qr/QRDecompositionHouseholder_DDRB.java @@ -218,12 +218,12 @@ public DMatrixRBlock getR( @Nullable DMatrixRBlock R, boolean compact ) { R = new DMatrixRBlock(dataA.numRows, dataA.numCols, blockLength); } } else { + if (R.blockLength != dataA.blockLength) + throw new RuntimeException("Block lengths don't match"); if (compact) { - if (R.numCols != dataA.numCols || R.numRows != min) { - throw new IllegalArgumentException("Unexpected dimension."); - } - } else if (R.numCols != dataA.numCols || R.numRows != dataA.numRows) { - throw new IllegalArgumentException("Unexpected dimension."); + R.reshape(min, dataA.numCols); + } else { + R.reshape(dataA.numRows, dataA.numCols); } }