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
|
package coffee.liz.ecs.math;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
public final class Mat2 {
private Mat2() {
}
/**
* Initializes a mutable 2d matrix of given type.
*
* @param dimensions
* the dimensions
* @param constructor
* the constructor
* @return row-indexed 2d matrix of {@param dimensions}
*/
public static <T> List<List<T>> init(final Vec2<Integer> dimensions, final Function<Vec2<Integer>, T> constructor) {
final List<List<T>> rows = new ArrayList<>();
for (int y = 0; y < dimensions.getY(); y++) {
final List<T> row = new ArrayList<>(dimensions.getX());
for (int x = 0; x < dimensions.getX(); x++)
row.add(constructor.apply(Vec2i.builder().y(y).x(x).build()));
rows.add(row);
}
return rows;
}
/**
* Convolves a {@link Convolver} across a matrix reaching neighbors around the
* grid like a torus.
*
* @param mat
* is the row-indexed 2d matrix to convolve.
* @param axes
* are the x/y major/minor axes.
* @param init
* is the initial value of the convolution.
* @param convolver
* is the {@link Convolver}.
* @param finalReduction
* to apply after {@param convolver}.
* @return result of {@param convolver} applied along axes at each cell.
* @param <T>
* is the type of the matrix to convolve.
* @param <R>
* is the type of the resulting type of each convolution.
*/
public static <T, R, U> List<List<U>> convolveTorus(final List<List<T>> mat, final Vec2<Integer> axes,
final Supplier<R> init, final Convolver<T, R> convolver, final BiFunction<T, R, U> finalReduction) {
final List<List<R>> rows = new ArrayList<>();
for (int y = 0; y < mat.size(); y++) {
final List<R> row = new ArrayList<>(mat.get(y).size());
for (int x = 0; x < mat.get(y).size(); x++) {
final T center = mat.get(y).get(x);
R result = init.get();
for (int dy = -axes.getY(); dy <= axes.getY(); dy++) {
final int ry = Math.floorMod(y + dy, mat.size());
for (int dx = -axes.getX(); dx <= axes.getX(); dx++) {
final int rx = Math.floorMod(x + dx, mat.get(ry).size());
result = convolver.convolve(mat.get(ry).get(rx), Vec2i.builder().x(dx).y(dy).build(), result);
}
}
row.add(result);
}
rows.add(row);
}
final List<List<U>> reductions = new ArrayList<>();
for (int y = 0; y < mat.size(); y++) {
final List<U> reduction = new ArrayList<>(mat.get(y).size());
for (int x = 0; x < mat.get(y).size(); x++) {
reduction.add(finalReduction.apply(mat.get(y).get(x), rows.get(y).get(x)));
}
reductions.add(reduction);
}
return reductions;
}
@FunctionalInterface
public interface Convolver<T, R> {
R convolve(final T center, final Vec2<Integer> rel, final R reduction);
}
}
|