diff --git a/src/main/java/org/openlca/mkl/DenseFactorization.java b/src/main/java/org/openlca/mkl/DenseFactorization.java deleted file mode 100644 index 180b6e7..0000000 --- a/src/main/java/org/openlca/mkl/DenseFactorization.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.openlca.mkl; - -import org.openlca.core.matrix.solvers.Factorization; - -import java.util.Arrays; -import java.util.concurrent.atomic.AtomicBoolean; - -class DenseFactorization implements Factorization { - - private final long pointer; - private final int size; - private final AtomicBoolean isDisposed; - - DenseFactorization(long pointer, int size) { - this.pointer = pointer; - this.size = size; - this.isDisposed = new AtomicBoolean(false); - } - - @Override - public int size() { - return size; - } - - @Override - public double[] solve(double[] b) { - if (b == null) - return new double[size]; - var x = Arrays.copyOf(b, b.length); - int info = MKL.solveDenseFactorization(pointer, 1, x); - InfoCode.checkBlas(info); - return x; - } - - @Override - public void dispose() { - if (isDisposed.get()) - return; - synchronized (isDisposed) { - if (isDisposed.get()) - return; - MKL.disposeDenseFactorization(pointer); - } - } - - @Override - public boolean isDisposed() { - return isDisposed.get(); - } -} diff --git a/src/main/java/org/openlca/mkl/InfoCode.java b/src/main/java/org/openlca/mkl/InfoCode.java deleted file mode 100644 index c74e62d..0000000 --- a/src/main/java/org/openlca/mkl/InfoCode.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.openlca.mkl; - -import org.apache.commons.math3.linear.SingularMatrixException; - -class InfoCode { - - private InfoCode() { - } - - static void checkPardiso(int code) { - if (code == 0) - return; - throw (code == -7 - ? new SingularMatrixException() - : PardisoError.of(code)); - } - - static void checkBlas(int code) { - if (code == 0) - return; - throw (code > 0 - ? new SingularMatrixException() - : new BlasError(code)); - } - - private static class BlasError extends RuntimeException { - BlasError(int code) { - super("BLAS/LAPACK error: illegal argument: code=" +code); - } - } - - private static class PardisoError extends RuntimeException { - private PardisoError(String message) { - super(message); - } - - static PardisoError of(int code) { - var message = switch (code) { - case -1 -> "input inconsistent"; - case -2 -> "not enough memory"; - case -3 -> "reordering problem"; - case -4 -> - "zero pivot, numerical factorization or iterative refinement problem"; - case -5 -> "unclassified (internal) error"; - case -6 -> "reordering failed (matrix types 11 and 13 only)"; - case -7 -> "diagonal matrix is singular"; - case -8 -> "32-bit integer overflow problem"; - case -9 -> "not enough memory for OOC"; - case -10 -> "error opening OOC files"; - case -11 -> "read/write error with OOC files"; - case -12 -> "(pardiso_64 only) pardiso_64 called from 32-bit library"; - case -13 -> "interrupted by the (user-defined) mkl_progress function"; - case -15 -> - "internal error which can appear for iparm[23]=10 and iparm[12]=1."; - default -> "undefined error code"; - }; - return new PardisoError("code = " + code + ": " + message); - } - } - -} diff --git a/src/main/java/org/openlca/mkl/MKL.java b/src/main/java/org/openlca/mkl/MKL.java deleted file mode 100644 index 14237db..0000000 --- a/src/main/java/org/openlca/mkl/MKL.java +++ /dev/null @@ -1,226 +0,0 @@ -package org.openlca.mkl; - -import org.openlca.core.DataDir; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.util.concurrent.atomic.AtomicBoolean; - -public final class MKL { - - /** - * The version of this JNI interface. This version and the version - * returned by the native library have to match exactly. - */ - public static final int VERSION = 1; - - private static final AtomicBoolean _loaded = new AtomicBoolean(false); - - /** - * The JNI version returned from the native library. - */ - public static native int version(); - - /** - * Calculates {@code y := A * x}. - * - * @param m the number of rows of matrix A. - * @param n the number of columns of matrix A. - * @param a the matrix A in column-major order. - * @param x the vector x of size n. - * @param y the vector y of size m. - */ - public static native void denseMatrixVectorMul( - int m, int n, double[] a, double[] x, double[] y - ); - - /** - * Calculates {@code C := A * B}. - * - * @param m the number of rows of matrix A. - * @param n the number of columns of matrix B. - * @param k the number of rows (columns) of matrix A (B). - * @param a the matrix A. - * @param b the matrix B. - * @param c the matrix C. - */ - public static native void denseMatrixMul( - int m, int n, int k, double[] a, double[] b, double[] c - ); - - /** - * Solves x in {@code A * x = b} where A is provided in CSC format. - * - * @param n the number of rows and columns of A. - * @param a the non-zero values of A. - * @param ia the row indices of the non-zero values of A. - * @param ja the column pointers of A. - * @param b the right-hand side vector of size n. - * @param x the solution vector of size n. - * @return a possible error code or 0 if no error occurred. - */ - public static native int solveSparse( - int n, double[] a, int[] ia, int[] ja, double[] b, double[] x - ); - - public static native int sparseFactorization( - int n, double[] a, int[] ia, int[] ja, long[] ptr - ); - - public static native int solveSparseFactorization( - long ptr, double[] b, double[] x - ); - - public static native void disposeSparseFactorization(long ptr); - - public static native int denseFactorization( - int n, double[] a, long[] ptr - ); - - public static native int solveDenseFactorization( - long ptr, int nrhs, double[] b - ); - - public static native void disposeDenseFactorization(long ptr); - - /** - * Solves x in {@code A * x = b}. Note that this method mutates - * the parameter A: on exit it will contain the LU-factorization - * of the matrix A. - * - * @param n the number of rows and columns of A. - * @param nrhs the number of columns of x and b. - * @param a on entry, the matrix A, on exit the factorization of A. - * @param b on entry, the right-hand side, on exit the solution x. - */ - public static native int solveDense( - int n, int nrhs, double[] a, double[] b - ); - - /** - * Inverts a matrix A in place. - * - * @param n the number of rows and columns of A. - * @param a on entry the matrix A, on exit the inverse of A. - * @return 0 on success or an error code otherwise. - */ - public static native int invertDense(int n, double[] a); - - public static boolean isLoaded() { - return _loaded.get(); - } - - /** - * Returns {@code true} if the default openLCA workspace is - * a directory with MKL library folder. - */ - public static boolean isDefaultLibraryDir() { - return isLibraryDir(DataDir.get().root()); - } - - /** - * Returns {@code true} if the given directory contains the - * MKL library folder for the current platform. - */ - public static boolean isLibraryDir(File root) { - if (root == null || !root.isDirectory()) - return false; - var dirName = "olca-mkl-" + arch() + "_v" + VERSION; - var libDir = new File(root, dirName); - if (!libDir.isDirectory()) - return false; - for (var lib : OS.detect().libraries()) { - var dll = new File(libDir, lib); - if (!dll.exists()) - return false; - } - return true; - } - - /** - * Tries to load the native libraries from the default - * openLCA workspace location. - */ - public static boolean loadFromDefault() { - return loadFrom(DataDir.get().root()); - } - - /** - * Tries to load the libraries from the olca-mkl specific - * sub-folder of the given directory. The name of the - * sub-folder has the following pattern: - * {@code olca-mkl-[arch]_v[version]}. - */ - public static boolean loadFrom(File root) { - if (_loaded.get()) - return true; - if (root == null || !root.exists()) - return false; - - var dirName = "olca-mkl-" + arch() + "_v" + VERSION; - var libDir = new File(root, dirName); - if (!libDir.isDirectory()) - return false; - - synchronized (_loaded) { - if (_loaded.get()) - return true; - var log = LoggerFactory.getLogger(MKL.class); - log.debug("try to load MKL libraries from {}", libDir); - try { - - // load the DLLs - var libs = OS.detect().libraries(); - for (var lib : libs) { - var dll = new File(libDir, lib); - if (!tryLoad(dll, log)) - return false; - } - - // check that the version matches - int v = MKL.version(); - if (v != VERSION) { - log.warn( - "loaded MKL libraries from {} but versions " + - "do not match: Java = {}, native = {}", - libDir, VERSION, v); - return false; - } - - _loaded.set(true); - log.info("loaded MKL libraries v{} from {}", v, libDir); - return true; - } catch (Throwable e) { - log.error("failed to load MKL libraries from " + libDir, e); - _loaded.set(false); - return false; - } - } - } - - private static boolean tryLoad(File dll, Logger log) { - if (!dll.exists()) { - log.warn("DLL {} missing; could not load MKL libraries", dll); - return false; - } - try { - System.load(dll.getAbsolutePath()); - log.info("loaded MKL DLL {}", dll); - return true; - } catch (Throwable e) { - log.error("failed to load MKL DLL " + dll, e); - return false; - } - } - - private static String arch() { - var arch = System.getProperty("os.arch"); - if (arch == null) - return "x64"; - var lower = arch.trim().toLowerCase(); - return lower.startsWith("aarch") || lower.startsWith("arm") - ? "arm64" - : "x64"; - } -} diff --git a/src/main/java/org/openlca/mkl/MKLSolver.java b/src/main/java/org/openlca/mkl/MKLSolver.java deleted file mode 100644 index f98a7a7..0000000 --- a/src/main/java/org/openlca/mkl/MKLSolver.java +++ /dev/null @@ -1,134 +0,0 @@ -package org.openlca.mkl; - -import org.apache.commons.math3.linear.NonSquareMatrixException; -import org.openlca.core.matrix.format.CSCMatrix; -import org.openlca.core.matrix.format.DenseMatrix; -import org.openlca.core.matrix.format.HashPointMatrix; -import org.openlca.core.matrix.format.Matrix; -import org.openlca.core.matrix.format.MatrixConverter; -import org.openlca.core.matrix.format.MatrixReader; -import org.openlca.core.matrix.solvers.Factorization; -import org.openlca.core.matrix.solvers.MatrixSolver; - -import java.util.Optional; - -public class MKLSolver implements MatrixSolver { - - @Override - public boolean hasSparseSupport() { - return true; - } - - @Override - public Matrix matrix(int rows, int columns) { - return new HashPointMatrix(rows, columns); - } - - @Override - public double[] solve(MatrixReader a, int idx, double d) { - if (!a.isSquare()) - throw new NonSquareMatrixException(a.rows(), a.columns()); - - int n = a.rows(); - var b = new double[n]; - b[idx] = d; - - var csc = asSparse(a).orElse(null); - if (csc != null) { - var x = new double[n]; - int info = MKL.solveSparse( - n, - csc.values, - csc.rowIndices, - csc.columnPointers, - b, - x - ); - InfoCode.checkPardiso(info); - return x; - } - - var dense = MatrixConverter.dense(a); - var lu = dense == a ? dense.copy() : dense; - int info = MKL.solveDense(n, 1, lu.data, b); - InfoCode.checkBlas(info); - return b; - } - - @Override - public double[] multiply(MatrixReader m, double[] x) { - // TODO: check/add native support - if (m instanceof HashPointMatrix || m instanceof CSCMatrix) - return m.multiply(x); - var a = MatrixConverter.dense(m); - var y = new double[m.rows()]; - MKL.denseMatrixVectorMul(m.rows(), m.columns(), a.data, x, y); - return y; - } - - @Override - public Matrix invert(MatrixReader a) { - if (!a.isSquare()) - throw new NonSquareMatrixException(a.rows(), a.columns()); - // TODO: add sparse support - var dense = MatrixConverter.dense(a); - var inv = dense == a ? dense.copy() : dense; - int info = MKL.invertDense(dense.columns(), inv.data); - InfoCode.checkBlas(info); - return inv; - } - - @Override - public Matrix multiply(MatrixReader a, MatrixReader b) { - // TODO: add sparse support - var denseA = MatrixConverter.dense(a); - var denseB = MatrixConverter.dense(b); - int m = denseA.rows(); - int n = denseB.columns(); - int k = denseA.columns(); - var c = new DenseMatrix(m, n); - if (n == 1) { - MKL.denseMatrixVectorMul( - m, k, denseA.data, denseB.data, c.data); - } else { - MKL.denseMatrixMul( - m, n, k, denseA.data, denseB.data, c.data); - } - return c; - } - - @Override - public Factorization factorize(MatrixReader matrix) { - var csc = asSparse(matrix).orElse(null); - var ptr = new long[1]; - if (csc != null) { - int info = MKL.sparseFactorization( - csc.rows, - csc.values, - csc.rowIndices, - csc.columnPointers, - ptr - ); - InfoCode.checkPardiso(info); - return new SparseFactorization(ptr[0], csc.rows); - } - - var dense = DenseMatrix.of(matrix); - int info = MKL.denseFactorization(dense.rows, dense.data, ptr); - InfoCode.checkBlas(info); - return new DenseFactorization(ptr[0], dense.rows); - } - - @Override - public boolean isNative() { - return true; - } - - private Optional asSparse(MatrixReader matrix) { - if (matrix instanceof CSCMatrix csc) - return Optional.of(csc); - if (matrix instanceof HashPointMatrix hpm) - return Optional.of(hpm.compress()); - return Optional.empty(); - } -} diff --git a/src/main/java/org/openlca/mkl/Main.java b/src/main/java/org/openlca/mkl/Main.java deleted file mode 100644 index 8236c7b..0000000 --- a/src/main/java/org/openlca/mkl/Main.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.openlca.mkl; - -import org.openlca.core.matrix.format.HashPointMatrix; - -import java.io.File; - -public class Main { - - public static void main(String[] args) { - var loaded = MKL.loadFrom(new File("bin")); - if (!loaded) { - System.out.println("failed to load kernel"); - return; - } - System.out.println(MKL.version()); - var y = new double[]{0, 0, 0}; - MKL.denseMatrixVectorMul( - 3, - 3, - new double[]{1, 2, 3, 4, 5, 6, 7, 8, 9}, - new double[]{1, 2, 3}, - y - ); - for (double yi : y) { - System.out.println(yi); - } - - double[] x = new double[2]; - var m = HashPointMatrix.of(new double[][]{ - {1.0, -0.5}, - {-1.0, 1.0}}); - var csc = m.compress(); - - MKL.solveSparse( - 2, - csc.values, - csc.rowIndices, - csc.columnPointers, - new double[]{1, 0}, - x - ); - - for (var xi : x) { - System.out.println(xi); - } - } -} diff --git a/src/main/java/org/openlca/mkl/OS.java b/src/main/java/org/openlca/mkl/OS.java deleted file mode 100644 index 267019c..0000000 --- a/src/main/java/org/openlca/mkl/OS.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.openlca.mkl; - -import java.util.Locale; - -enum OS { - - Linux(new String[]{ - "libmkl_rt.so", - "libolcamkl.so" - }), - - MacOS(new String[]{ - "libmkl_rt.2.dylib", - "libolcamkl.dylib" - }), - - Windows(new String[]{ - "mkl_rt.2.dll", - "olcamkl.dll", - }); - - private final String[] libraries; - - OS(String[] libraries) { - this.libraries = libraries; - } - - static OS detect() { - var os = System.getProperty("os.name", "generic") - .toLowerCase(Locale.ENGLISH); - if (os.contains("mac") || os.contains("darwin")) - return OS.MacOS; - if (os.contains("win")) - return OS.Windows; - return OS.Linux; - } - - String[] libraries() { - return libraries; - } -} diff --git a/src/main/java/org/openlca/mkl/SparseFactorization.java b/src/main/java/org/openlca/mkl/SparseFactorization.java deleted file mode 100644 index e0692c2..0000000 --- a/src/main/java/org/openlca/mkl/SparseFactorization.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.openlca.mkl; - -import org.openlca.core.matrix.solvers.Factorization; - -import java.util.concurrent.atomic.AtomicBoolean; - -class SparseFactorization implements Factorization { - - private final long pointer; - private final int size; - private final AtomicBoolean isDisposed; - - SparseFactorization(long pointer, int size) { - this.pointer = pointer; - this.size = size; - this.isDisposed = new AtomicBoolean(false); - } - - @Override - public int size() { - return size; - } - - @Override - public double[] solve(double[] b) { - double[] x = new double[size]; - if (b == null) - return x; - int info = MKL.solveSparseFactorization(pointer, b, x); - InfoCode.checkPardiso(info); - return x; - } - - @Override - public void dispose() { - if (isDisposed.get()) - return; - synchronized (isDisposed) { - if (isDisposed.get()) - return; - MKL.disposeSparseFactorization(pointer); - } - } - - @Override - public boolean isDisposed() { - return isDisposed.get(); - } -} diff --git a/src/test/java/org/openlca/mkl/DenseTest.java b/src/test/java/org/openlca/mkl/DenseTest.java deleted file mode 100644 index 879f7c2..0000000 --- a/src/test/java/org/openlca/mkl/DenseTest.java +++ /dev/null @@ -1,63 +0,0 @@ -package org.openlca.mkl; - -import static org.junit.Assert.*; - -import org.junit.BeforeClass; -import org.junit.Test; - -public class DenseTest { - - @BeforeClass - public static void setup() { - MKL.loadFromDefault(); - } - - @Test - public void testMatrixMul() { - double[] a = {1, 4, 2, 5, 3, 6}; - double[] b = {7, 8, 9, 10, 11, 12}; - double[] c = new double[4]; - MKL.denseMatrixMul(2, 2, 3, a, b, c); - assertArrayEquals(new double[]{50, 122, 68, 167}, c, 1e-16); - } - - @Test - public void testMatrixVectorMul() { - double[] a = {1, 4, 2, 5, 3, 6}; - double[] x = {2, 1, 0.5}; - double[] y = new double[2]; - MKL.denseMatrixVectorMul(2, 3, a, x, y); - assertArrayEquals(new double[]{5.5, 16}, y, 1e-16); - } - - @Test - public void testSolve() { - double[] a = {1, -4, 0, 2}; - double[] b = {1, 0, 0, 1}; - int info = MKL.solveDense(2, 2, a, b); - assertEquals(0, info); - assertArrayEquals(new double[]{1, 2, 0, 0.5}, b, 1e-16); - } - - @Test - public void testSolveSingularMatrix() { - double[] a = {1, -1, 0, 0}; - double[] b = {1, 0}; - int info = MKL.solveDense(2, 1, a, b); - assertTrue(info > 0); // info > 0 indicates that A was singular - } - - @Test - public void testInvert() { - double[] a = {1, -4, 0, 2}; - MKL.invertDense(2, a); - assertArrayEquals(new double[]{1, 2, 0, 0.5}, a, 1e-16); - } - - @Test - public void testInvertSingularMatrix() { - double[] a = {1, -1, 0, 0}; - int info = MKL.invertDense(2, a); - assertTrue(info > 0); // info > 0 indicates that A was singular - } -} diff --git a/src/test/java/org/openlca/mkl/FactorizationTest.java b/src/test/java/org/openlca/mkl/FactorizationTest.java deleted file mode 100644 index 6f02c34..0000000 --- a/src/test/java/org/openlca/mkl/FactorizationTest.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.openlca.mkl; - -import static org.junit.Assert.*; - -import org.junit.BeforeClass; -import org.junit.Test; -import org.openlca.core.matrix.format.DenseMatrix; -import org.openlca.core.matrix.format.HashPointMatrix; - -import java.io.File; - -public class FactorizationTest { - - @BeforeClass - public static void setup() { - MKL.loadFromDefault(); - } - - @Test - public void testSparse() { - var m = HashPointMatrix.of(new double[][] { - {1, -0.5}, - {-1, 1.0} - }); - var f = new MKLSolver().factorize(m); - assertTrue(f instanceof SparseFactorization); - var x = f.solve(new double[] {1.0, 0.0}); - f.dispose(); - assertEquals(2.0, x[0], 1e-16); - assertEquals(2.0, x[1], 1e-16); - } - - @Test - public void testDense() { - var m = DenseMatrix.of(new double[][] { - {1, -0.5}, - {-1, 1.0} - }); - var f = new MKLSolver().factorize(m); - assertTrue(f instanceof DenseFactorization); - var x = f.solve(new double[] {1.0, 0.0}); - f.dispose(); - assertEquals(2.0, x[0], 1e-16); - assertEquals(2.0, x[1], 1e-16); - } -} diff --git a/src/test/java/org/openlca/mkl/LibraryTest.java b/src/test/java/org/openlca/mkl/LibraryTest.java deleted file mode 100644 index 264aa45..0000000 --- a/src/test/java/org/openlca/mkl/LibraryTest.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.openlca.mkl; - -import static org.junit.Assert.*; - -import org.junit.Test; - -public class LibraryTest { - - @Test - public void testIsLibFolder() { - assertTrue(MKL.isDefaultLibraryDir()); - assertTrue(MKL.loadFromDefault()); - } - -} diff --git a/src/test/java/org/openlca/mkl/NpyExample.java b/src/test/java/org/openlca/mkl/NpyExample.java deleted file mode 100644 index b3d9220..0000000 --- a/src/test/java/org/openlca/mkl/NpyExample.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.openlca.mkl; - -import org.openlca.core.DataDir; -import org.openlca.core.library.LibMatrix; -import org.openlca.core.matrix.format.CSCMatrix; -import org.openlca.julia.Julia; -import org.openlca.mkl.MKL; -import org.openlca.nativelib.NativeLib; - -import java.io.File; - -public class NpyExample { - - public static void main(String[] args) { - MKL.loadFrom(new File("bin")); - NativeLib.loadFrom(DataDir.get().root()); - - var m = DataDir.get() - .getLibraryDir() - .getLibrary("ei39") - .orElseThrow() - .getMatrix(LibMatrix.A) - .orElseThrow(); - var csc = CSCMatrix.of(m); - - System.out.println("\nUMFPACK:"); - testUmfpack(csc); - - System.out.println("\nMKL:"); - testMkl(csc); - } - - private static void testUmfpack(CSCMatrix csc) { - var n = csc.rows(); - var b = new double[n]; - b[0] = 1; - var x = new double[n]; - - System.out.println("iteration\ttime [ms]"); - for (int i = 1; i <= 20; i++) { - long start = System.nanoTime(); - Julia.umfSolve( - n, - csc.columnPointers, - csc.rowIndices, - csc.values, - b, - x); - double time = ((double) (System.nanoTime() - start)) / 1e6; - System.out.printf("%d\t%.0f%n", i, time); - } - } - - private static void testMkl(CSCMatrix csc) { - var n = csc.rows(); - var b = new double[n]; - b[0] = 1; - var x = new double[n]; - - System.out.println("iteration\ttime [ms]"); - for (int i = 1; i <= 20; i++) { - long start = System.nanoTime(); - MKL.solveSparse( - n, - csc.values, - csc.rowIndices, - csc.columnPointers, - b, - x); - double time = ((double) (System.nanoTime() - start)) / 1e6; - System.out.printf("%d\t%.0f%n", i, time); - } - } -} diff --git a/src/test/java/org/openlca/mkl/SimpleTest.java b/src/test/java/org/openlca/mkl/SimpleTest.java deleted file mode 100644 index 85d2fd4..0000000 --- a/src/test/java/org/openlca/mkl/SimpleTest.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.openlca.mkl; - -import org.junit.Assert; -import org.junit.Test; - -public class SimpleTest { - - @Test - public void test() { - System.out.println("running a test ..."); - Assert.assertTrue(true); - } -} diff --git a/src/test/java/org/openlca/mkl/SparseTest.java b/src/test/java/org/openlca/mkl/SparseTest.java deleted file mode 100644 index 5556b6c..0000000 --- a/src/test/java/org/openlca/mkl/SparseTest.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.openlca.mkl; - -import static org.junit.Assert.*; - -import org.junit.BeforeClass; -import org.junit.Test; - -public class SparseTest { - - @BeforeClass - public static void setup() { - MKL.loadFromDefault(); - } - - @Test - public void testSolveNative() { - double[] x = new double[5]; - MKL.solveSparse( - 5, - new double[]{2., 3., 3., -1., 4., 4., -3., 1., 2., 2., 6., 1.}, - new int[]{0, 1, 0, 2, 4, 1, 2, 3, 4, 2, 1, 4}, - new int[]{0, 2, 5, 9, 10, 12}, - new double[]{8., 45., -3., 3., 19.}, - x - ); - assertArrayEquals( - new double[]{1d, 2d, 3d, 4d, 5d}, x, 1e-8); - } -}