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 List> init(final Vec2 dimensions, final Function, T> constructor) { final List> rows = new ArrayList<>(); for (int y = 0; y < dimensions.getY(); y++) { final List 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 * is the type of the matrix to convolve. * @param * is the type of the resulting type of each convolution. */ public static List> convolveTorus(final List> mat, final Vec2 axes, final Supplier init, final Convolver convolver, final BiFunction finalReduction) { final List> rows = new ArrayList<>(); for (int y = 0; y < mat.size(); y++) { final List 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> reductions = new ArrayList<>(); for (int y = 0; y < mat.size(); y++) { final List 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 { R convolve(final T center, final Vec2 rel, final R reduction); } }