forked from TheAlgorithms/Java
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMatrixUtil.java
130 lines (106 loc) · 4.94 KB
/
MatrixUtil.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package com.thealgorithms.matrix.utils;
import java.math.BigDecimal;
import java.util.Optional;
import java.util.function.BiFunction;
import java.util.stream.IntStream;
/**
* @author: caos321
* @date: 31 October 2021 (Sunday)
*/
public class MatrixUtil {
private static boolean isValid(final BigDecimal[][] matrix) {
return matrix != null && matrix.length > 0 && matrix[0].length > 0;
}
private static boolean hasEqualSizes(final BigDecimal[][] matrix1, final BigDecimal[][] matrix2) {
return (isValid(matrix1) && isValid(matrix2) && matrix1.length == matrix2.length && matrix1[0].length == matrix2[0].length);
}
private static boolean canMultiply(final BigDecimal[][] matrix1, final BigDecimal[][] matrix2) {
return (isValid(matrix1) && isValid(matrix2) && matrix1[0].length == matrix2.length);
}
public static void validateInputMatrix(double[][] matrix) {
if (matrix == null) {
throw new IllegalArgumentException("The input matrix cannot be null");
}
if (matrix.length == 0) {
throw new IllegalArgumentException("The input matrix cannot be empty");
}
if (!hasValidRows(matrix)) {
throw new IllegalArgumentException("The input matrix cannot have null or empty rows");
}
if (isJaggedMatrix(matrix)) {
throw new IllegalArgumentException("The input matrix cannot be jagged");
}
}
private static boolean hasValidRows(double[][] matrix) {
for (double[] row : matrix) {
if (row == null || row.length == 0) {
return false;
}
}
return true;
}
/**
* @brief Checks if the input matrix is a jagged matrix.
* Jagged matrix is a matrix where the number of columns in each row is not the same.
*
* @param matrix The input matrix
* @return True if the input matrix is a jagged matrix, false otherwise
*/
private static boolean isJaggedMatrix(double[][] matrix) {
int numColumns = matrix[0].length;
for (double[] row : matrix) {
if (row.length != numColumns) {
return true;
}
}
return false;
}
private static Optional<BigDecimal[][]> operate(final BigDecimal[][] matrix1, final BigDecimal[][] matrix2, final BiFunction<BigDecimal, BigDecimal, BigDecimal> operation) {
if (!hasEqualSizes(matrix1, matrix2)) {
return Optional.empty();
}
final int rowSize = matrix1.length;
final int columnSize = matrix1[0].length;
final BigDecimal[][] result = new BigDecimal[rowSize][columnSize];
IntStream.range(0, rowSize).forEach(rowIndex -> IntStream.range(0, columnSize).forEach(columnIndex -> {
final BigDecimal value1 = matrix1[rowIndex][columnIndex];
final BigDecimal value2 = matrix2[rowIndex][columnIndex];
result[rowIndex][columnIndex] = operation.apply(value1, value2);
}));
return Optional.of(result);
}
public static Optional<BigDecimal[][]> add(final BigDecimal[][] matrix1, final BigDecimal[][] matrix2) {
return operate(matrix1, matrix2, BigDecimal::add);
}
public static Optional<BigDecimal[][]> subtract(final BigDecimal[][] matrix1, final BigDecimal[][] matrix2) {
return operate(matrix1, matrix2, BigDecimal::subtract);
}
public static Optional<BigDecimal[][]> multiply(final BigDecimal[][] matrix1, final BigDecimal[][] matrix2) {
if (!canMultiply(matrix1, matrix2)) {
return Optional.empty();
}
final int size = matrix1[0].length;
final int matrix1RowSize = matrix1.length;
final int matrix2ColumnSize = matrix2[0].length;
final BigDecimal[][] result = new BigDecimal[matrix1RowSize][matrix2ColumnSize];
IntStream.range(0, matrix1RowSize)
.forEach(rowIndex
-> IntStream.range(0, matrix2ColumnSize)
.forEach(columnIndex
-> result[rowIndex][columnIndex] = IntStream.range(0, size)
.mapToObj(index -> {
final BigDecimal value1 = matrix1[rowIndex][index];
final BigDecimal value2 = matrix2[index][columnIndex];
return value1.multiply(value2);
})
.reduce(BigDecimal.ZERO, BigDecimal::add)));
return Optional.of(result);
}
public static double[] reverseRow(final double[] inRow) {
double[] res = new double[inRow.length];
for (int i = 0; i < inRow.length; ++i) {
res[i] = inRow[inRow.length - 1 - i];
}
return res;
}
}