Multiply 2 double[][] Matrices Using Streams

ε祈祈猫儿з 提交于 2019-12-03 20:28:49

A more compact and readable solution is to create a Stream over the rows of the first matrix, map each row to the result of multiplying it with the second matrix column and collect that back into a double[][].

public static void main(String[] args) {
    double[][] m1 = { { 4, 8 }, { 0, 2 }, { 1, 6 } };
    double[][] m2 = { { 5, 2 }, { 9, 4 } };

    double[][] result = Arrays.stream(m1).map(r -> 
        IntStream.range(0, m2[0].length).mapToDouble(i -> 
            IntStream.range(0, m2.length).mapToDouble(j -> r[j] * m2[j][i]).sum()
    ).toArray()).toArray(double[][]::new);

    System.out.println(Arrays.deepToString(result));
}

This will calculate m1 * m2 and the result will be in result. For the multiplication of each row, we can't create a Stream with Arrays.stream of the second matrix since this would create a Stream over the rows when we need a Stream over the columns. To counteract that, we simply go back to using an IntStream over the indexes.

I created a BiFunction that performs the multiplication using IntStream.range(). If anyone has anything more compact I would love to see it. Here it is:

public static BiFunction<ArrayMatrix, ArrayMatrix, ArrayMatrix> multiply(boolean parallel) {

    return (m1, m2) -> {
        // checkMultiplicationCompatible(m1, m2);

        final int m1Rows = m1.getRowDimension();
        final int m2Rows = m2.getRowDimension();
        final int m1Cols = m1.getColumnDimension();
        final int m2Cols = m2.getColumnDimension();

        double[][] a1 = m1.getData();
        double[][] a2 = m2.getData();

        final double[][] result = new double[m1Rows][m2Cols];

        // Buffer for the tranpose of each md2 column
        final double[] transpose = new double[m1Rows];

        range(0, m2Cols).forEach(m2Col -> {
            range(0, m2Rows).forEach(m2Row -> {
                transpose[m2Row] = a2[m2Row][m2Col];
            });

            range(0, m1Rows).forEach(row -> {
                final double[] dataRow = a1[row];
                double sum = 0;
                for (int m1Col = 0; m1Col < m1Cols; m1Col++) {
                    sum += dataRow[m1Col]
                            * transpose[m1Col];
                }
                result[row][m2Col] = sum;
            });
        });

        return new ArrayMatrix(result, false);
    };
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!