All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ojalgo.structure.Mutate2D Maven / Gradle / Ivy

Go to download

oj! Algorithms - ojAlgo - is Open Source Java code that has to do with mathematics, linear algebra and optimisation.

There is a newer version: 55.0.1
Show newest version
/*
 * Copyright 1997-2024 Optimatika
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package org.ojalgo.structure;

import java.util.function.Consumer;

import org.ojalgo.ProgrammingError;
import org.ojalgo.array.operation.FillCompatible;
import org.ojalgo.function.BinaryFunction;
import org.ojalgo.function.NullaryFunction;
import org.ojalgo.function.UnaryFunction;

/**
 * 2-dimensional mutator methods
 *
 * @author apete
 */
public interface Mutate2D extends Structure2D, Mutate1D {

    /**
     * A few operations with no 1D or AnyD counterpart.
     *
     * @author apete
     */
    interface Exchangeable extends Structure2D {

        void exchangeColumns(long colA, long colB);

        void exchangeRows(long rowA, long rowB);

    }

    interface Fillable> extends Mutate2D, Mutate1D.Fillable {

        default void fillColumn(final long col, final Access1D values) {
            this.fillColumn(0L, col, values);
        }

        default void fillColumn(final long row, final long col, final Access1D values) {
            for (long i = row, limit = this.countRows(); i < limit; i++) {
                this.set(i, col, values.get(i - row));
            }
        }

        default void fillColumn(final long row, final long col, final N value) {
            for (long i = row, limit = this.countRows(); i < limit; i++) {
                this.set(i, col, value);
            }
        }

        default void fillColumn(final long row, final long col, final NullaryFunction supplier) {
            for (long i = row, limit = this.countRows(); i < limit; i++) {
                this.set(i, col, supplier.get());
            }
        }

        default void fillColumn(final long col, final N value) {
            this.fillColumn(0L, col, value);
        }

        default void fillColumn(final long col, final NullaryFunction supplier) {
            this.fillColumn(0L, col, supplier);
        }

        /**
         * 'this' needs to be of a size compatible with the 'left' and 'right' matrices. No checks are
         * performed. The term "compatible" refers to MATLAB's rules for "array broadcasting". The result will
         * be the same as if the 'left' and 'right' matrices where expanded (repeated) so that all three where
         * of the same size, and then the operation was performed. The actual implementation may be more
         * efficient than that.
         * 
         * @see https://se.mathworks.com/help/matlab/matlab_prog/compatible-array-sizes-for-basic-operations.html
         */
        default void fillCompatible(final Access2D left, final BinaryFunction operator, final Access2D right) {
            FillCompatible.invoke(this, left, operator, right);
        }

        default void fillDiagonal(final Access1D values) {
            this.fillDiagonal(0L, 0L, values);
        }

        default void fillDiagonal(final long row, final long col, final Access1D values) {
            for (long ij = 0L, limit = Math.min(this.countRows() - row, this.countColumns() - col); ij < limit; ij++) {
                this.set(row + ij, col + ij, values.get(ij));
            }
        }

        default void fillDiagonal(final long row, final long col, final N value) {
            for (long ij = 0L, limit = Math.min(this.countRows() - row, this.countColumns() - col); ij < limit; ij++) {
                this.set(row + ij, col + ij, value);
            }
        }

        default void fillDiagonal(final long row, final long col, final NullaryFunction supplier) {
            for (long ij = 0L, limit = Math.min(this.countRows() - row, this.countColumns() - col); ij < limit; ij++) {
                this.set(row + ij, col + ij, supplier.get());
            }
        }

        default void fillDiagonal(final N value) {
            this.fillDiagonal(0L, 0L, value);
        }

        default void fillDiagonal(final NullaryFunction supplier) {
            this.fillDiagonal(0L, 0L, supplier);
        }

        default void fillRow(final long row, final Access1D values) {
            this.fillRow(row, 0L, values);
        }

        default void fillRow(final long row, final long col, final Access1D values) {
            for (long j = col, limit = this.countColumns(); j < limit; j++) {
                this.set(row, j, values.get(j - col));
            }
        }

        default void fillRow(final long row, final long col, final N value) {
            for (long j = col, limit = this.countColumns(); j < limit; j++) {
                this.set(row, j, value);
            }
        }

        default void fillRow(final long row, final long col, final NullaryFunction supplier) {
            for (long j = col, limit = this.countColumns(); j < limit; j++) {
                this.set(row, j, supplier.get());
            }
        }

        default void fillRow(final long row, final N value) {
            this.fillRow(row, 0L, value);
        }

        default void fillRow(final long row, final NullaryFunction supplier) {
            this.fillRow(row, 0L, supplier);
        }

    }

    interface Mixable> extends Structure2D, Mutate1D.Mixable {

        @Override
        default double mix(final long index, final BinaryFunction mixer, final double addend) {
            long structure = this.countRows();
            return this.mix(Structure2D.row(index, structure), Structure2D.column(index, structure), mixer, addend);
        }

        @Override
        default N mix(final long index, final BinaryFunction mixer, final N addend) {
            long structure = this.countRows();
            return this.mix(Structure2D.row(index, structure), Structure2D.column(index, structure), mixer, addend);
        }

        double mix(long row, long col, BinaryFunction mixer, double addend);

        N mix(long row, long col, BinaryFunction mixer, N addend);
    }

    interface Modifiable> extends Structure2D, Mutate1D.Modifiable {

        @Override
        default void add(final long index, final byte addend) {
            long structure = this.countRows();
            this.add(Structure2D.row(index, structure), Structure2D.column(index, structure), addend);
        }

        @Override
        default void add(final long index, final Comparable addend) {
            long structure = this.countRows();
            this.add(Structure2D.row(index, structure), Structure2D.column(index, structure), addend);
        }

        @Override
        default void add(final long index, final double addend) {
            long structure = this.countRows();
            this.add(Structure2D.row(index, structure), Structure2D.column(index, structure), addend);
        }

        @Override
        default void add(final long index, final float addend) {
            long structure = this.countRows();
            this.add(Structure2D.row(index, structure), Structure2D.column(index, structure), addend);
        }

        @Override
        default void add(final long index, final int addend) {
            long structure = this.countRows();
            this.add(Structure2D.row(index, structure), Structure2D.column(index, structure), addend);
        }

        @Override
        default void add(final long index, final long addend) {
            long structure = this.countRows();
            this.add(Structure2D.row(index, structure), Structure2D.column(index, structure), addend);
        }

        default void add(final long row, final long col, final byte addend) {
            this.add(row, col, (short) addend);
        }

        void add(long row, long col, Comparable addend);

        void add(long row, long col, double addend);

        default void add(final long row, final long col, final float addend) {
            this.add(row, col, (double) addend);
        }

        default void add(final long row, final long col, final int addend) {
            this.add(row, col, (long) addend);
        }

        default void add(final long row, final long col, final long addend) {
            this.add(row, col, (double) addend);
        }

        default void add(final long row, final long col, final short addend) {
            this.add(row, col, (int) addend);
        }

        @Override
        default void add(final long index, final short addend) {
            long structure = this.countRows();
            this.add(Structure2D.row(index, structure), Structure2D.column(index, structure), addend);
        }

        default void modifyColumn(final long row, final long col, final UnaryFunction modifier) {
            for (long i = row, limit = this.countRows(); i < limit; i++) {
                this.modifyOne(i, col, modifier);
            }
        }

        default void modifyColumn(final long col, final UnaryFunction modifier) {
            this.modifyColumn(0L, col, modifier);
        }

        default void modifyDiagonal(final long row, final long col, final UnaryFunction modifier) {
            for (long ij = 0L, limit = Math.min(this.countRows() - row, this.countColumns() - col); ij < limit; ij++) {
                this.modifyOne(row + ij, col + ij, modifier);
            }
        }

        default void modifyDiagonal(final UnaryFunction modifier) {
            this.modifyDiagonal(0L, 0L, modifier);
        }

        /**
         * "Matching In Columns" refers to that the supplied, left, data structure will be treated as a
         * column, matching the columns of this structure. Matching columns have the same number of rows.
         * 

* This method will modify all elements of this structure by applying the modifier function to each of * them. The left/first argument to the modifier function is taken from the supplied data structure, * and the row-index determines which element. */ default void modifyMatchingInColumns(final Access1D left, final BinaryFunction function) { for (long r = 0L, limit = Math.min(left.count(), this.countRows()); r < limit; r++) { this.modifyRow(r, function.first(left.get(r))); } } /** * Same as {@link #modifyMatchingInColumns(Access1D, BinaryFunction)} but with the arguments to the * modifier function swapped. */ default void modifyMatchingInColumns(final BinaryFunction function, final Access1D right) { for (long r = 0L, limit = Math.min(this.countRows(), right.count()); r < limit; r++) { this.modifyRow(r, function.second(right.get(r))); } } /** * Same as {@link #modifyMatchingInColumns(Access1D, BinaryFunction)} but now the supplied left data * structure is treated as a row. (Matching rows have the same number of columns.) */ default void modifyMatchingInRows(final Access1D left, final BinaryFunction function) { for (long c = 0L, limit = Math.min(left.count(), this.countColumns()); c < limit; c++) { this.modifyColumn(c, function.first(left.get(c))); } } /** * Same as {@link #modifyMatchingInRows(Access1D, BinaryFunction)} but with the arguments to the * modifier function swapped. */ default void modifyMatchingInRows(final BinaryFunction function, final Access1D right) { for (long c = 0L, limit = Math.min(this.countColumns(), right.count()); c < limit; c++) { this.modifyColumn(c, function.second(right.get(c))); } } void modifyOne(long row, long col, UnaryFunction modifier); @Override default void modifyOne(final long index, final UnaryFunction modifier) { long structure = this.countRows(); this.modifyOne(Structure2D.row(index, structure), Structure2D.column(index, structure), modifier); } default void modifyRow(final long row, final long col, final UnaryFunction modifier) { for (long j = col, limit = this.countColumns(); j < limit; j++) { this.modifyOne(row, j, modifier); } } default void modifyRow(final long row, final UnaryFunction modifier) { this.modifyRow(row, 0L, modifier); } } /** * Apart from extending {@link org.ojalgo.structure.Mutate2D.Receiver} this interface extends * {@link org.ojalgo.structure.Mutate2D.Modifiable} and {@link Exchangeable} which both imply access to * existing elements as well as {@link Access2D} that dictates explicit access. * * @author apete */ interface ModifiableReceiver> extends Modifiable, Receiver, Exchangeable, Access2D { void modifyAny(Transformation2D modifier); /** * The "compatible" part of the method name references MATLAB's terminology "Compatible Array Sizes". * Here the possible combinations are somewhat limited as 'this' is modified in-place. * * @see https://se.mathworks.com/help/matlab/matlab_prog/compatible-array-sizes-for-basic-operations.html */ default void modifyCompatible(final Access2D left, final BinaryFunction operator) { long nbLeftRows = left.countRows(); long nbLeftCols = left.countColumns(); long nbRightRows = this.countRows(); long nbRightCols = this.countColumns(); if (nbLeftRows != 1L && nbLeftRows != nbRightRows) { throw new IllegalArgumentException("Incompatible row dimensions: " + nbLeftRows + " != " + nbRightRows); } if (nbLeftCols != 1L && nbLeftCols != nbRightCols) { throw new IllegalArgumentException("Incompatible column dimensions: " + nbLeftCols + " != " + nbRightCols); } if (nbLeftRows == 1L && nbLeftCols == 1L) { this.modifyAll(operator.first(left.get(0, 0))); } else if (nbLeftRows == 1L && nbLeftCols == nbRightCols) { this.modifyMatchingInRows(left, operator); } else if (nbLeftCols == 1L && nbLeftRows == nbRightRows) { this.modifyMatchingInColumns(left, operator); } else { FillCompatible.invoke(this, left, operator, this); } } default void modifyCompatible(final BinaryFunction operator, final Access2D right) { long nbLeftCols = this.countColumns(); long nbLeftRows = this.countRows(); long nbRightRows = right.countRows(); long nbRightCols = right.countColumns(); if (nbRightRows != 1L && nbRightRows != nbLeftRows) { throw new IllegalArgumentException("Incompatible row dimensions: " + nbLeftRows + " != " + nbRightRows); } if (nbRightCols != 1L && nbRightCols != nbLeftCols) { throw new IllegalArgumentException("Incompatible column dimensions: " + nbLeftCols + " != " + nbRightCols); } if (nbRightRows == 1L && nbRightCols == 1L) { this.modifyAll(operator.second(right.get(0, 0))); } else if (nbRightRows == 1L && nbRightCols == nbLeftCols) { this.modifyMatchingInRows(operator, right); } else if (nbRightCols == 1L && nbRightRows == nbLeftRows) { this.modifyMatchingInColumns(operator, right); } else { FillCompatible.invoke(this, this, operator, right); } } } interface Receiver> extends Fillable, Consumer> { @Override default void accept(final Access2D supplied) { if (this.isAcceptable(supplied)) { long limitRows = Math.min(this.countRows(), supplied.countRows()); long limitCols = Math.min(this.countColumns(), supplied.countColumns()); for (long j = 0L; j < limitCols; j++) { for (long i = 0L; i < limitRows; i++) { this.set(i, j, supplied.get(i, j)); } } } else { throw new ProgrammingError("Not acceptable!"); } } default boolean isAcceptable(final Structure2D supplier) { return this.countRows() >= supplier.countRows() && this.countColumns() >= supplier.countColumns(); } } @Override default void set(final int index, final byte value) { long structure = this.countRows(); this.set(Structure2D.row(index, structure), Structure2D.column(index, structure), value); } @Override default void set(final int index, final double value) { long structure = this.countRows(); this.set(Structure2D.row(index, structure), Structure2D.column(index, structure), value); } @Override default void set(final int index, final float value) { long structure = this.countRows(); this.set(Structure2D.row(index, structure), Structure2D.column(index, structure), value); } @Override default void set(final int index, final int value) { long structure = this.countRows(); this.set(Structure2D.row(index, structure), Structure2D.column(index, structure), value); } default void set(final int row, final int col, final byte value) { this.set(row, col, (short) value); } void set(int row, int col, double value); default void set(final int row, final int col, final float value) { this.set(row, col, (double) value); } default void set(final int row, final int col, final int value) { this.set(row, col, (long) value); } default void set(final int row, final int col, final long value) { this.set(row, col, (double) value); } default void set(final int row, final int col, final short value) { this.set(row, col, (int) value); } @Override default void set(final int index, final long value) { long structure = this.countRows(); this.set(Structure2D.row(index, structure), Structure2D.column(index, structure), value); } @Override default void set(final int index, final short value) { long structure = this.countRows(); this.set(Structure2D.row(index, structure), Structure2D.column(index, structure), value); } @Override default void set(final long index, final byte value) { long structure = this.countRows(); this.set(Structure2D.row(index, structure), Structure2D.column(index, structure), value); } @Override default void set(final long index, final Comparable value) { long structure = this.countRows(); this.set(Structure2D.row(index, structure), Structure2D.column(index, structure), value); } @Override default void set(final long index, final double value) { long structure = this.countRows(); this.set(Structure2D.row(index, structure), Structure2D.column(index, structure), value); } @Override default void set(final long index, final float value) { long structure = this.countRows(); this.set(Structure2D.row(index, structure), Structure2D.column(index, structure), value); } @Override default void set(final long index, final int value) { long structure = this.countRows(); this.set(Structure2D.row(index, structure), Structure2D.column(index, structure), value); } @Override default void set(final long index, final long value) { long structure = this.countRows(); this.set(Structure2D.row(index, structure), Structure2D.column(index, structure), value); } default void set(final long row, final long col, final byte value) { this.set(row, col, (short) value); } void set(long row, long col, Comparable value); default void set(final long row, final long col, final double value) { this.set(Math.toIntExact(row), Math.toIntExact(col), value); } default void set(final long row, final long col, final float value) { this.set(row, col, (double) value); } default void set(final long row, final long col, final int value) { this.set(row, col, (long) value); } default void set(final long row, final long col, final long value) { this.set(row, col, (double) value); } default void set(final long row, final long col, final short value) { this.set(row, col, (int) value); } @Override default void set(final long index, final short value) { long structure = this.countRows(); this.set(Structure2D.row(index, structure), Structure2D.column(index, structure), value); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy