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

net.algart.arrays.Matrix Maven / Gradle / Ivy

Go to download

Open-source Java libraries, supporting generalized smart arrays and matrices with elements of any types, including a wide set of 2D-, 3D- and multidimensional image processing and other algorithms, working with arrays and matrices.

There is a newer version: 1.4.23
Show newest version
/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2007-2024 Daniel Alievsky, AlgART Laboratory (http://algart.net)
 *
 * 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 net.algart.arrays;

import net.algart.math.*;

import java.util.List;
import java.util.Objects;

/**
 * 

AlgART matrix: multidimensional array.

* *

Unlike {@link Array AlgART array}, AlgART matrix is a very simple thing. * The matrix is just a pair:

* *
    *
  1. a reference to any AlgART array, so-called built-in array of the matrix, * that actually stores all matrix elements;
  2. * *
  3. the set of dimensions: a little usual array of integers — long[] dim, * describing the sizes of the multidimensional matrix in every dimension.
  4. *
* *

The product of all dimensions must be equal to the array length. Moreover, * the array must be {@link UpdatableArray#asUnresizable() unresizable}: so, the array length * cannot be changed after creating the matrix.

* *

It is supposed that all matrix elements are stored in the built-in AlgART array. * The storing scheme is traditional. For 2D matrix, the matrix element (x,y) * is stored at the position y*dim[0]+x of the array (dim[0] is the first * matrix dimension: the "width"). For 3D matrix, the matrix element (x,y,z) * is stored at the position z*dim[1]*dim[0]+y*dim[0]+x (dim[0] is the * x-dimension, dim[1] is the y-dimension). In the common case, the element of n-dimensional matrix * with coordinates i0,i1,...,in-1 is stored * in the built-in array at the position

* *
* in-1dn-2...d1d0 + ... + * i2d1d0 + * i1d0 + i0, *
* *

where dk=dim[k] (k=0,1,...,n-1) * is the dimension #k.

* *

There are 3 basic ways to create a new matrix.

* *
    *
  1. You may create a new zero-filled matrix with new allocated array by * {@link MemoryModel#newMatrix(Class, Class, long...)} * method or one of more concrete methods {@link MemoryModel#newByteMatrix(long...)}, * {@link MemoryModel#newShortMatrix(long...)}, etc.
  2. * *
  3. You may create a matrix view of an existing array with the specified dimension set * by {@link Matrices#matrix(Array, long...)} method.
  4. * *
  5. You may replace built-in array of the matrix with a new one (with the same length) * by {@link #matrix(Array)} method of the matrix instance; * the new matrix instance will be created. * It is the basic way to change some properties of the built-in array, * for example, to convert it to {@link Array#asImmutable() immutable} * or {@link Array#asCopyOnNextWrite() copy-on-next-write} form.
  6. *
* *

We do not provide special tools for accessing matrix elements by several indexes, * as "getByte(x,y)" or similar methods. But there is the {@link #index(long...) index} * method, that transforms a set of multidimensional indexes * i0, i2, ..., in-1 * into the position in the corresponded array, as described above. * Also you can get a reference to the built-in array by the {@link #array()} method. * The typical example of access to matrix elements is the following:

* *
 * Matrix<UpdatableFloatArray> m = ...;
 * m.array().setFloat(m.index(x, y, z), myValue);
 * 
* *

There are two important notes concerning usage of matrices.

* *

First, the matrix indexes in all methods ({@link #index(long...) index}, * {@link #dim(int) dim(n)}, dim argument in {@link MemoryModel#newMatrix(Class, Class, long...) * MemoryModel.newMatrix}, etc.) are ordered from the lowest index to the highest. * Please compare: for numeric matrix m, m.array().getDouble(m.index(15,10)) * returns the element #15 of the row #10. However, * for usual 2-dimensional Java array, * declared as "double[][] a", the same element is accessed as * a[10][15]!

* *

Second, the number of indexes in the {@link #index(long...) index} method * may differ from the number of dimensions ({@link #dimCount()}). * In any case, the returned position in calculated by the formula listed above * (in-1dn-2...d1d0 + ... + * i2d1d0 + * i1d0 + i0), * where i0, i2, ..., in-1 * are the coordinates passed to the method, and dk is the dimension #k * or 1 if k>={@link #dimCount()}. * In other words, it is supposed that all dimensions "after" the actual number of dimensions * are always equal to 1. For example, the one-dimensional matrix with L elements * can be interpreted as 2-dimensional Lx1 matrix, * or 3-dimensional Lx1x1 one, etc.

* *

The matrix object is immutable, that means that there are no ways to change * any dimension or the reference to the built-in AlgART array. * But the matrix elements can be modified, if the AlgART array is not * {@link Array#asImmutable() immutable}. * So, the matrix object is thread-safe or thread-compatible * in the same situations as the built-in AlgART array: see comments to {@link Array} interface.

* *

The generic argument T specifies the type of the built-in AlgART array. * Any array type can be declared here, but the contract of this interface * requires that the array must be {@link UpdatableArray#asUnresizable() unresizable}. * So, there are no ways to create a matrix with {@link MutableArray} (or its subinterface) * as the type argument, alike Matrix<MutableByteArray>: * all creation methods throw IllegalArgumentException in this case. * * @param the type of the built-in AlgART array. * @author Daniel Alievsky * @see Array * @see UpdatableArray * @see MutableArray */ public interface Matrix extends Cloneable { /** *

Continuation mode for submatrices, created by * {@link Matrix#subMatrix(long[], long[], ContinuationMode continuationMode)}, * {@link Matrix#subMatr(long[], long[], ContinuationMode continuationMode)} and similar methods. * The continuation mode is passed to those methods as the last argument and specifies, * what will be the values of elements of the returned submatrix, which lie outside the original matrix. * (This argument is not important if all submatrix elements belong to the original matrix, * i.e. if the returned matrix is a true sub-matrix of the original one.)

* *

The following continuation modes are possible:

* *
    *
  • {@link #NONE}: continuation is not allowed;
  • *
  • {@link #CYCLIC}: cyclic repetition of the original matrix along all coordinates;
  • *
  • {@link #PSEUDO_CYCLIC}: pseudo-cyclic (toroidal) repetition of the original matrix, * corresponding to the cyclic repetition of its {@link Matrix#array() built-in array}; * most of algorithms of image processing work in accordance with this model;
  • *
  • {@link #MIRROR_CYCLIC}: improved version of {@link #CYCLIC} model, where the original matrix * is repeated with "mirror reflecting"; this mode provides the best smoothness of continuation;
  • *
  • {@link #getConstantMode(Object) constant continuation}: the space outside the original matrix * is considered to be filled by some constant value.
  • *
* *

See comments to these modes for more details.

* *

Note: {@link #CYCLIC}, {@link #PSEUDO_CYCLIC} * and {@link #MIRROR_CYCLIC} modes are not applicable for matrices with zero dimensions: * if some matrix dimension {@link Matrix#dim(int) dim(k)}==0, then the corresponding * coordinate range of a submatrix must be 0..0, as for {@link #NONE} continuation mode. * See more details in comments to {@link Matrix#subMatrix(long[], long[], ContinuationMode)} method. * *

This class is immutable and thread-safe: * there are no ways to modify settings of the created instance. * Moreover, the constants {@link #NONE}, {@link #CYCLIC}, {@link #PSEUDO_CYCLIC}, {@link #MIRROR_CYCLIC}, * {@link #NULL_CONSTANT}, {@link #ZERO_CONSTANT}, {@link #NAN_CONSTANT}, * as well as constants in standard Java enumerations, are unique instances, which cannot be equal to any other * instance of this class. So, you can use == Java operator to compare objects with these constants, * instead of calling {@link #equals(Object)} method of this class.

*/ class ContinuationMode { /** * Simplest continuation mode: any continuation outside the source matrix is disabled. * *

In this mode, the element of the returned submatrix with coordinates * i0,i1,...,in-1 * always corresponds to the element of the source matrix m * with the coordinates * p0+i0,p1+i1, * ..., pn-1+in-1, * where p0,p1,...,pn-1 * are the low endpoints of all coordinates in the submatrix, * passed as the first argument of {@link Matrix#subMatrix(long[], long[], ContinuationMode)} * or {@link Matrix#subMatr(long[], long[], ContinuationMode)} method. * An attempt to read this element of the submatrix returns the corresponding element * of the source matrix m, * and an attempt to write into this element of the submatrix modifies the corresponding element * of the source matrix m. * *

In a case of this mode, {@link Matrix#subMatrix(long[], long[], ContinuationMode continuationMode)} * method is strictly equivalent to more simple {@link Matrix#subMatrix(long[], long[])}, and * {@link Matrix#subMatr(long[], long[], ContinuationMode continuationMode)} * is strictly equivalent to more simple {@link Matrix#subMatr(long[], long[])}. * In other words, all submatrix elements must lie inside the original matrix, * i.e. the returned matrix must be a true sub-matrix of the original one. * An attempt to create a submatrix with this continuation mode, * which does not lie fully inside the original matrix, leads to IndexOutOfBoundsException. */ public static final ContinuationMode NONE = new ContinuationMode("not-continued mode"); /** * The cyclic (or true-cyclic) continuation mode. * *

In this mode, the element of the returned submatrix with coordinates * i0,i1,...,in-1 * corresponds to the element of the built-in array * m.{@link Matrix#array() array()} of the source matrix m * with the index m.{@link Matrix#cyclicIndex(long...) * cyclicIndex}(p0+i0,p1+i1, * ..., pn-1+in-1), * where p0,p1,...,pn-1 * are the low endpoints of all coordinates in the submatrix, * passed as the first argument of {@link Matrix#subMatrix(long[], long[], ContinuationMode)} * or {@link Matrix#subMatr(long[], long[], ContinuationMode)} method. * An attempt to read this element of the submatrix returns the corresponding element * of the source matrix m, * and an attempt to write into this element of the submatrix modifies the corresponding element * of the source matrix m. * *

In other words, in this mode you can consider that the resulting matrix * is a submatrix of an infinite "matrix", which is come out from the original matrix * by infinite periodical repeating along all coordinate axes. */ public static final ContinuationMode CYCLIC = new ContinuationMode( "cyclically-continued mode"); /** * The pseudo-cyclic (or toroidal) continuation mode. * *

In this mode, the element of the returned submatrix with coordinates * i0,i1,...,in-1 * corresponds to the element of the built-in array * m.{@link Matrix#array() array()} of the source matrix m * with the index m.{@link Matrix#pseudoCyclicIndex(long...) * pseudoCyclicIndex}(p0+i0,p1+i1, * ..., pn-1+in-1), * where p0,p1,...,pn-1 * are the low endpoints of all coordinates in the submatrix, * passed as the first argument of {@link Matrix#subMatrix(long[], long[], ContinuationMode)} * or {@link Matrix#subMatr(long[], long[], ContinuationMode)} method. * An attempt to read this element of the submatrix returns the corresponding element * of the source matrix m, * and an attempt to write into this element of the submatrix modifies the corresponding element * of the source matrix m. * *

In other words, in this mode you can consider that the resulting matrix * is a submatrix of an infinite "matrix", which is come out from the original matrix * by infinite periodical repeating its {@link Matrix#array() built-in array}. * It is the most natural mode for many image processing algorithms, * which work directly with the built-in array instead of working with coordinates of matrix elements. */ public static final ContinuationMode PSEUDO_CYCLIC = new ContinuationMode( "pseudo-cyclically-continued mode"); /** * The mirror-cyclic continuation mode. * *

In this mode, the element of the returned submatrix with coordinates * i0,i1,...,in-1 * corresponds to the element of the built-in array * m.{@link Matrix#array() array()} of the source matrix m * with the index m.{@link Matrix#mirrorCyclicIndex(long...) * mirrorCyclicIndex}(p0+i0,p1+i1, * ..., pn-1+in-1), * where p0,p1,...,pn-1 * are the low endpoints of all coordinates in the submatrix, * passed as the first argument of {@link Matrix#subMatrix(long[], long[], ContinuationMode)} * or {@link Matrix#subMatr(long[], long[], ContinuationMode)} method. * An attempt to read this element of the submatrix returns the corresponding element * of the source matrix m, * and an attempt to write into this element of the submatrix modifies the corresponding element * of the source matrix m. * *

In other words, in this mode you can consider that the resulting matrix * is a submatrix of an infinite "matrix", which is come out from the original matrix * by infinite periodical repeating along all coordinate axes, if, while every "odd" repeating, * the matrix is symmetrically reflected along the corresponding coordinate. * In other words, it's possible to say that the matrix is infinitely reflected in each its bound as * in a mirror. Usually this mode provides the best smoothness of continuation of the matrix. */ public static final ContinuationMode MIRROR_CYCLIC = new ContinuationMode( "mirroring-cyclically-continued mode"); /** * The special case of constant continuation mode, corresponding to continuing by {@code null} * constant. Strictly equivalent to {@link #getConstantMode(Object) getConstantMode(null)} * (such a call always returns the reference to this constant). * *

Note: unlike {@link #ZERO_CONSTANT}, this mode can be used with any element type of the original matrix, * including non-primitive objects. For matrices with primitive element type, this mode is equivalent * to {@link #ZERO_CONSTANT}. */ public static final ContinuationMode NULL_CONSTANT = new ConstantImpl(null); /** * The special popular case of constant continuation mode, corresponding to continuing by 0.0d * numeric constant. Strictly equivalent to * {@link #getConstantMode(Object) getConstantMode(new Double(0.0d))} * (such a call always returns the reference to this constant). * *

Note: unlike {@link #NULL_CONSTANT}, this mode can be used only with matrices, containing elements of * some primitive type, i.e. with {@link Matrix}<? extends {@link PArray}>. */ public static final ContinuationMode ZERO_CONSTANT = new ConstantImpl(0.0d); /** * The special popular case of constant continuation mode, corresponding to continuing by * Double.NaN numeric constant. Strictly equivalent to * {@link #getConstantMode(Object) getConstantMode(new Double(Double.NaN))} * (such a call always returns the reference to this constant). * *

Note: unlike {@link #NULL_CONSTANT}, this mode can be used only with matrices, containing elements of * some primitive type, i.e. with {@link Matrix}<? extends {@link PArray}>. */ public static final ContinuationMode NAN_CONSTANT = new ConstantImpl(Double.NaN); /** * Creates an instance of this class for constant continuation mode. * *

In this mode, the element of the returned submatrix with coordinates * i0,i1,...,in-1 * corresponds to the element of the source matrix m * with the coordinates * p0+i0,p1+i1, * ..., pn-1+in-1 * (where p0,p1,...,pn-1 * are the low endpoints of all coordinates in the submatrix, * passed as the first argument of {@link Matrix#subMatrix(long[], long[], ContinuationMode)} * or {@link Matrix#subMatr(long[], long[], ContinuationMode)} method) — * if this element {@link Matrix#inside(long...) lies inside} the source matrix. * In this case, an attempt to read this element of the submatrix returns the corresponding element * of the source matrix m, * and an attempt to write into this element of the submatrix modifies the corresponding element * of the source matrix m. * In another case (if this element lies outside the source matrix), * the element is considered to be equal continuationConstant (an argument of this method): * an attempt to read it returns this constant, and * an attempt to write into this element is just ignored. * *

In other words, in this mode, you can consider that the resulting matrix * is a submatrix of an infinite "matrix", which is come out from the original matrix * by infinite appending it along all coordinates with the specified continuation constant. * *

The argument continuationConstant of this method is automatically cast to the type of * elements of the source matrix m according the following rules. * *

For non-primitive element types, the continuationConstant argument * must be some instance of the class m.{@link #elementType()}, * or its superclass, or {@code null}. * So, the type cast is trivial here. * *

For primitive element types, continuationConstant can be {@code null} or any * wrapper for primitive types: Boolean, Character, * Byte, Short, * Integer, Long, Float, Double. In this case, * the following casting rules are used while reading elements (I remind that attempts to write * outside the original matrix are ignored), * depending on the primitive type m.{@link #elementType()}: * *

    *
  • {@code null} is converted to false for bit elements or to zero (0, * (char)0, 0.0) for all other element types * (so, it is the only universal continuation constant, which can be used with any element type: * see {@link #NULL_CONSTANT});
  • * *
  • if the wrapper type corresponds to the element primitive type, the trivial default conversion * is used; in all other cases: * *
  • Boolean value v is converted to v?1:0 for numeric element types * and to v?(char)1:(char)0 for char element type; * *
  • Character value v is converted to (byte)v, * (short)v, (int)v, (long)v, * (float)v, (double)v * for corresponding numeric element types * and to v!=0 for boolean element type;
  • * *
  • Byte value v is converted to (char)(v&0xFF), * (short)(v&0xFF), (int)(v&0xFF), (long)(v&0xFF), * (float)(v&0xFF), (double)(v&0xFF) * for corresponding numeric or character element types * and to v!=0 for boolean element type;
  • * *
  • Short value v is converted to (char)v, * (byte)v, (int)(v&0xFFFF), (long)(v&0xFFFF), * (float)(v&0xFFFF), (double)(v&0xFFFF) * for corresponding numeric or character element types * and to v!=0 for boolean element type;
  • * *
  • Integer, Long, Float or Double value v * is converted to (char)v, * (byte)v, (short)v, (int)v, (long)v, * (float)v, (double)v * for corresponding numeric or character element types * and to v!=0 for boolean element type.
  • *
* * @param continuationConstant the value returned while reading elements, lying outside this matrix. * @return new continuation mode with the specified continuation constant. */ public static ContinuationMode getConstantMode(Object continuationConstant) { if (continuationConstant == null) { return NULL_CONSTANT; } if (ZERO_CONSTANT.continuationConstant().equals(continuationConstant)) { return ZERO_CONSTANT; } if (NAN_CONSTANT.continuationConstant().equals(continuationConstant)) { return NAN_CONSTANT; } return new ConstantImpl(continuationConstant); } private final String description; private ContinuationMode(String description) { assert description != null; this.description = description; } /** * Returns true if and only if this instance is a constant continuation mode, * i.e. was created by {@link #getConstantMode(Object)} method, or it is one * of the predefined constants {@link #ZERO_CONSTANT} and {@link #NULL_CONSTANT}. * * @return whether it is a constant continuation mode. */ public boolean isConstant() { return false; } /** * Returns true if and only if {@link #isConstant()} returns true and * the result of {@link #continuationConstant()} is {@code null} or is an instance of * some wrapper for primitive types: Boolean, Character, * Byte, Short, * Integer, Long, Float or Double. * *

This method indicates, whether this mode can be used for constant continuation of a matrix * with primitive type of elements. But note that such a mode can also be used for continuation of * a matrix, consisting of non-primitive elements, belonging to the corresponding wrapper type * or its superclass like Number or Object. * * @return whether it is a constant continuation mode, where the continuation constant is {@code null} * or some Java wrapper object for a primitive type. */ public boolean isPrimitiveTypeOrNullConstant() { return false; } /** * Returns the continuation constant, used in this mode, if it is a * {@link #isConstant() constant continuation mode}, * or throws {@link NonConstantMatrixContinuationModeException}, * if it is not a constant continuation mode. * *

If this instance was created by {@link #getConstantMode(Object)} method, * this method returns exactly the same reference to an object, which was passed * to that method as continuationConstant argument. * For {@link #NULL_CONSTANT}, this method returns {@code null}. * For {@link #ZERO_CONSTANT}, this method returns Double.valueOf(0.0d). * For {@link #NAN_CONSTANT}, this method returns Double.valueOf(Double.NaN). * * @return the continuation constant, used in this mode, * if it is a {@link #isConstant() constant continuation mode}, * @throws NonConstantMatrixContinuationModeException if this mode is not a constant continuation mode. * @see #isConstant() */ public Object continuationConstant() { throw new NonConstantMatrixContinuationModeException(this + " has no continuation constant"); } /** * Returns a brief string description of this object. * *

The result of this method may depend on implementation. * * @return a brief string description of this object. */ @Override public String toString() { return description; } /** * Returns the hash code of this object. * * @return the hash code of this object. */ @Override public int hashCode() { Object constant = isConstant() ? continuationConstant() : null; return description.hashCode() ^ (constant != null ? constant.hashCode() : 157); } /** * Indicates whether some continuation mode is equal to this instance. * *

If the argument is {@code null} or not an instance of this class, * this method returns false. * *

If this instance is a {@link #isConstant() constant continuation mode}, * this method returns true if and only if the argument is also a constant continuation mode * and either both continuation constants, returned by {@link #continuationConstant()} method, * are {@code null}, or they are equal objects in terms of standard equals method * (i.e. equal method of the {@link #continuationConstant()} object returns true * for ((ContinuationMode)o).{@link #continuationConstant()}). * *

If this instance is not a constant continuation mode, this method returns true * if and only if this instance and o argument are the same reference (this==o). * It is correct, because all only possible non-constant instances of this class are represented * by static constants of this class, as well as in standard enumerations. * * @param o the object to be compared for equality with this instance. * @return true if the specified object is a continuation mode equal to this one. */ @Override public boolean equals(Object o) { if (!isConstant() || this == o) { return this == o; } if (!(o instanceof ContinuationMode && ((ContinuationMode) o).isConstant())) { return false; } Object constant = continuationConstant(); return constant == null ? ((ContinuationMode) o).continuationConstant() == null : constant.equals(((ContinuationMode) o).continuationConstant()); } private static class ConstantImpl extends ContinuationMode { private final Object continuationConstant; private final boolean primitiveTypeOrNullConstant; private ConstantImpl(Object continuationConstant) { super("constantly-continued (by " + continuationConstant + ") mode"); this.continuationConstant = continuationConstant; this.primitiveTypeOrNullConstant = continuationConstant == null || continuationConstant instanceof Boolean || continuationConstant instanceof Character || continuationConstant instanceof Byte || continuationConstant instanceof Short || continuationConstant instanceof Integer || continuationConstant instanceof Long || continuationConstant instanceof Float || continuationConstant instanceof Double; } @Override public boolean isConstant() { return true; } @Override public Object continuationConstant() { return continuationConstant; } @Override public boolean isPrimitiveTypeOrNullConstant() { return primitiveTypeOrNullConstant; } } } /** * Maximal number of dimensions for some complex algorithms or service classes: {@value}. * Most modules process matrices with any number of dimensions, but there are some cases * when an algorithm can work only with 2-dimensional, 3-dimensional or n-dimensional matrices with * n<={@link #MAX_DIM_COUNT_FOR_SOME_ALGORITHMS}. * In this package and all known subpackages of net.algart package, * the following classes require that the number of dimensions must not be greater * than {@link #MAX_DIM_COUNT_FOR_SOME_ALGORITHMS}: *

    *
  • net.algart.matrices.scanning.ConnectedObjectScanner;
  • *
  • {@link MatrixInfo}.
  • *
* *

Note: the value of this constant ({@value}) is the maximal n so that * 3n<32768=215 (39=19683). * It can be useful while storing indexes of elements of little 3x3x3x... submatrix (aperture): * signed short type is enough in this case. */ int MAX_DIM_COUNT_FOR_SOME_ALGORITHMS = 9; /** * Returns a reference to the built-in AlgART array. * *

There is a guarantee that this method works very quickly * (usually it just returns a value of some private field). * * @return a reference to the built-in AlgART array. */ T array(); /** * Returns the type of matrix elements. * Equivalent to {@link #array()}.{@link Array#elementType() elementType()}. * * @return the type of the matrix elements. */ Class elementType(); /** * Equivalent to {@link #array()}.{@link Array#toJavaArray() toJavaArray()}. * * @return Java array containing all the elements in this matrix. * @throws TooLargeArrayException if the array length is greater than Integer.MAX_VALUE. * @see #toByte() * @see #toChar() * @see #toShort() * @see #toInt() * @see #toLong() * @see #toFloat() * @see #toDouble() * @see #ja() * @see Array#toJavaArray() */ Object toJavaArray(); /** * Equivalent to {@link #array()}.{@link Array#ja() ja()}. * * @return Java array, equivalent to {@link #array()}. * @throws TooLargeArrayException if the array length is greater than Integer.MAX_VALUE. * @see #jaByte() * @see #jaChar() * @see #jaShort() * @see #jaInt() * @see #jaLong() * @see #jaFloat() * @see #jaDouble() * @see #toJavaArray() * @see Array#ja() */ Object ja(); /*Repeat() byte ==> char,,short,,int,,long,,float,,double;; Byte ==> Char,,Short,,Int,,Long,,Float,,Double */ /** * Equivalent to (PArray) {@link #array()}.{@link PArray#toByte() toByte()}. * However, if the built-in AlgART array is not {@link PArray}, in other words, * if this matrix contains objects (non-primitive elements), this method * throws {@link UnsupportedOperationException} instead of {@link ClassCastException}. * * @return Java array containing all the elements in this matrix, cast to byte type. * @throws UnsupportedOperationException if {@link #array()} is not {@link PArray}. * @throws TooLargeArrayException if the matrix size is greater than Integer.MAX_VALUE. * @see #toByte(byte[]) * @see #jaByte() * @see #toJavaArray() * @see PArray#toByte() */ default byte[] toByte() { return toByte(null); } /** * Equivalent to (PArray) {@link #array()}.{@link PArray#toByte(byte[]) toByte(result)}. * However, if the built-in AlgART array is not {@link PArray}, in other words, * if this matrix contains objects (non-primitive elements), this method * throws {@link UnsupportedOperationException} instead of {@link ClassCastException}. * * @param result the result byte[] array; can be {@code null}, * then it will be created automatically. * @return a reference to result argument or (when result==null) a newly created array: * Java array containing all the elements in this matrix, * cast to byte type according to AlgART rules. * @throws UnsupportedOperationException if {@link #array()} is not {@link PArray}. * @throws TooLargeArrayException if the matrix size is greater than Integer.MAX_VALUE. * @throws IndexOutOfBoundsException if the result argument is not {@code null}, but its length * is too small: less than {@link Matrix#size() matrix.size()}. * @see #toByte() * @see #jaByte() * @see #toJavaArray() * @see PArray#toByte(byte[]) */ default byte[] toByte(byte[] result) { if (!(array() instanceof PArray a)) { throw new UnsupportedOperationException("Matrix, containing non-primitive (Object) elements, " + "cannot be accessed using toByte(): " + this); } return a.toByte(result); } /** * Equivalent to (PArray) {@link #array()}.{@link PArray#jaByte() jaByte()}. * However, if the built-in AlgART array is not {@link PArray}, in other words, * if this matrix contains objects (non-primitive elements), this method * throws {@link UnsupportedOperationException} instead of {@link ClassCastException}. * * @return Java array containing all the elements in this matrix, cast to byte type * according to AlgART rules. * @throws UnsupportedOperationException if {@link #array()} is not {@link PArray}. * @throws TooLargeArrayException if the array length is greater than Integer.MAX_VALUE. * @see #toByte() * @see #toByte(byte[]) * @see #ja * @see PArray#jaByte() */ default byte[] jaByte() { if (!(array() instanceof PArray a)) { throw new UnsupportedOperationException("Matrix, containing non-primitive (Object) elements, " + "cannot be accessed using jaByte(): " + this); } return a.jaByte(); } /*Repeat.AutoGeneratedStart !! Auto-generated: NOT EDIT !! */ /** * Equivalent to (PArray) {@link #array()}.{@link PArray#toChar() toChar()}. * However, if the built-in AlgART array is not {@link PArray}, in other words, * if this matrix contains objects (non-primitive elements), this method * throws {@link UnsupportedOperationException} instead of {@link ClassCastException}. * * @return Java array containing all the elements in this matrix, cast to char type. * @throws UnsupportedOperationException if {@link #array()} is not {@link PArray}. * @throws TooLargeArrayException if the matrix size is greater than Integer.MAX_VALUE. * @see #toChar(char[]) * @see #jaChar() * @see #toJavaArray() * @see PArray#toChar() */ default char[] toChar() { return toChar(null); } /** * Equivalent to (PArray) {@link #array()}.{@link PArray#toChar(char[]) toChar(result)}. * However, if the built-in AlgART array is not {@link PArray}, in other words, * if this matrix contains objects (non-primitive elements), this method * throws {@link UnsupportedOperationException} instead of {@link ClassCastException}. * * @param result the result char[] array; can be {@code null}, * then it will be created automatically. * @return a reference to result argument or (when result==null) a newly created array: * Java array containing all the elements in this matrix, * cast to char type according to AlgART rules. * @throws UnsupportedOperationException if {@link #array()} is not {@link PArray}. * @throws TooLargeArrayException if the matrix size is greater than Integer.MAX_VALUE. * @throws IndexOutOfBoundsException if the result argument is not {@code null}, but its length * is too small: less than {@link Matrix#size() matrix.size()}. * @see #toChar() * @see #jaChar() * @see #toJavaArray() * @see PArray#toChar(char[]) */ default char[] toChar(char[] result) { if (!(array() instanceof PArray a)) { throw new UnsupportedOperationException("Matrix, containing non-primitive (Object) elements, " + "cannot be accessed using toChar(): " + this); } return a.toChar(result); } /** * Equivalent to (PArray) {@link #array()}.{@link PArray#jaChar() jaChar()}. * However, if the built-in AlgART array is not {@link PArray}, in other words, * if this matrix contains objects (non-primitive elements), this method * throws {@link UnsupportedOperationException} instead of {@link ClassCastException}. * * @return Java array containing all the elements in this matrix, cast to char type * according to AlgART rules. * @throws UnsupportedOperationException if {@link #array()} is not {@link PArray}. * @throws TooLargeArrayException if the array length is greater than Integer.MAX_VALUE. * @see #toChar() * @see #toChar(char[]) * @see #ja * @see PArray#jaChar() */ default char[] jaChar() { if (!(array() instanceof PArray a)) { throw new UnsupportedOperationException("Matrix, containing non-primitive (Object) elements, " + "cannot be accessed using jaChar(): " + this); } return a.jaChar(); } /** * Equivalent to (PArray) {@link #array()}.{@link PArray#toShort() toShort()}. * However, if the built-in AlgART array is not {@link PArray}, in other words, * if this matrix contains objects (non-primitive elements), this method * throws {@link UnsupportedOperationException} instead of {@link ClassCastException}. * * @return Java array containing all the elements in this matrix, cast to short type. * @throws UnsupportedOperationException if {@link #array()} is not {@link PArray}. * @throws TooLargeArrayException if the matrix size is greater than Integer.MAX_VALUE. * @see #toShort(short[]) * @see #jaShort() * @see #toJavaArray() * @see PArray#toShort() */ default short[] toShort() { return toShort(null); } /** * Equivalent to (PArray) {@link #array()}.{@link PArray#toShort(short[]) toShort(result)}. * However, if the built-in AlgART array is not {@link PArray}, in other words, * if this matrix contains objects (non-primitive elements), this method * throws {@link UnsupportedOperationException} instead of {@link ClassCastException}. * * @param result the result short[] array; can be {@code null}, * then it will be created automatically. * @return a reference to result argument or (when result==null) a newly created array: * Java array containing all the elements in this matrix, * cast to short type according to AlgART rules. * @throws UnsupportedOperationException if {@link #array()} is not {@link PArray}. * @throws TooLargeArrayException if the matrix size is greater than Integer.MAX_VALUE. * @throws IndexOutOfBoundsException if the result argument is not {@code null}, but its length * is too small: less than {@link Matrix#size() matrix.size()}. * @see #toShort() * @see #jaShort() * @see #toJavaArray() * @see PArray#toShort(short[]) */ default short[] toShort(short[] result) { if (!(array() instanceof PArray a)) { throw new UnsupportedOperationException("Matrix, containing non-primitive (Object) elements, " + "cannot be accessed using toShort(): " + this); } return a.toShort(result); } /** * Equivalent to (PArray) {@link #array()}.{@link PArray#jaShort() jaShort()}. * However, if the built-in AlgART array is not {@link PArray}, in other words, * if this matrix contains objects (non-primitive elements), this method * throws {@link UnsupportedOperationException} instead of {@link ClassCastException}. * * @return Java array containing all the elements in this matrix, cast to short type * according to AlgART rules. * @throws UnsupportedOperationException if {@link #array()} is not {@link PArray}. * @throws TooLargeArrayException if the array length is greater than Integer.MAX_VALUE. * @see #toShort() * @see #toShort(short[]) * @see #ja * @see PArray#jaShort() */ default short[] jaShort() { if (!(array() instanceof PArray a)) { throw new UnsupportedOperationException("Matrix, containing non-primitive (Object) elements, " + "cannot be accessed using jaShort(): " + this); } return a.jaShort(); } /** * Equivalent to (PArray) {@link #array()}.{@link PArray#toInt() toInt()}. * However, if the built-in AlgART array is not {@link PArray}, in other words, * if this matrix contains objects (non-primitive elements), this method * throws {@link UnsupportedOperationException} instead of {@link ClassCastException}. * * @return Java array containing all the elements in this matrix, cast to int type. * @throws UnsupportedOperationException if {@link #array()} is not {@link PArray}. * @throws TooLargeArrayException if the matrix size is greater than Integer.MAX_VALUE. * @see #toInt(int[]) * @see #jaInt() * @see #toJavaArray() * @see PArray#toInt() */ default int[] toInt() { return toInt(null); } /** * Equivalent to (PArray) {@link #array()}.{@link PArray#toInt(int[]) toInt(result)}. * However, if the built-in AlgART array is not {@link PArray}, in other words, * if this matrix contains objects (non-primitive elements), this method * throws {@link UnsupportedOperationException} instead of {@link ClassCastException}. * * @param result the result int[] array; can be {@code null}, * then it will be created automatically. * @return a reference to result argument or (when result==null) a newly created array: * Java array containing all the elements in this matrix, * cast to int type according to AlgART rules. * @throws UnsupportedOperationException if {@link #array()} is not {@link PArray}. * @throws TooLargeArrayException if the matrix size is greater than Integer.MAX_VALUE. * @throws IndexOutOfBoundsException if the result argument is not {@code null}, but its length * is too small: less than {@link Matrix#size() matrix.size()}. * @see #toInt() * @see #jaInt() * @see #toJavaArray() * @see PArray#toInt(int[]) */ default int[] toInt(int[] result) { if (!(array() instanceof PArray a)) { throw new UnsupportedOperationException("Matrix, containing non-primitive (Object) elements, " + "cannot be accessed using toInt(): " + this); } return a.toInt(result); } /** * Equivalent to (PArray) {@link #array()}.{@link PArray#jaInt() jaInt()}. * However, if the built-in AlgART array is not {@link PArray}, in other words, * if this matrix contains objects (non-primitive elements), this method * throws {@link UnsupportedOperationException} instead of {@link ClassCastException}. * * @return Java array containing all the elements in this matrix, cast to int type * according to AlgART rules. * @throws UnsupportedOperationException if {@link #array()} is not {@link PArray}. * @throws TooLargeArrayException if the array length is greater than Integer.MAX_VALUE. * @see #toInt() * @see #toInt(int[]) * @see #ja * @see PArray#jaInt() */ default int[] jaInt() { if (!(array() instanceof PArray a)) { throw new UnsupportedOperationException("Matrix, containing non-primitive (Object) elements, " + "cannot be accessed using jaInt(): " + this); } return a.jaInt(); } /** * Equivalent to (PArray) {@link #array()}.{@link PArray#toLong() toLong()}. * However, if the built-in AlgART array is not {@link PArray}, in other words, * if this matrix contains objects (non-primitive elements), this method * throws {@link UnsupportedOperationException} instead of {@link ClassCastException}. * * @return Java array containing all the elements in this matrix, cast to long type. * @throws UnsupportedOperationException if {@link #array()} is not {@link PArray}. * @throws TooLargeArrayException if the matrix size is greater than Integer.MAX_VALUE. * @see #toLong(long[]) * @see #jaLong() * @see #toJavaArray() * @see PArray#toLong() */ default long[] toLong() { return toLong(null); } /** * Equivalent to (PArray) {@link #array()}.{@link PArray#toLong(long[]) toLong(result)}. * However, if the built-in AlgART array is not {@link PArray}, in other words, * if this matrix contains objects (non-primitive elements), this method * throws {@link UnsupportedOperationException} instead of {@link ClassCastException}. * * @param result the result long[] array; can be {@code null}, * then it will be created automatically. * @return a reference to result argument or (when result==null) a newly created array: * Java array containing all the elements in this matrix, * cast to long type according to AlgART rules. * @throws UnsupportedOperationException if {@link #array()} is not {@link PArray}. * @throws TooLargeArrayException if the matrix size is greater than Integer.MAX_VALUE. * @throws IndexOutOfBoundsException if the result argument is not {@code null}, but its length * is too small: less than {@link Matrix#size() matrix.size()}. * @see #toLong() * @see #jaLong() * @see #toJavaArray() * @see PArray#toLong(long[]) */ default long[] toLong(long[] result) { if (!(array() instanceof PArray a)) { throw new UnsupportedOperationException("Matrix, containing non-primitive (Object) elements, " + "cannot be accessed using toLong(): " + this); } return a.toLong(result); } /** * Equivalent to (PArray) {@link #array()}.{@link PArray#jaLong() jaLong()}. * However, if the built-in AlgART array is not {@link PArray}, in other words, * if this matrix contains objects (non-primitive elements), this method * throws {@link UnsupportedOperationException} instead of {@link ClassCastException}. * * @return Java array containing all the elements in this matrix, cast to long type * according to AlgART rules. * @throws UnsupportedOperationException if {@link #array()} is not {@link PArray}. * @throws TooLargeArrayException if the array length is greater than Integer.MAX_VALUE. * @see #toLong() * @see #toLong(long[]) * @see #ja * @see PArray#jaLong() */ default long[] jaLong() { if (!(array() instanceof PArray a)) { throw new UnsupportedOperationException("Matrix, containing non-primitive (Object) elements, " + "cannot be accessed using jaLong(): " + this); } return a.jaLong(); } /** * Equivalent to (PArray) {@link #array()}.{@link PArray#toFloat() toFloat()}. * However, if the built-in AlgART array is not {@link PArray}, in other words, * if this matrix contains objects (non-primitive elements), this method * throws {@link UnsupportedOperationException} instead of {@link ClassCastException}. * * @return Java array containing all the elements in this matrix, cast to float type. * @throws UnsupportedOperationException if {@link #array()} is not {@link PArray}. * @throws TooLargeArrayException if the matrix size is greater than Integer.MAX_VALUE. * @see #toFloat(float[]) * @see #jaFloat() * @see #toJavaArray() * @see PArray#toFloat() */ default float[] toFloat() { return toFloat(null); } /** * Equivalent to (PArray) {@link #array()}.{@link PArray#toFloat(float[]) toFloat(result)}. * However, if the built-in AlgART array is not {@link PArray}, in other words, * if this matrix contains objects (non-primitive elements), this method * throws {@link UnsupportedOperationException} instead of {@link ClassCastException}. * * @param result the result float[] array; can be {@code null}, * then it will be created automatically. * @return a reference to result argument or (when result==null) a newly created array: * Java array containing all the elements in this matrix, * cast to float type according to AlgART rules. * @throws UnsupportedOperationException if {@link #array()} is not {@link PArray}. * @throws TooLargeArrayException if the matrix size is greater than Integer.MAX_VALUE. * @throws IndexOutOfBoundsException if the result argument is not {@code null}, but its length * is too small: less than {@link Matrix#size() matrix.size()}. * @see #toFloat() * @see #jaFloat() * @see #toJavaArray() * @see PArray#toFloat(float[]) */ default float[] toFloat(float[] result) { if (!(array() instanceof PArray a)) { throw new UnsupportedOperationException("Matrix, containing non-primitive (Object) elements, " + "cannot be accessed using toFloat(): " + this); } return a.toFloat(result); } /** * Equivalent to (PArray) {@link #array()}.{@link PArray#jaFloat() jaFloat()}. * However, if the built-in AlgART array is not {@link PArray}, in other words, * if this matrix contains objects (non-primitive elements), this method * throws {@link UnsupportedOperationException} instead of {@link ClassCastException}. * * @return Java array containing all the elements in this matrix, cast to float type * according to AlgART rules. * @throws UnsupportedOperationException if {@link #array()} is not {@link PArray}. * @throws TooLargeArrayException if the array length is greater than Integer.MAX_VALUE. * @see #toFloat() * @see #toFloat(float[]) * @see #ja * @see PArray#jaFloat() */ default float[] jaFloat() { if (!(array() instanceof PArray a)) { throw new UnsupportedOperationException("Matrix, containing non-primitive (Object) elements, " + "cannot be accessed using jaFloat(): " + this); } return a.jaFloat(); } /** * Equivalent to (PArray) {@link #array()}.{@link PArray#toDouble() toDouble()}. * However, if the built-in AlgART array is not {@link PArray}, in other words, * if this matrix contains objects (non-primitive elements), this method * throws {@link UnsupportedOperationException} instead of {@link ClassCastException}. * * @return Java array containing all the elements in this matrix, cast to double type. * @throws UnsupportedOperationException if {@link #array()} is not {@link PArray}. * @throws TooLargeArrayException if the matrix size is greater than Integer.MAX_VALUE. * @see #toDouble(double[]) * @see #jaDouble() * @see #toJavaArray() * @see PArray#toDouble() */ default double[] toDouble() { return toDouble(null); } /** * Equivalent to (PArray) {@link #array()}.{@link PArray#toDouble(double[]) toDouble(result)}. * However, if the built-in AlgART array is not {@link PArray}, in other words, * if this matrix contains objects (non-primitive elements), this method * throws {@link UnsupportedOperationException} instead of {@link ClassCastException}. * * @param result the result double[] array; can be {@code null}, * then it will be created automatically. * @return a reference to result argument or (when result==null) a newly created array: * Java array containing all the elements in this matrix, * cast to double type according to AlgART rules. * @throws UnsupportedOperationException if {@link #array()} is not {@link PArray}. * @throws TooLargeArrayException if the matrix size is greater than Integer.MAX_VALUE. * @throws IndexOutOfBoundsException if the result argument is not {@code null}, but its length * is too small: less than {@link Matrix#size() matrix.size()}. * @see #toDouble() * @see #jaDouble() * @see #toJavaArray() * @see PArray#toDouble(double[]) */ default double[] toDouble(double[] result) { if (!(array() instanceof PArray a)) { throw new UnsupportedOperationException("Matrix, containing non-primitive (Object) elements, " + "cannot be accessed using toDouble(): " + this); } return a.toDouble(result); } /** * Equivalent to (PArray) {@link #array()}.{@link PArray#jaDouble() jaDouble()}. * However, if the built-in AlgART array is not {@link PArray}, in other words, * if this matrix contains objects (non-primitive elements), this method * throws {@link UnsupportedOperationException} instead of {@link ClassCastException}. * * @return Java array containing all the elements in this matrix, cast to double type * according to AlgART rules. * @throws UnsupportedOperationException if {@link #array()} is not {@link PArray}. * @throws TooLargeArrayException if the array length is greater than Integer.MAX_VALUE. * @see #toDouble() * @see #toDouble(double[]) * @see #ja * @see PArray#jaDouble() */ default double[] jaDouble() { if (!(array() instanceof PArray a)) { throw new UnsupportedOperationException("Matrix, containing non-primitive (Object) elements, " + "cannot be accessed using jaDouble(): " + this); } return a.jaDouble(); } /*Repeat.AutoGeneratedEnd*/ /** * Returns the total number of matrix elements. * Equivalent to {@link #array()}.{@link Array#length() length()}. * * @return the total number of matrix elements. */ default long size() { return array().length(); } /** * Returns the total number of matrix elements as 32-bit int value. * Equivalent to {@link #array()}.{@link Array#length32() length32()}. * * @return the total number of matrix elements, if it is less than 231. * @throws TooLargeArrayException if the total number of matrix elements is greater than * Integer.MAX_VALUE=231−1. */ default int size32() { return array().length32(); } /** * Equivalent to the call {@link #size() size}() == 0. * * @return true if the matrix is empty, i.e. at least one its dimensions is zero. */ default boolean isEmpty() { return array().isEmpty(); } /** * Returns {@link #array()}.{@link Array#type() type()}. * * @return the canonical type of AlgART array of the same kind as the built-in one. * @throws NullPointerException if the passed argument is {@code null}. */ Class type(); /** * Returns {@link #array()}.{@link Array#updatableType() updatableType()}. * * @return the canonical updatable type of AlgART array of the same kind as the built-in one. * @throws NullPointerException if the passed argument is {@code null}. */ Class updatableType(); /** * Returns {@link #array()}.{@link Array#type() type()}, * if it is a subtype of (or same type as) the passed arraySupertype, * or throws ClassCastException in another case. * (If the passed argument is a class of {@link UpdatableArray} or some its * subinterfaces or subclasses, IllegalArgumentException is thrown instead: * updatable array classes cannot be specified in this method.) * * @param the generic type of AlgART array. * @param arraySupertype the required supertype of the built-in AlgART array. * @return the canonical type of AlgART array of the same kind as the built-in one. * @throws NullPointerException if the passed argument is {@code null}. * @throws IllegalArgumentException if the passed argument is a class of {@link UpdatableArray} or some its * subinterfaces or subclasses (updatable classes cannot be supertypes of * for {@link Array#type() Array.type()}). * @throws ClassCastException if arraySupertype does not allow storing * the immutable version of the built-in AlgART array. */ Class type(Class arraySupertype); /** * Returns {@link #array()}.{@link Array#updatableType() updatableType()}, * if it is a subtype of (or same type as) the passed arraySupertype, * or throws ClassCastException in another case. * * @param the generic type of AlgART array. * @param arraySupertype the required supertype of the built-in AlgART array. * @return the canonical updatable type of AlgART array of the same kind as the built-in one. * @throws NullPointerException if the passed argument is {@code null}. * @throws ClassCastException if arraySupertype does not allow storing * the built-in AlgART array. */ Class updatableType(Class arraySupertype); /** * Returns true if and only if the {@link #elementType() element type} is primitive: * {@link #array()} instanceof {@link PArray}. * * @return whether the type of matrix element is boolean, char, byte, short, int, long, float or double. */ boolean isPrimitive(); /** * Returns true if and only if the {@link #elementType() element type} is float * or double: * {@link #array()} instanceof {@link PFloatingArray}. * * @return whether the type of matrix element is float or double. */ boolean isFloatingPoint(); /** * Returns true if and only if the {@link #elementType() element type} is fixed-point: * {@link #array()} instanceof {@link PFixedArray}. * * @return whether the type of matrix element is byte, short, int, long, char or boolean. */ boolean isFixedPoint(); /** * Returns true if and only if the {@link #elementType() element type} is boolean.class, * short.class, byte.class or short.class. * *

Equivalent to {@link Arrays#isUnsignedElementType(Class) * Arrays.isUnsignedElementType}(thisMatrix.{@link #elementType() elementType()}). * * @return whether the element type of this matrix should be interpreted as unsigned primitive type. */ boolean isUnsigned(); /** * Returns the number of in bits, required for each element of this matrix, if they are * {@link #isPrimitive() primitive}; in another case returns −1. * Equivalent to {@link Arrays#bitsPerElement(Class) * Arrays.bitsPerElement}(thisMatrix.{@link #elementType() elementType()}). * * @return the size of each element in bits or −1 if for non-primitive elements. */ long bitsPerElement(); /** * Returns the maximal possible value, that can stored in elements of this matrix, * if they are fixed-point elements, or the argument for floating-point elements, * or Double.NaN if elements are not primitive. * *

Equivalent to

     *     thisMatrix.{@link #isPrimitive() isPrimitive()} ?
     *         ((PArray) thisMatrix.array()).{@link PArray#maxPossibleValue(double)
     *         maxPossibleValue(valueForFloatingPoint)} :
     *         Double.NaN;
     * 
* * @param valueForFloatingPoint some "default" value returned for floating-point element type. * @return {@link #array()}.{@link PArray#maxPossibleValue maxPossibleValue()} for primitive element types, * or Double.NaN for non-primitive element types. */ double maxPossibleValue(double valueForFloatingPoint); /** * Returns the maximal possible value, that can stored in elements of this matrix, * if they are fixed-point elements, or 1.0 for floating-point elements, * or Double.NaN if elements are not primitive. * *

Equivalent to {@link #maxPossibleValue(double) maxPossibleValue(1.0)}. * It is a good default for most application. * * @return maximal possible value for primitive element types (1.0 for float/double), * or Double.NaN for non-primitive element types. */ double maxPossibleValue(); /** * Returns an array containing all dimensions of this matrix. * Returned array is equal to the dim argument passed to methods that create new matrix instances. * *

The returned array is a clone of the internal dimension array, stored in this object. * The returned array is never empty (its length cannot be zero). * The elements of the returned array are never negative. * * @return an array containing all dimensions of this matrix. */ long[] dimensions(); /** * Returns the number of dimensions of this matrix. * This value is always positive (>=1). * Equivalent to {@link #dimensions()}.length, but works faster. * *

There is a guarantee that this method works very quickly * (usually it just returns a value of some private field). * * @return the number of dimensions of this matrix. */ int dimCount(); /** * Returns the dimension #n of this matrix * or 1 if n>={@link #dimCount()}. * Equivalent to n<{@link #dimCount()}?{@link #dimensions()}[n]:1, but works faster. * *

There is a guarantee that this method works very quickly. * * @param n the index of dimension. * @return the dimension #n of this matrix or 1 if the index is too large. * @throws IndexOutOfBoundsException if n<0 (but not if n is too large). * @see #dim32(int) */ long dim(int n); /** * Returns the same result as the method {@link #dim(int) dim(n)} as 32-bit int value. * If the dimension, returned by {@link #dim(int) dim(n)}, is greater than Integer.MAX_VALUE, * throws TooLargeArrayException. * *

This method is convenient when you are sure that matrix sizes * cannot exceed the limit 231−1.

* * @param n the index of dimension. * @return the dimension #n of this matrix, if it is less than 231. * @throws IndexOutOfBoundsException if n<0 (but not if n is too large). * @throws TooLargeArrayException if this matrix dimension is greater than * Integer.MAX_VALUE=231−1. */ default int dim32(int n) { long result = dim(n); if (result < 0) { throw new AssertionError("Negative result " + result + " of dim() method"); } if (result > Integer.MAX_VALUE) { throw new TooLargeArrayException("Too large matrix dimension #" + n + " (" + result + " >= 2^31): " + this); } return (int) result; } /** * Equivalent to {@link #dim(int) dim}(0). * * @return the first matrix dimension. */ default long dimX() { return dim(0); } /** * Equivalent to {@link #dim32(int) dim32}(0). * * @return the first matrix dimension. * @throws TooLargeArrayException if this matrix dimension is greater than * Integer.MAX_VALUE=231−1. */ default int dimX32() { return dim32(0); } /** * Equivalent to {@link #dim(int) dim}(1). * * @return the second matrix dimension (or 1 for 1-dimensional matrix). */ default long dimY() { return dim(1); } /** * Equivalent to {@link #dim32(int) dim32}(1). * * @return the second matrix dimension (or 1 for 1-dimensional matrix). * @throws TooLargeArrayException if this matrix dimension is greater than * Integer.MAX_VALUE=231−1. */ default int dimY32() { return dim32(1); } /** * Equivalent to {@link #dim(int) dim}(2). * * @return the third matrix dimension (or 1 for 1-dimensional or 2-dimensional matrix). */ default long dimZ() { return dim(2); } /** * Equivalent to {@link #dim32(int) dim32}(2). * * @return the third matrix dimension (or 1 for 1-dimensional or 2-dimensional matrix). * @throws TooLargeArrayException if this matrix dimension is greater than * Integer.MAX_VALUE=231−1. */ default int dimZ32() { return dim32(2); } /** * Indicates whether the other matrix has the same dimension array. * In other words, returns true if and only if * both matrices have the same dimension count ({@link #dimCount()}) * and the corresponding dimensions ({@link #dim(int) dim(k)}) are equal. * * @param m the matrix to be compared for equal dimensions with this matrix. * @return true if the specified matrix has the same dimension array. * @throws NullPointerException if the passed argument is {@code null}. * @see #dimEquals(long...) */ boolean dimEquals(Matrix m); /** * Indicates whether the passed dimensions are equal to the dimension array of this matrix. * In other words, returns true if and only if * dimension.length=={@link #dimCount()} * and the corresponding dimensions {@link #dim(int) dim(k)}==dimension[k] for all k. * *

Note: this method does not check, whether all passed dimensions are correct (in particular, non-negative). * If some elements of the passed array are incorrect, this method just returns false. * But it the passed array is {@code null}, this method throws NullPointerException. * * @param dimensions the dimension array. * @return true if the specified dimensions are equal to the dimensions of this matrix. * @throws NullPointerException if the passed argument is {@code null}. * @see #dimEquals(Matrix) */ boolean dimEquals(long... dimensions); /** * Returns the linear index in the built-in AlgART array of the matrix element * with specified coordinates. * *

More precisely, * index(i0,i1,...,in-1) * returns the following value: * *

* in-1dn-2...d1d0 + ... + * i2d1d0 + * i1d0 + i0, *
*

* where dk={@link #dim(int) dim}(k). * All passed indexes ik must be in ranges 0..dk-1. * *

All elements of coordinates array are always used, regardless * of the number of matrix dimensions. * But the extra elements of coordinates array must be zero, * because dk=1 for k>={@link #dimCount()}. * *

Good algorithms processing the matrix should use this method rarely: * usually there are more optimal ways to calculate necessary linear index. * For example, if you just need to calculate something for all matrix elements, * the best way is the following: * *

     * Array a = m.array();
     * for (long disp = 0, n = a.length(); disp < n; disp++)
     *     // process the element #k of the array
     * 
* * @param coordinates all coordinates. * @return the linear index of the matrix element with specified coordinates. * @throws NullPointerException if the passed array is {@code null}. * @throws IllegalArgumentException if the passed array is empty (no coordinates are passed). * @throws IndexOutOfBoundsException if some coordinate ik is out of range * 0..dk-1. * @see #uncheckedIndex(long...) * @see #cyclicIndex(long...) * @see #pseudoCyclicIndex(long...) * @see #mirrorCyclicIndex(long...) * @see #coordinates(long, long[]) * @see IPoint#toOneDimensional(long[], boolean) */ long index(long... coordinates); /** * The simplified version of the full {@link #index(long...) index} method for the case * of 2-dimensional matrix. * * @param x the first coordinate. * @param y the second coordinate. * @return y * {@link #dimX()} + x. * @throws IndexOutOfBoundsException if x<0, x>={@link #dimX()}, * y<0 or y>={@link #dimX()}. */ long index(long x, long y); /** * The simplified version of the full {@link #index(long...) index} method for the case * of 3-dimensional matrix. * * @param x the first coordinate. * @param y the second coordinate. * @param z the third coordinate. * @return z * {@link #dimY()} * {@link #dimX()} + y * {@link #dimX()} + x. * @throws IndexOutOfBoundsException if x<0, x>={@link #dimX()}, * y<0, y>={@link #dimX()}, * z<0 or z>={@link #dimZ()}. */ long index(long x, long y, long z); /** * Returns the coordinates in the matrix, corresponding to the given linear index in the built-in AlgART array. * This method is reverse to {@link #index(long...)}: for any index, * {@link #index(long...) index}({@link #coordinates(long, long[]) * coordinates}(index, null)) == index. * *

The result argument can be {@code null} or some array, * containing at least {@link #dimCount()} * elements. If the first case, this method allocates new Java array long[{@link #dimCount()}] * for storing coordinates and returns it. * In the second case, this method stores the found coordinates in result array and returns it. * The returned coordinates are always in ranges *

     * 0 ≤ result[k] < {@link #dim(int) dim}(k)
* * @param index the linear index in the built-in AlgART array. * @param result the array where you want to store results; can be {@code null}. * @return a reference to the result argument, if it is not {@code null}, * else newly created Java array contains all calculated coordinates. * @throws IllegalArgumentException if result!=null, * but result.length<{@link #dimCount()}. * @throws IndexOutOfBoundsException if index<0 or index>={@link #dim(int) * dim}(0)*{@link #dim(int) dim}(1)*...={@link #array()}.{@link * Array#length() length()}. */ long[] coordinates(long index, long[] result); /** * An analog of {@link #index(long...)} method, that does not check, * whether the passed coordinates are in the required ranges. * *

More precisely, * uncheckedIndex(i0,i1,...,in-1) * always returns the following value: * *

* in-1dn-2...d1d0 + ... + * i2d1d0 + * i1d0 + i0, *
*

* where dk={@link #dim(int) dim}(k). * *

All calculations are performed with long type without any overflow checks. * All elements of coordinates array are always used, regardless of the number of matrix dimensions. * Please remember that dk={@link #dim(int) dim}(k)=1 * for k>={@link #dimCount()} * (extra elements of coordinates array). * * @param coordinates all coordinates. * @return the linear index of the matrix element with specified coordinates, without range checks. * @throws NullPointerException if the passed array is {@code null}. * @throws IllegalArgumentException if the passed array is empty (no coordinates are passed). */ long uncheckedIndex(long... coordinates); /** * An analog of {@link #index(long...)} method, that, before all calculations, * replaces the passed coordinates with the positive remainders * from division of them by the corresponding matrix dimensions. * *

More precisely, let i0,i1,...,in-1 * are the arguments of the method. Let * dk={@link #dim(int) dim}(k) and *

* i'k = dk == 0 ? 0 : * ik % dk >= 0 ? * ik % dk : * ik % dk + dk *
*

* This method returns the following value: * *

* i'n-1dn-2...d1d0 + ... + * i'2d1d0 + * i'1d0 + i'0, *
*

* In other words, the resulting index is "cyclical". * *

All elements of coordinates array are always used, * regardless of the number of matrix dimensions. * (You can note that extra elements of coordinates array are ignored in fact: * the reminders ik%dk=ik%1 will be zero for them.) * * @param coordinates all coordinates. * @return the cyclical linear index of the matrix element with specified coordinates, * without range checks. * @throws NullPointerException if the passed array is {@code null}. * @throws IllegalArgumentException if the passed array is empty (no coordinates are passed). * @see Matrix.ContinuationMode#CYCLIC */ long cyclicIndex(long... coordinates); /** * An analog of {@link #index(long...)} method, that does not check, * whether the passed coordinates are in the required ranges, * but replaces the resulting index with the positive remainder * from division of it by the length of the built-in array. * *

More precisely, let i0,i1,...,in-1 * are the arguments of the method, and index is the following value * (as in {@link #index(long...)} method): * *

* index = in-1dn-2...d1d0 + ... + * i2d1d0 + * i1d0 + i0, *
*

* where dk={@link #dim(int) dim}(k). * Here we do no require that the passed indexes ik * are in ranges 0..dk-1. * Then, let len={@link #array()}.{@link Array#length() * length()}=dn-1...d1d0. * The result of this method is the following: * *

* len == 0 ? 0 : index % len >= 0 ? * index % len : index % len + len *
*

* (It is in the 0..len-1 range always, * excepting the degenerated case len==0.) * In other words, the resulting index is "pseudo-cyclical", as the resulting shift * in {@link Matrices#asShifted(Matrix, long...)} method. * *

All elements of coordinates array are always used, * regardless of the number of matrix dimensions. * (You can note that extra elements of coordinates array are ignored in fact: * they add k*len summand, where k is an integer.) * *

Note that all calculations are performed absolutely precisely, even in a case when * the direct calculation according the formulas above leads to overflow (because some * of the values in these formulas are out of Long.MIN_VALUE..Long.MAX_VALUE range). * * @param coordinates all coordinates. * @return the pseudo-cyclical linear index of the matrix element with specified coordinates, * without range checks. * @throws NullPointerException if the passed array is {@code null}. * @throws IllegalArgumentException if the passed array is empty (no coordinates are passed). * @see IPoint#toOneDimensional(long[], boolean) * @see Matrix.ContinuationMode#PSEUDO_CYCLIC */ long pseudoCyclicIndex(long... coordinates); /** * An analog of {@link #index(long...)} method, that, before all calculations, * replaces the passed coordinates with the positive remainders * from division of them by the corresponding matrix dimensions * or with complement of these remainders on the dimensions, * as if the matrix would be reflected in each its bound as in a mirror. * *

More precisely, let i0,i1,...,in-1 * are the arguments of the method. Let * dk={@link #dim(int) dim}(k), *

* i'k = dk == 0 ? 0 : * ik % dk >= 0 ? * ik % dk : * ik % dk + dk *
* (as in {@link #cyclicIndex(long...)}) and *
* i''k = dk == 0 ? 0 : * ⌊ik / dk⌋ % 2 == 0 ? * i'k : * dk − 1 − i'k *
* (here ⌊x⌋ means the integer part of x, i.e. Math.floor(x)). * *

This method returns the following value: * *

* i''n-1dn-2...d1d0 + ... + * i''2d1d0 + * i''1d0 + i''0, *
* *

In other words, the resulting index is "mirroring-cyclical". * *

All elements of coordinates array are always used, regardless of the number of matrix dimensions. * (You can note that extra elements of coordinates array are ignored in fact: * the reminders ik%dk=ik%1 will be zero for them.) * * @param coordinates all coordinates. * @return the mirror-cyclical linear index of the matrix element with specified coordinates, * without range checks. * @throws NullPointerException if the passed array is {@code null}. * @throws IllegalArgumentException if the passed array is empty (no coordinates are passed). * @see Matrix.ContinuationMode#MIRROR_CYCLIC */ long mirrorCyclicIndex(long... coordinates); /** * Returns true if all specified coordinates ik * are inside the ranges 0..dk-1, * where dk={@link #dim(int) dim}(k). * *

This method allows simply check that the arguments of * the {@link #index(long...) index} method are correct and will not lead to * IndexOutOfBoundsException: *

     * if (matrix.inside(i1, i2, ...)) {
     *     long index = matrix.index(i1, i2, ...);
     *     // processing an element at this index
     * } else {
     *     // special branch for positions outside the matrix
     * }
     * 
* * @param coordinates all coordinates. * @return true if all specified coordinates are inside the matrix. * @throws NullPointerException if the passed array is {@code null}. * @throws IllegalArgumentException if the passed array is empty (no coordinates are passed). */ boolean inside(long... coordinates); /** * The simplified version of the full {@link #inside(long...) inside} method for the case * of 2-dimensional matrix. * * @param x the first coordinate. * @param y the second coordinate. * @return true if all specified coordinates are inside the matrix. */ boolean inside(long x, long y); /** * The simplified version of the full {@link #inside(long...) inside} method for the case * of 3-dimensional matrix. * * @param x the first coordinate. * @param y the second coordinate. * @param z the third coordinate. * @return true if all specified coordinates are inside the matrix. */ boolean inside(long x, long y, long z); /** * Returns the new matrix backed by the specified AlgART array with the same dimensions as this one. * Equivalent to {@link Matrices#matrix(Array, long...) * Matrices.matrix}(anotherArray, {@link #dimensions()}). * *

The array anotherArray must be {@link Array#isUnresizable() unresizable}, * and its length must be equal to the length of the array built-in this matrix. * * @param the generic type of AlgART array. * @param anotherArray some another AlgART array with the same length as {@link #array()}. * @return new matrix instance. * @throws NullPointerException if anotherArray argument is {@code null}. * @throws IllegalArgumentException if the passed array is resizable * (for example, implements {@link MutableArray}). * @throws SizeMismatchException if the product of all dimensions is not equal to the passed array length. */ Matrix matrix(U anotherArray); /** * Returns this matrix, cast to the specified generic array type, * or throws ClassCastException if the built-in AlgART array * cannot be cast to the required type (because the array type is not its subclass). * Works alike {@link #matrix(Array) matrix}((U)array), but returns * the reference to this instance and is compiled without "unchecked cast" warning. * *

This method is useful when you need to cast the type of AlgART array, * built in this matrix, to to its sub- or superinterface. * * @param the generic type of AlgART array. * @param arrayClass the type of built-in array in the new matrix. * @return new matrix with the same dimensions, based on the same array cast to the required type. * @throws NullPointerException if the argument is {@code null}. * @throws ClassCastException if the built-in AlgART array cannot be cast to the required type. */ Matrix cast(Class arrayClass); /** * Returns a view of the rectangular fragment of this matrix between from, * inclusive, and to, exclusive. * *

More precisely, the returned matrix consists of all elements of this one with coordinates * i0, i1, ..., in−1, * n={@link #dimCount()}, * matching the following conditions:

     *     from[0] <= i0 < to[0],
     *     from[1] <= i1 < to[1],
     *     . . .
     *     from[n-1] <= in-1 < to[n-1]
     * 
*

* So, every dimension {@link #dim(int) dim(k)} in the returned matrix will be equal to to[k]-from[k]. * The following condition must be fulfilled for all k: * 0<=from[k]<=to[k]<=thisMatrix.{@link #dim(int) dim(k)}. * The {@link #elementType() element type} of the returned matrix is identical to the element type * of this matrix. * *

This method is equivalent to the call * {@link #subMatrix(long[], long[], ContinuationMode) * subMatrix}(from,to,{@link Matrix.ContinuationMode#NONE}). * *

The built-in AlgART array of the returned matrix is backed by the built-in array of this matrix, * so — if this matrix is not {@link #isImmutable() immutable} * — any changes of the elements in the returned matrix are reflected in this matrix, and vice versa. * The returned matrix is {@link #isImmutable() immutable} if, and only if, * the built-in array of this matrix does not implement {@link UpdatableArray}. * The {@link Array#asTrustedImmutable()} method * in the built-in array of the returned matrix is equivalent to {@link Array#asImmutable()}, * and {@link Array#asCopyOnNextWrite()} method just returns the full copy of the array. * * @param from low endpoints (inclusive) of all coordinates. * @param to high endpoints (exclusive) of all coordinates. * @return a view of the specified rectangular fragment within this matrix. * @throws NullPointerException if from or to argument is {@code null}. * @throws IllegalArgumentException if from.length or to.length * is not equal to {@link #dimCount()}. * @throws IndexOutOfBoundsException if, for some k, * from[k]<0 || to[k]>{@link #dim(int) dim(k)} || * from[k]>to[k]. * @see #subMatrix(long[], long[], ContinuationMode) * @see #subMatrix(IRectangularArea) * @see #subMatr(long[], long[], ContinuationMode) * @see #subMatr(long[], long[]) * @see #isSubMatrix() */ Matrix subMatrix(long[] from, long[] to); /** * Equivalent to {@link #subMatrix(long[] from, long[] to)} method, where * from.length=to.length=area.{@link IRectangularArea#coordCount() coordCount()}, * from[k]=area.{@link IRectangularArea#min(int) min}(k), * to[k]=area.{@link IRectangularArea#max(int) max}(k)+1. * * @param area rectangular area within this matrix. * @return a view of the specified rectangular fragment within this matrix. * @throws NullPointerException if the argument is {@code null}. * @throws IllegalArgumentException if area.{@link IRectangularArea#coordCount() coordCount()} * is not equal to {@link #dimCount()}. * @throws IndexOutOfBoundsException if, for some k, * min[k]<0 || max[k]>={@link #dim(int) dim(k)}, where * min=area.{@link IRectangularArea#min() * min()}.{@link IPoint#coordinates() coordinates()} and, * max=area.{@link IRectangularArea#max() * max()}.{@link IPoint#coordinates() coordinates()}. */ Matrix subMatrix(IRectangularArea area); /** * Equivalent to {@link #subMatrix(long[], long[]) * subMatrix}(new long[]{fromX,fromY}, new long[]{toX,toY}). * Note that this matrix must be 2-dimensional * (in another case IllegalArgumentException will be thrown). * * @param fromX low endpoints (inclusive) of the first coordinate. * @param fromY low endpoints (inclusive) of the second coordinate. * @param toX high endpoints (exclusive) of the first coordinate. * @param toY high endpoints (exclusive) of the second coordinate. * @return a view of the specified rectangular fragment within this matrix. * @throws IllegalArgumentException if {@link #dimCount()}!=2. * @throws IndexOutOfBoundsException in the same situations as in {@link #subMatrix(long[], long[])}. */ Matrix subMatrix(long fromX, long fromY, long toX, long toY); /** * Equivalent to {@link #subMatrix(long[], long[]) * subMatrix}(new long[]{fromX,fromY,fromZ}, new long[]{toX,toY,toZ}). * Note that this matrix must be 3-dimensional * (in another case IllegalArgumentException will be thrown). * * @param fromX low endpoints (inclusive) of the first coordinate. * @param fromY low endpoints (inclusive) of the second coordinate. * @param fromZ low endpoints (inclusive) of the third coordinate. * @param toX high endpoints (exclusive) of the first coordinate. * @param toY high endpoints (exclusive) of the second coordinate. * @param toZ high endpoints (exclusive) of the third coordinate. * @return a view of the specified rectangular fragment within this matrix. * @throws IllegalArgumentException if {@link #dimCount()}!=3. * @throws IndexOutOfBoundsException in the same situations as in {@link #subMatrix(long[], long[])}. */ Matrix subMatrix(long fromX, long fromY, long fromZ, long toX, long toY, long toZ); /** * An extended analog of {@link #subMatrix(long[], long[])} method, allowing to get a rectangular fragment * which is not fully inside this matrix. * *

More precisely, unlike {@link #subMatrix(long[], long[])}, here * the only requirement for the from * and to coordinate boundaries is from[k]<=to[k], * but from[k] may be negative and to[k] may be greater than {@link #dim(int) dim(k)}. * (And there is also a trivial obvious requirement * to[k]-from[k]≤Long.MAX_VALUE, i.e. that the dimensions of the result must * be representable by long type.) * *

The elements of the returned matrix, that do not correspond to any elements of this one, * i.e. "lie outside" of this matrix, are considered to be equal to some values, according to * some continuation model, described by continuationMode argument. * Such "outside" elements can correspond (according some rules) to actual elements of the source elements — * then attempts to read them return the values of the corresponding source elements * and attempts to write into them modify the corresponding source elements * (it is so for {@link ContinuationMode#CYCLIC}, {@link ContinuationMode#PSEUDO_CYCLIC}, * {@link ContinuationMode#MIRROR_CYCLIC} modes), * — or can be calculated "virtually" (according some rules) — * then attempts to read them return the calculated values * and attempts to modify them are ignored * (it is so for the {@link ContinuationMode#getConstantMode(Object) constant continuation} mode). * See {@link ContinuationMode} class for more details. * *

Important note: there are two cases, when requirements to the from and to * coordinate boundaries are stronger, than described above. *

    *
  1. If continuationMode=={@link ContinuationMode#NONE}, this method is strictly * equivalent to more simple {@link Matrix#subMatrix(long[], long[])} method, * so all requirements are the same as for that method.
  2. *
  3. If continuationMode is {@link ContinuationMode#CYCLIC}, * {@link ContinuationMode#PSEUDO_CYCLIC} or {@link ContinuationMode#MIRROR_CYCLIC} * (but it is not a constant continuation mode) and some dimension #k * of this matrix is zero — {@link #dim(int) dim}(k)==0 — * then both corresponding coordinate boundaries from[k] and to[k] * must be zero (as in {@link Matrix#subMatrix(long[], long[])} method).
  4. *
* * @param from low endpoints (inclusive) of all coordinates. * @param to high endpoints (exclusive) of all coordinates. * @param continuationMode the mode of continuation outside this matrix. * @return a view of the specified rectangular fragment within this matrix. * @throws NullPointerException if from, to or continuationMode * argument is {@code null}. * @throws IllegalArgumentException if from.length or to.length * is not equal to {@link #dimCount()}. * @throws IndexOutOfBoundsException for continuationMode=={@link ContinuationMode#NONE} — * see {@link Matrix#subMatrix(long[], long[])} method; * for other cases — if, for some k, * from[k]>to[k] or * to[k]-from[k]>Long.MAX_VALUE, * or if (for some k) {@link #dim(int) dim(k)}==0 and * from[k]!=0 || to[k]!=0, * or if the product of all differences to[k]-from[k] * (i.e. desired total size of the new matrix) * is greater than Long.MAX_VALUE. * @throws ClassCastException if continuationMode is {@link * ContinuationMode#getConstantMode(Object) a constant mode}, * the {@link Matrix.ContinuationMode#continuationConstant() * continuation constant} is not {@code null} and the class of this * constant is illegal, i.e. * cannot be cast to the necessary type according the rules, specified * for the {@link * ContinuationMode#getConstantMode(Object) constant continuation mode}. * @see #subMatr(long[], long[], ContinuationMode) * @see #subMatrix(long[], long[]) * @see #subMatr(long[], long[]) * @see #isSubMatrix() */ Matrix subMatrix(long[] from, long[] to, ContinuationMode continuationMode); /** * Equivalent to {@link #subMatrix(long[] from, long[] to, ContinuationMode continuationMode)} method, where * from.length=to.length=area.{@link IRectangularArea#coordCount() coordCount()}, * from[k]=area.{@link IRectangularArea#min(int) min}(k), * to[k]=area.{@link IRectangularArea#max(int) max}(k)+1. * * @param area rectangular area within this matrix. * @param continuationMode the value returned while reading elements, lying outside this matrix. * @return a view of the specified rectangular fragment within this matrix. * @throws NullPointerException if one of the arguments is {@code null}. * @throws IllegalArgumentException if area.{@link IRectangularArea#coordCount() coordCount()} * is not equal to {@link #dimCount()}. * @throws IndexOutOfBoundsException for continuationMode=={@link ContinuationMode#NONE} — * see {@link Matrix#subMatrix(long[], long[])} method; for other cases — * if the product of all area.{@link IRectangularArea#sizes()} * (i.e. desired total size of the new matrix) * is greater than Long.MAX_VALUE. * @throws ClassCastException if continuationMode is {@link * ContinuationMode#getConstantMode(Object) a constant mode}, * the {@link Matrix.ContinuationMode#continuationConstant() * continuation constant} is not {@code null} and the class of this * constant is illegal, i.e. * cannot be cast to the necessary type according the rules, specified * for the {@link * ContinuationMode#getConstantMode(Object) constant continuation mode}. */ Matrix subMatrix(IRectangularArea area, ContinuationMode continuationMode); /** * Equivalent to {@link #subMatrix(long[], long[], ContinuationMode) * subMatrix}(new long[]{fromX,fromY}, new long[]{toX,toY}, continuationMode). * Note that this matrix must be 2-dimensional * (in another case IllegalArgumentException will be thrown). * * @param fromX low endpoints (inclusive) of the first coordinate. * @param fromY low endpoints (inclusive) of the second coordinate. * @param toX high endpoints (exclusive) of the first coordinate. * @param toY high endpoints (exclusive) of the second coordinate. * @param continuationMode the value returned while reading elements, lying outside this matrix. * @return a view of the specified rectangular fragment within this matrix. * @throws NullPointerException if continuationMode argument is {@code null}. * @throws IllegalArgumentException if {@link #dimCount()}!=2. * @throws IndexOutOfBoundsException for continuationMode=={@link ContinuationMode#NONE} — * see {@link Matrix#subMatrix(long[], long[])} method; for other cases — * if fromX>toX or toX-fromX>Long.MAX_VALUE, * or if fromY>toY or toY-fromY>Long.MAX_VALUE, * or if the product (toX-fromX)*(toY-fromY) * (i.e. desired total size of the new matrix) * is greater than Long.MAX_VALUE. * @throws ClassCastException if continuationMode is {@link * ContinuationMode#getConstantMode(Object) a constant mode}, * the {@link Matrix.ContinuationMode#continuationConstant() * continuation constant} is not {@code null} and the class of this * constant is illegal, i.e. * cannot be cast to the necessary type according the rules, specified * for the {@link * ContinuationMode#getConstantMode(Object) constant continuation mode}. */ Matrix subMatrix(long fromX, long fromY, long toX, long toY, ContinuationMode continuationMode); /** * Equivalent to {@link #subMatrix(long[], long[], ContinuationMode) * subMatrix}(new long[]{fromX,fromY,fromZ}, new long[]{toX,toY,toZ}, continuationMode). * Note that this matrix must be 3-dimensional * (in another case IllegalArgumentException will be thrown). * * @param fromX low endpoints (inclusive) of the first coordinate. * @param fromY low endpoints (inclusive) of the second coordinate. * @param fromZ low endpoints (inclusive) of the third coordinate. * @param toX high endpoints (exclusive) of the first coordinate. * @param toY high endpoints (exclusive) of the second coordinate. * @param toZ high endpoints (exclusive) of the third coordinate. * @param continuationMode the value returned while reading elements, lying outside this matrix. * @return a view of the specified rectangular fragment within this matrix. * @throws NullPointerException if continuationMode argument is {@code null}. * @throws IllegalArgumentException if {@link #dimCount()}!=3. * @throws IndexOutOfBoundsException for continuationMode=={@link ContinuationMode#NONE} — * see {@link Matrix#subMatrix(long[], long[])} method; for other cases — * or if fromY>toY or toY-fromY>Long.MAX_VALUE, * or if fromZ>toZ or toZ-fromZ>Long.MAX_VALUE, * or if the product (toX-fromX)*(toY-fromY)*(toZ-fromZ) * (i.e. desired total size of the new matrix) * is greater than Long.MAX_VALUE. * @throws ClassCastException if continuationMode is {@link * ContinuationMode#getConstantMode(Object) a constant mode}, * the {@link Matrix.ContinuationMode#continuationConstant() * continuation constant} is not {@code null} and the class of this * constant is illegal, i.e. * cannot be cast to the necessary type according the rules, specified * for the {@link * ContinuationMode#getConstantMode(Object) constant continuation mode}. */ Matrix subMatrix( long fromX, long fromY, long fromZ, long toX, long toY, long toZ, ContinuationMode continuationMode); /** * Equivalent to {@link #subMatrix(long[] from, long[] to)} method, where * from[k]=position[k] and to[k]=position[k]+dimensions[k] for all k. * * @param position low endpoints (inclusive) of all coordinates. * @param dimensions dimensions of the returned submatrix. * @return a view of the specified rectangular fragment within this matrix. * @throws NullPointerException if position or dimensions * argument is {@code null}. * @throws IllegalArgumentException if position.length or dimensions.length * is not equal to {@link #dimCount()}. * @throws IndexOutOfBoundsException if, for some k, * position[k]<0 || dimensions[k]<0 || * position[k]+dimensions[k]>{@link #dim(int) dim(k)}. * @see #subMatr(long[], long[], ContinuationMode) */ Matrix subMatr(long[] position, long[] dimensions); /** * Equivalent to {@link #subMatr(long[], long[]) * subMatr}(new long[]{x,y}, new long[]{dimX,dimY}). * Note that this matrix must be 2-dimensional * (in another case IllegalArgumentException will be thrown). * * @param x low endpoint (inclusive) of the first coordinate. * @param y low endpoint (inclusive) of the second coordinate. * @param dimX the first dimension of the returned submatrix. * @param dimY the second dimension of the returned submatrix. * @return a view of the specified rectangular fragment within this matrix. * @throws IllegalArgumentException if {@link #dimCount()}!=2. * @throws IndexOutOfBoundsException in the same situations as in {@link #subMatr(long[], long[])}. */ Matrix subMatr(long x, long y, long dimX, long dimY); /** * Equivalent to {@link #subMatr(long[], long[]) * subMatr}(new long[]{x,y,z}, new long[]{dimX,dimY,dimZ}). * Note that this matrix must be 3-dimensional * (in another case IllegalArgumentException will be thrown). * * @param x low endpoint (inclusive) of the first coordinate. * @param y low endpoint (inclusive) of the second coordinate. * @param z low endpoint (inclusive) of the third coordinate. * @param dimX the first dimension of the returned submatrix. * @param dimY the second dimension of the returned submatrix. * @param dimZ the third dimension of the returned submatrix. * @return a view of the specified rectangular fragment within this matrix. * @throws IllegalArgumentException if {@link #dimCount()}!=2. * @throws IndexOutOfBoundsException in the same situations as in {@link #subMatr(long[], long[])}. */ Matrix subMatr(long x, long y, long z, long dimX, long dimY, long dimZ); /** * Equivalent to {@link #subMatrix(long[] from, long[] to, ContinuationMode continuationMode)} method, where * from[k]=position[k] and to[k]=position[k]+dimensions[k] for all k. * * @param position low endpoints (inclusive) of all coordinates. * @param dimensions dimensions of the returned submatrix. * @param continuationMode the value returned while reading elements, lying outside this matrix. * @return a view of the specified rectangular fragment within this matrix. * @throws NullPointerException if position, dimensions * or continuationMode * argument is {@code null}. * @throws IllegalArgumentException if position.length or dimensions.length * is not equal to {@link #dimCount()}. * @throws IndexOutOfBoundsException for continuationMode=={@link ContinuationMode#NONE} — * see {@link Matrix#subMatr(long[], long[])} method; for other cases — * if, for some k, dimensions[k]<0 * or position[k]+dimensions[k]>Long.MAX_VALUE, * or if the product of all dimensions[k] * (i.e. desired total size of the new matrix) * is greater than Long.MAX_VALUE. * @throws ClassCastException if continuationMode is {@link * ContinuationMode#getConstantMode(Object) a constant mode}, * the {@link Matrix.ContinuationMode#continuationConstant() * continuation constant} is not {@code null} and the class of this * constant is illegal, i.e. * cannot be cast to the necessary type according the rules, specified * for the {@link * ContinuationMode#getConstantMode(Object) constant continuation mode}. * @see #subMatr(long[], long[]) */ Matrix subMatr(long[] position, long[] dimensions, ContinuationMode continuationMode); /** * Equivalent to {@link #subMatr(long[], long[], ContinuationMode) * subMatr}(new long[]{x,y}, new long[]{dimX,dimY}, continuationMode). * Note that this matrix must be 2-dimensional * (in another case IllegalArgumentException will be thrown). * * @param x low endpoint (inclusive) of the first coordinate. * @param y low endpoint (inclusive) of the second coordinate. * @param dimX the first dimension of the returned submatrix. * @param dimY the second dimension of the returned submatrix. * @param continuationMode the value returned while reading elements, lying outside this matrix. * @return a view of the specified rectangular fragment within this matrix. * @throws NullPointerException if continuationMode argument is {@code null}. * @throws IllegalArgumentException if {@link #dimCount()}!=2. * @throws IndexOutOfBoundsException for continuationMode=={@link ContinuationMode#NONE} — * see {@link Matrix#subMatr(long[], long[])} method; for other cases — * if dimX<0, dimY<0, * x+dimX>Long.MAX_VALUE * or y+dimY>Long.MAX_VALUE, * or if the product dimX*dimY * (i.e. desired total size of the new matrix) * is greater than Long.MAX_VALUE. * @throws ClassCastException if continuationMode is {@link * ContinuationMode#getConstantMode(Object) a constant mode}, * the {@link Matrix.ContinuationMode#continuationConstant() * continuation constant} is not {@code null} and the class of this * constant is illegal, i.e., * cannot be cast to the necessary type according the rules, specified * for the {@link * ContinuationMode#getConstantMode(Object) constant continuation mode}. */ Matrix subMatr(long x, long y, long dimX, long dimY, ContinuationMode continuationMode); /** * Equivalent to {@link #subMatr(long[], long[], ContinuationMode) * subMatr}(new long[]{x,y,z}, new long[]{dimX,dimY,dimZ}, continuationMode). * Note that this matrix must be 3-dimensional (otherwise, IllegalArgumentException will be thrown). * * @param x low endpoint (inclusive) of the first coordinate. * @param y low endpoint (inclusive) of the second coordinate. * @param z low endpoint (inclusive) of the third coordinate. * @param dimX the first dimension of the returned submatrix. * @param dimY the second dimension of the returned submatrix. * @param dimZ the third dimension of the returned submatrix. * @param continuationMode the value returned while reading elements, lying outside this matrix. * @return a view of the specified rectangular fragment within this matrix. * @throws NullPointerException if continuationMode argument is {@code null}. * @throws IllegalArgumentException if {@link #dimCount()}!=3. * @throws IndexOutOfBoundsException for continuationMode=={@link ContinuationMode#NONE} — * see {@link Matrix#subMatr(long[], long[])} method; for other cases — * if dimX<0, dimY<0, dimZ<0, * x+dimX>Long.MAX_VALUE, y+dimY>Long.MAX_VALUE * or z+dimZ>Long.MAX_VALUE, * or if the product dimX*dimY*dimZ * (i.e. desired total size of the new matrix) * is greater than Long.MAX_VALUE. * @throws ClassCastException if continuationMode is {@link * ContinuationMode#getConstantMode(Object) a constant mode}, * the {@link Matrix.ContinuationMode#continuationConstant() * continuation constant} is not {@code null} and the class of this * constant is illegal, i.e. * cannot be cast to the necessary type according the rules, specified * for the {@link * ContinuationMode#getConstantMode(Object) constant continuation mode}. */ Matrix subMatr( long x, long y, long z, long dimX, long dimY, long dimZ, ContinuationMode continuationMode); /** * Returns true if and only if this matrix is a {@link #subMatrix(long[], long[]) submatrix} of * some parent matrix, created by one of calls parent.subMatrix(...), * parent.subMatr(...) or equivalent. * The {@link #subMatrixParent()} method throws {@link NotSubMatrixException} * if and only if this method returns false. * * @return whether this object is created by subMatrix(...), * subMatr(...) or equivalent call. * @see #subMatrix(long[], long[]) * @see #subMatrix(long[], long[], ContinuationMode) * @see #subMatr(long[], long[]) * @see #subMatr(long[], long[], ContinuationMode) * @see #subMatrixParent() */ boolean isSubMatrix(); /** * If this matrix is a {@link #subMatrix(long[], long[]) submatrix} of some parent matrix, * created by one of calls parent.subMatrix(...) or parent.subMatr(...), * returns a reference to the parent matrix instance. * If this matrix is not a submatrix, throws {@link NotSubMatrixException}. * * @return a reference to the parent matrix, if this instance is a submatrix. * @throws NotSubMatrixException if this object is not created by subMatrix(...), * subMatr(...) or equivalent call. * @see #isSubMatrix() */ Matrix subMatrixParent() throws NotSubMatrixException; /** * If this matrix is a {@link #subMatrix(long[], long[]) submatrix} of some parent matrix, * created by one of calls parent.subMatrix(...) or parent.subMatr(...), * creates and returns a new Java array containing the starting position of this submatrix * in the parent one. The result will be equal to "from" argument of * {@link #subMatrix(long[], long[])} and {@link #subMatrix(long[], long[], ContinuationMode)} methods. * If this matrix is not a submatrix, throws {@link NotSubMatrixException}. * * @return low endpoints (inclusive) of all coordinates of this submatrix in its parent matrix. * @throws NotSubMatrixException if this object is not created by subMatrix(...), * subMatr(...) or equivalent call. * @see #isSubMatrix() */ long[] subMatrixFrom() throws NotSubMatrixException; /** * If this matrix is a {@link #subMatrix(long[], long[]) submatrix} of some parent matrix, * created by one of calls parent.subMatrix(...) or parent.subMatr(...), * creates and returns a new Java array containing the ending position (exclusive) of this submatrix * in the parent one. The result will be equal to "to" argument of * {@link #subMatrix(long[], long[])} and {@link #subMatrix(long[], long[], ContinuationMode)} methods. * If this matrix is not a submatrix, throws {@link NotSubMatrixException}. * * @return low endpoints (inclusive) of all coordinates of this submatrix in its parent matrix. * @throws NotSubMatrixException if this object is not created by subMatrix(...), * subMatr(...) or equivalent call. * @see #isSubMatrix() */ long[] subMatrixTo() throws NotSubMatrixException; /** * If this matrix is a {@link #subMatrix(long[], long[], Matrix.ContinuationMode) submatrix} * of some parent matrix, * created by one of calls parent.subMatrix(...) or parent.subMatr(...), * returns the {@link ContinuationMode continuation mode}, used by this submatrix. * If this matrix is not a submatrix, throws {@link NotSubMatrixException}. * *

If the submatrix was created by * {@link #subMatrix(long[], long[], net.algart.arrays.Matrix.ContinuationMode)} or equivalent method, * the continuationMode argument, passed to that method, is returned. * If the submatrix was created by * {@link #subMatrix(long[], long[])} or equivalent method, * {@link ContinuationMode#NONE} constant is returned. * * @return low endpoints (inclusive) of all coordinates of this submatrix in its parent matrix. * @throws NotSubMatrixException if this object is not created by subMatrix(...), * subMatr(...) or equivalent call. * @see #isSubMatrix() */ ContinuationMode subMatrixContinuationMode() throws NotSubMatrixException; /** * Returns a view ot this matrix, where the elements are reordered in some order "like" * in the specified matrix m. * In other words, the elements of the {@link #array() built-in array} of the returned matrix are * the same as the elements of the {@link #array() built-in array} of this one * (any changes of the elements in the returned matrix are reflected in this matrix, and vice versa), * but the order of the elements can differ. The precise algorithm of reordering is not specified * and depends on the matrix m: this method tries to help algorithms, processing the same * or similar areas in both matrices, to provide maximal performance. * *

This method returns non-trivial results only if the matrix m is already a view of some other * matrix with some form of reordering elements, for example, if m is a {@link #isTiled() tiled} * matrix. * In another case, this method just returns this instance. * *

In the current version of this package (if this instance was created by methods of this package), * this method is equivalent to the following: * *

     * m.{@link #isTiled()} ?
     *     thisInstance.{@link #tile() tile}(m.{@link #tileDimensions()}) :
     *     thisInstance;
     * 
* *

In future versions, it is possible that this method will recognize other forms of reordering matrix elements * and return non-trivial results for such m matrices. * *

Because the precise order of elements of the returning matrix is not specified, we recommend to use * this method generally for newly created matrices, for example: * *

     * memoryModel.{@link MemoryModel#newMatrix(Class, Matrix)
     * newMatrix}({@link UpdatablePArray}.class, m).{@link #structureLike(Matrix) structureLike}(m);
     * 
* or, more briefly, *
     * memoryModel.{@link MemoryModel#newStructuredMatrix(Class, Matrix)
     * newStructuredMatrix}({@link UpdatablePArray}.class, m);
     * 
* * @param m some matrix, probably a view of another matrix with reordered elements * (for example, {@link #tile(long...) tiled}). * @return a view of this matrix with elements reordered in similar order, or a reference to this instance * if m matrix is not reodered or this method does not "know" about the way of that reordering. * @throws NullPointerException if m argument is {@code null}. * @see #isStructuredLike(Matrix) */ Matrix structureLike(Matrix m); /** * Returns true if the elements of this matrix is ordered "alike" the elements * of the specified matrix m, in terms of {@link #structureLike(Matrix)} method. * "Ordered alike" does not mean that the dimensions of both matrices are equal, or that * the details of the structure are the same; it means only that both matrices use similar * reordering algorithms. * *

More precisely, {@link #structureLike(Matrix)} method returns this instance if and only if * this method returns true. * *

In the current version of this package (if this instance was created by means of methods of this package), * this method is equivalent to: thisInstance.{@link #isTiled()}==m.{@link #isTiled()}. * * @param m some matrix, probably a view of another matrix with reordered elements * (for example, {@link #tile(long...) tiled}). * @return whether this matrix is reordered alike m. * @throws NullPointerException if m argument is {@code null}. */ boolean isStructuredLike(Matrix m); /** * Returns a view ot this matrix, where the elements are reordered by tiles: a grid of rectangular * regions (tiles), the sizes of which are specified by tileDim argument. * It means that the elements of the built-in AlgART array of the returned matrix are the elements * of the built-in array of this one, but "shuffled" so that all elements of every tile in the returned matrix * are located in a continuous block of the built-in array of this matrix. * The returned matrix is named tiled matrix. The {@link #dimensions() dimensions} * of the returned matrix are the same as the dimensions of this one. * The {@link #elementType() element type} of the returned matrix is identical to the element type * of this matrix. * *

More precisely, let this matrix be M and the tiled matrix, returned by this method, be T. * Let i0, i1, ..., in−1 * (n={@link #dimCount()}) be coordinates of some element it the tiled matrix T, * that is located in T.{@link #array() array()} * at the index i=T.{@link #index(long...) * index}(i0,i1,...,in−1). * This element is located in the original array M.{@link #array() array()} at another index * j, which is calculated by the following algorithm. * *

    *
  1. Let dk = M.{@link #dim(int) dim}(k), * k=0,1,...,n−1: dimensions of this and returned matrix.
  2. * *
  3. Let i'k = ik%tileDim[k], * k=0,1,...,n−1: i'k are the coordinates of this element inside * the tile, containing it in T matrix.
  4. * *
  5. Let sk = iki'k, * k=0,1,...,n−1: sk are the coordinates of the starting element * of the tile, containing this element in T matrix.
  6. * *
  7. Let tk = min(tileDim[k], * dksk), * k=0,1,...,n−1: tk are the dimensions * of the tile, containing this element in T matrix. (Note that boundary tiles can be less * than tileDim, if dimensions of matrix are not divisible by corresponding dimensions of tiles.)
  8. * *
  9. Let previousVolume = * d0d1...dn−3dn−2sn−1 * + d0d1...dn−3cn−2tn−1 * + ... + s0t1...tn−2tn−1. * This complex formula returns the summary sizes of all tiles, that are fully located * in the source T.{@link #array() array()} before the given element. * In 2-dimensional case, the formula is more simple: * previousVolume = dxsy * + sxty. *
  10. * *
  11. Let indexInTile = * i'0 + i'1t0 + ... * + i'n−1tn−2...t0: * it is the index of the element with coordinates * i'0,i'1,...,i'n−1 * in the built-in array of a little matrix, dimensions of which are equal to the tile dimensions. *
  12. * *
  13. The required index of the given element in the original array * M.{@link #array() array()} * is j = previousVolume + indexInTile.
  14. *
* *

Tiled matrices are necessary to provide good performance of many algorithms, if this matrix is very large * (much greater than amount of RAM) and is located on disk or other external devices. * For example, extracting a rectangular area 1000x1000 from a byte matrix 1000000x1000000 (1 terabyte) * will probably work much faster if it is tiled, than if it is a usual matrix, where every line * occupies 1 MB of continuous disk space. * *

In the degenerated case of 1-dimensional matrix ({@link #dimCount()}=1) * the tiled matrix is absolutely useless, though still works correctly. * *

Recommended tile dimensions are from several hundreds to several thousands, but it depends * on the number of dimensions. If tile dimensions are degrees of two (2k), * the tiled matrix will probably work faster. * *

The built-in AlgART array of the returned matrix is backed by the built-in array of this matrix, * so — if this matrix is not {@link #isImmutable() immutable} * — any changes of the elements of the returned matrix are reflected in this matrix, and vice versa. * The returned matrix is {@link #isImmutable() immutable} if, and only if, * the built-in array of this matrix does not implement {@link UpdatableArray}. * The {@link Array#asTrustedImmutable()} method * in the built-in array of the returned matrix is equivalent to {@link Array#asImmutable()}, * and {@link Array#asCopyOnNextWrite()} method just returns the full copy of the array. * * @param tileDim dimensions of the tiles in the returned matrix (excepting the boundary tiles, * which can be less). * @return a tiled view of this matrix. * @throws NullPointerException if tileDim argument is {@code null}. * @throws IllegalArgumentException if tileDim.length is not equal to {@link #dimCount()}, * or if some tileDim[k]<=0, * or if the product of all tile dimensions tileDim[k] * is greater than Long.MAX_VALUE. * @see #tile() * @see #isTiled() * @see #tileDimensions() */ Matrix tile(long... tileDim); /** * Returns a tiled view ot this matrix with some default dimensions of the tiles. * Equivalent to {@link #tile(long...) tile}(tileDim), where all elements of tileDim * are equal to the default integer value, retrieved from the system property * "net.algart.arrays.matrixTile2D", * "net.algart.arrays.matrixTile3D" * "net.algart.arrays.matrixTile4D" * "net.algart.arrays.matrixTile5D" or * "net.algart.arrays.matrixTileND", * if the {@link #dimCount() number of dimensions} of this matrix is correspondingly 2, 3, 4, 5 or greater. * If there is no such property, or if it contains not a number, * or if some exception occurred while calling Long.getLong, * this method uses the following tile dimensions: * 4096x4096 in 2-dimensional case, * 256x256x256 in 3-dimensional case, * 64x64x64x64 in 4-dimensional case, * 32x32x32x32x32 in 5-dimensional case, * 16x16x... if the number of dimensions is greater than 5. * If the corresponding property exists and contains a valid integer number, * but it is too small, in particular, zero or negative, then it is replaced with some minimal positive value. * The values of all these system property is loaded and checked only once * while initializing {@link Arrays} class. * If the number of dimensions is 1 (degenerated case), this method always uses 65536 as the tile size. * (Warning! These defaults can be changed in future versions!) * * @return a tiled view of this matrix with default tile dimensions. * @throws IllegalArgumentException if the product of all tile dimensions tileDim[k] * is greater than Long.MAX_VALUE. * @see #tile(long...) * @see #isTiled() * @see #tileDimensions() */ Matrix tile(); /** * Returns true if and only if this matrix is a {@link #tile(long...) tiled view} * of some parent matrix, created by a call parent.tile(...) or an equivalent call. * The {@link #tileParent()} method throws {@link NotSubMatrixException} * if and only if this method returns false. * * @return whether this object is created by tile(...) or equivalent call. * @see #tile(long...) * @see #tile() */ boolean isTiled(); /** * If this matrix is a {@link #tile(long...) tiled view} of some parent matrix, * created by a call parent.tile(...), * returns a reference to the parent matrix instance. * If this matrix is not a tiled view, throws {@link NotTiledMatrixException}. * * @return a reference to the parent matrix, if this instance is a tiled view of other matrix. * @throws NotTiledMatrixException if this object is not created by tile(...) or equivalent call. * @see #isTiled() */ Matrix tileParent() throws NotTiledMatrixException; /** * If this matrix is a {@link #tile(long...) tiled view} of some parent matrix, * created by a call parent.tile(...), * creates and returns a new Java array containing the tile dimensions, used while creating this tiled view * (argument of {@link #tile(long...)} method). * If this matrix is not a tiled view, throws {@link NotTiledMatrixException}. * * @return sizes of each tile, if this instance is a tiled view of other matrix. * @throws NotTiledMatrixException if this object is not created by tile(...) or equivalent call. * @see #isTiled() */ long[] tileDimensions() throws NotTiledMatrixException; /** * Equivalent to {@link Matrices#asLayers(Matrix) Matrices.asLayers}(thisMatrix). * * @return a list of matrices: "layers" of this matrix one along the last dimension. * @throws IllegalStateException if this matrix is 1-dimensional. */ default List> asLayers() { return Matrices.asLayers(this); } /** * Equivalent to {@link #array()}.{@link Array#isImmutable() isImmutable()}. * *

There is a guarantee that this method works very quickly. * * @return true if this instance is immutable. */ boolean isImmutable(); /** * Equivalent to {@link #array()}.{@link Array#isCopyOnNextWrite() isCopyOnNextWrite()}. * *

There is a guarantee that this method works very quickly. * * @return true if this instance is copy-on-next-write. */ boolean isCopyOnNextWrite(); /** * Returns true if and only if the built-in AlgART array implements {@link DirectAccessible} * interface and (({@link DirectAccessible}){@link #array()}).{@link DirectAccessible#hasJavaArray() * hasJavaArray()} method returns true. * *

There is a guarantee that this method works very quickly. * * @return whether this matrix can be viewed as a Java array or a part of Java array. */ boolean isDirectAccessible(); /** * Returns an exact clone of this matrix, created in {@link SimpleMemoryModel}. * *

For primitive element types, equivalent to * {@link Matrices#clone(Matrix) Matrices.clone}(thisInstance), * but the generic type of the result is not {@link UpdatableArray updatable}. * For any types, equivalent to the following operators: *

     *     final Matrix<UpdatableArray> result = Arrays.SMM.{@link MemoryModel#newMatrix(Class, Matrix)
     *     newMatrix}(UpdatableArray.class, thisInstance);
     *     {@link Matrices#copy(ArrayContext, Matrix, Matrix)
     *     Matrices.copy}(null, result, thisInstance); // - maximally fast multithreading copying
     *     (return result)
     * 
* * @return exact clone of the passed matrix. */ Matrix clone(); /** * Equivalent to {@link #array()}.{@link Array#flushResources(ArrayContext) flushResources(context)}. * * @param context the context of execution; can be {@code null}, then it will be ignored. */ void flushResources(ArrayContext context); /** * Equivalent to {@link #array()}.{@link Array#freeResources(ArrayContext) freeResources(context)}. * * @param context the context of execution; can be {@code null}, then it will be ignored. */ void freeResources(ArrayContext context); /** * Equivalent to {@link #array()}.{@link Array#freeResources() freeResources()}. */ void freeResources(); /** * Returns a brief string description of this object. * *

The result of this method may depend on implementation and usually contains * a short description of the built-in AlgART array and all matrix dimensions. * * @return a brief string description of this object. */ String toString(); /** * Returns the hash code of this matrix. The result depends on all elements of the built-in array * (as {@link Array#hashCode()}) and all matrix dimensions. * * @return the hash code of this matrix. */ int hashCode(); /** * Indicates whether some other matrix is equal to this one. * Returns true if and only if:

    *
  1. the specified object is a matrix (i.e. implements {@link Matrix}),
  2. *
  3. both matrices have the same dimension count ({@link #dimCount()}) * and the same corresponding dimensions;
  4. *
  5. the built-in AlgART arrays ({@link #array()}) are equal (see {@link Array#equals(Object)}).
  6. *
* * @param obj the object to be compared for equality with this matrix. * @return true if the specified object is a matrix equal to this one. */ boolean equals(Object obj); /** * Equivalent to {@link MemoryModel#newMatrix(Class, Class, long...) * memoryModel.newMatrix(UpdatablePArray.class, elementType, dim)}. Throws * IllegalArgumentException in a case when the element type is not primitive. * * @param memoryModel the memory model, used for allocation new matrix. * @param elementType the type of matrix elements. * @param dim the dimensions of the matrix. * @return created matrix. * @throws NullPointerException if one of the arguments is {@code null}. * @throws IllegalArgumentException if elementType is not a primitive class, * or if the specified dimensions are incorrect: * dim.length==0, * dim[n] < 0 for some n, * or the product of all specified dimensions * is greater than Long.MAX_VALUE. * @throws UnsupportedElementTypeException if elementType is not supported by this memory model. * @throws TooLargeArrayException if the product of all specified dimensions is too large * for this memory model. */ static Matrix newMatrix(MemoryModel memoryModel, Class elementType, long... dim) { Objects.requireNonNull(memoryModel, "Null memory model"); Objects.requireNonNull(elementType, "Null element type"); if (!elementType.isPrimitive()) { throw new IllegalArgumentException("Not a primitive type: " + elementType); } return memoryModel.newMatrix(UpdatablePArray.class, elementType, dim); } /** * Equivalent to {@link #newMatrix(MemoryModel, Class, long...) * newMatrix}({@link Arrays#SMM Arrays.SMM}, elementType, dim). * * @param elementType the type of matrix elements. * @param dim the dimensions of the matrix. * @return created matrix. * @throws NullPointerException if one of the arguments is {@code null}. * @throws IllegalArgumentException if elementType is not a primitive class, * or if the specified dimensions are incorrect: * dim.length==0, * dim[n] < 0 for some n, * or the product of all specified dimensions * is greater than Long.MAX_VALUE. * @throws TooLargeArrayException if the product of all specified dimensions is too large * for {@link SimpleMemoryModel}. */ static Matrix newMatrix(Class elementType, long... dim) { return newMatrix(Arrays.SMM, elementType, dim); } /*Repeat() boolean ==> char,,byte,,short,,int,,long,,float,,double;; Bit ==> Char,,Byte,,Short,,Int,,Long,,Float,,Double;; bit ==> char,,byte,,short,,int,,long,,float,,double */ /** * Equivalent to {@link MemoryModel#newBitMatrix(long...) memoryModel.newBitMatrix(dim)}. * * @param dim the dimensions of the matrix. * @return created matrix. * @throws NullPointerException if dim is {@code null}. * @throws IllegalArgumentException if the specified dimensions are incorrect: dim.length == 0, * dim[n] <= 0 for some n, * or the product of all specified dimensions * is greater than Long.MAX_VALUE. * @throws UnsupportedElementTypeException if boolean element type * is not supported by this memory model. * @throws TooLargeArrayException if the product of all specified dimensions is too large * for this memory model. */ static Matrix newBitMatrix(MemoryModel memoryModel, long... dim) { Objects.requireNonNull(memoryModel, "Null memory model"); return memoryModel.newBitMatrix(dim); } /** * Equivalent to {@link Arrays#SMM Arrays.SMM}.{@link MemoryModel#newBitMatrix(long...) * newBitMatrix(dim)}. * * @param dim the dimensions of the matrix. * @return created matrix. * @throws NullPointerException if dim is {@code null}. * @throws IllegalArgumentException if the specified dimensions are incorrect: dim.length == 0, * dim[n] <= 0 for some n, * or the product of all specified dimensions * is greater than Long.MAX_VALUE. * @throws TooLargeArrayException if the product of all specified dimensions is too large * for {@link SimpleMemoryModel}. */ static Matrix newBitMatrix(long... dim) { return Arrays.SMM.newBitMatrix(dim); } /*Repeat.AutoGeneratedStart !! Auto-generated: NOT EDIT !! */ /** * Equivalent to {@link MemoryModel#newCharMatrix(long...) memoryModel.newCharMatrix(dim)}. * * @param dim the dimensions of the matrix. * @return created matrix. * @throws NullPointerException if dim is {@code null}. * @throws IllegalArgumentException if the specified dimensions are incorrect: dim.length == 0, * dim[n] <= 0 for some n, * or the product of all specified dimensions * is greater than Long.MAX_VALUE. * @throws UnsupportedElementTypeException if char element type * is not supported by this memory model. * @throws TooLargeArrayException if the product of all specified dimensions is too large * for this memory model. */ static Matrix newCharMatrix(MemoryModel memoryModel, long... dim) { Objects.requireNonNull(memoryModel, "Null memory model"); return memoryModel.newCharMatrix(dim); } /** * Equivalent to {@link Arrays#SMM Arrays.SMM}.{@link MemoryModel#newCharMatrix(long...) * newCharMatrix(dim)}. * * @param dim the dimensions of the matrix. * @return created matrix. * @throws NullPointerException if dim is {@code null}. * @throws IllegalArgumentException if the specified dimensions are incorrect: dim.length == 0, * dim[n] <= 0 for some n, * or the product of all specified dimensions * is greater than Long.MAX_VALUE. * @throws TooLargeArrayException if the product of all specified dimensions is too large * for {@link SimpleMemoryModel}. */ static Matrix newCharMatrix(long... dim) { return Arrays.SMM.newCharMatrix(dim); } /** * Equivalent to {@link MemoryModel#newByteMatrix(long...) memoryModel.newByteMatrix(dim)}. * * @param dim the dimensions of the matrix. * @return created matrix. * @throws NullPointerException if dim is {@code null}. * @throws IllegalArgumentException if the specified dimensions are incorrect: dim.length == 0, * dim[n] <= 0 for some n, * or the product of all specified dimensions * is greater than Long.MAX_VALUE. * @throws UnsupportedElementTypeException if byte element type * is not supported by this memory model. * @throws TooLargeArrayException if the product of all specified dimensions is too large * for this memory model. */ static Matrix newByteMatrix(MemoryModel memoryModel, long... dim) { Objects.requireNonNull(memoryModel, "Null memory model"); return memoryModel.newByteMatrix(dim); } /** * Equivalent to {@link Arrays#SMM Arrays.SMM}.{@link MemoryModel#newByteMatrix(long...) * newByteMatrix(dim)}. * * @param dim the dimensions of the matrix. * @return created matrix. * @throws NullPointerException if dim is {@code null}. * @throws IllegalArgumentException if the specified dimensions are incorrect: dim.length == 0, * dim[n] <= 0 for some n, * or the product of all specified dimensions * is greater than Long.MAX_VALUE. * @throws TooLargeArrayException if the product of all specified dimensions is too large * for {@link SimpleMemoryModel}. */ static Matrix newByteMatrix(long... dim) { return Arrays.SMM.newByteMatrix(dim); } /** * Equivalent to {@link MemoryModel#newShortMatrix(long...) memoryModel.newShortMatrix(dim)}. * * @param dim the dimensions of the matrix. * @return created matrix. * @throws NullPointerException if dim is {@code null}. * @throws IllegalArgumentException if the specified dimensions are incorrect: dim.length == 0, * dim[n] <= 0 for some n, * or the product of all specified dimensions * is greater than Long.MAX_VALUE. * @throws UnsupportedElementTypeException if short element type * is not supported by this memory model. * @throws TooLargeArrayException if the product of all specified dimensions is too large * for this memory model. */ static Matrix newShortMatrix(MemoryModel memoryModel, long... dim) { Objects.requireNonNull(memoryModel, "Null memory model"); return memoryModel.newShortMatrix(dim); } /** * Equivalent to {@link Arrays#SMM Arrays.SMM}.{@link MemoryModel#newShortMatrix(long...) * newShortMatrix(dim)}. * * @param dim the dimensions of the matrix. * @return created matrix. * @throws NullPointerException if dim is {@code null}. * @throws IllegalArgumentException if the specified dimensions are incorrect: dim.length == 0, * dim[n] <= 0 for some n, * or the product of all specified dimensions * is greater than Long.MAX_VALUE. * @throws TooLargeArrayException if the product of all specified dimensions is too large * for {@link SimpleMemoryModel}. */ static Matrix newShortMatrix(long... dim) { return Arrays.SMM.newShortMatrix(dim); } /** * Equivalent to {@link MemoryModel#newIntMatrix(long...) memoryModel.newIntMatrix(dim)}. * * @param dim the dimensions of the matrix. * @return created matrix. * @throws NullPointerException if dim is {@code null}. * @throws IllegalArgumentException if the specified dimensions are incorrect: dim.length == 0, * dim[n] <= 0 for some n, * or the product of all specified dimensions * is greater than Long.MAX_VALUE. * @throws UnsupportedElementTypeException if int element type * is not supported by this memory model. * @throws TooLargeArrayException if the product of all specified dimensions is too large * for this memory model. */ static Matrix newIntMatrix(MemoryModel memoryModel, long... dim) { Objects.requireNonNull(memoryModel, "Null memory model"); return memoryModel.newIntMatrix(dim); } /** * Equivalent to {@link Arrays#SMM Arrays.SMM}.{@link MemoryModel#newIntMatrix(long...) * newIntMatrix(dim)}. * * @param dim the dimensions of the matrix. * @return created matrix. * @throws NullPointerException if dim is {@code null}. * @throws IllegalArgumentException if the specified dimensions are incorrect: dim.length == 0, * dim[n] <= 0 for some n, * or the product of all specified dimensions * is greater than Long.MAX_VALUE. * @throws TooLargeArrayException if the product of all specified dimensions is too large * for {@link SimpleMemoryModel}. */ static Matrix newIntMatrix(long... dim) { return Arrays.SMM.newIntMatrix(dim); } /** * Equivalent to {@link MemoryModel#newLongMatrix(long...) memoryModel.newLongMatrix(dim)}. * * @param dim the dimensions of the matrix. * @return created matrix. * @throws NullPointerException if dim is {@code null}. * @throws IllegalArgumentException if the specified dimensions are incorrect: dim.length == 0, * dim[n] <= 0 for some n, * or the product of all specified dimensions * is greater than Long.MAX_VALUE. * @throws UnsupportedElementTypeException if long element type * is not supported by this memory model. * @throws TooLargeArrayException if the product of all specified dimensions is too large * for this memory model. */ static Matrix newLongMatrix(MemoryModel memoryModel, long... dim) { Objects.requireNonNull(memoryModel, "Null memory model"); return memoryModel.newLongMatrix(dim); } /** * Equivalent to {@link Arrays#SMM Arrays.SMM}.{@link MemoryModel#newLongMatrix(long...) * newLongMatrix(dim)}. * * @param dim the dimensions of the matrix. * @return created matrix. * @throws NullPointerException if dim is {@code null}. * @throws IllegalArgumentException if the specified dimensions are incorrect: dim.length == 0, * dim[n] <= 0 for some n, * or the product of all specified dimensions * is greater than Long.MAX_VALUE. * @throws TooLargeArrayException if the product of all specified dimensions is too large * for {@link SimpleMemoryModel}. */ static Matrix newLongMatrix(long... dim) { return Arrays.SMM.newLongMatrix(dim); } /** * Equivalent to {@link MemoryModel#newFloatMatrix(long...) memoryModel.newFloatMatrix(dim)}. * * @param dim the dimensions of the matrix. * @return created matrix. * @throws NullPointerException if dim is {@code null}. * @throws IllegalArgumentException if the specified dimensions are incorrect: dim.length == 0, * dim[n] <= 0 for some n, * or the product of all specified dimensions * is greater than Long.MAX_VALUE. * @throws UnsupportedElementTypeException if float element type * is not supported by this memory model. * @throws TooLargeArrayException if the product of all specified dimensions is too large * for this memory model. */ static Matrix newFloatMatrix(MemoryModel memoryModel, long... dim) { Objects.requireNonNull(memoryModel, "Null memory model"); return memoryModel.newFloatMatrix(dim); } /** * Equivalent to {@link Arrays#SMM Arrays.SMM}.{@link MemoryModel#newFloatMatrix(long...) * newFloatMatrix(dim)}. * * @param dim the dimensions of the matrix. * @return created matrix. * @throws NullPointerException if dim is {@code null}. * @throws IllegalArgumentException if the specified dimensions are incorrect: dim.length == 0, * dim[n] <= 0 for some n, * or the product of all specified dimensions * is greater than Long.MAX_VALUE. * @throws TooLargeArrayException if the product of all specified dimensions is too large * for {@link SimpleMemoryModel}. */ static Matrix newFloatMatrix(long... dim) { return Arrays.SMM.newFloatMatrix(dim); } /** * Equivalent to {@link MemoryModel#newDoubleMatrix(long...) memoryModel.newDoubleMatrix(dim)}. * * @param dim the dimensions of the matrix. * @return created matrix. * @throws NullPointerException if dim is {@code null}. * @throws IllegalArgumentException if the specified dimensions are incorrect: dim.length == 0, * dim[n] <= 0 for some n, * or the product of all specified dimensions * is greater than Long.MAX_VALUE. * @throws UnsupportedElementTypeException if double element type * is not supported by this memory model. * @throws TooLargeArrayException if the product of all specified dimensions is too large * for this memory model. */ static Matrix newDoubleMatrix(MemoryModel memoryModel, long... dim) { Objects.requireNonNull(memoryModel, "Null memory model"); return memoryModel.newDoubleMatrix(dim); } /** * Equivalent to {@link Arrays#SMM Arrays.SMM}.{@link MemoryModel#newDoubleMatrix(long...) * newDoubleMatrix(dim)}. * * @param dim the dimensions of the matrix. * @return created matrix. * @throws NullPointerException if dim is {@code null}. * @throws IllegalArgumentException if the specified dimensions are incorrect: dim.length == 0, * dim[n] <= 0 for some n, * or the product of all specified dimensions * is greater than Long.MAX_VALUE. * @throws TooLargeArrayException if the product of all specified dimensions is too large * for {@link SimpleMemoryModel}. */ static Matrix newDoubleMatrix(long... dim) { return Arrays.SMM.newDoubleMatrix(dim); } /*Repeat.AutoGeneratedEnd*/ /** * Equivalent to {@link SimpleMemoryModel#asMatrix(Object, long...)} * SimpleMemoryModel.asMatrix}(array, dim). * * @param array the source Java array. * @param dim the matrix dimensions. * @return a matrix backed by the specified Java array with the specified dimensions. * @throws NullPointerException if array or dim argument is {@code null}. * @throws IllegalArgumentException if array argument is not a Java array * and is not {@link UpdatablePArray}, * or if it is boolean[] array, or array of objects, * or if the number of dimensions is 0 (empty dim Java array), * or if some of the dimensions are negative. * @throws SizeMismatchException if the product of all dimensions is not equal to the array length. * @throws TooLargeArrayException if the product of all dimensions is greater than Long.MAX_VALUE. */ static Matrix as(Object array, long... dim) { return SimpleMemoryModel.asMatrix(array, dim); } }