Class NonSquareMatrix

All Implemented Interfaces:
Serializable, Cloneable, ExtendedPrecisionMatrix, LenientComparable, org.opengis.referencing.operation.Matrix

final class NonSquareMatrix extends GeneralMatrix
A matrix which is not square.
Since:
0.4
Version:
0.4
See Also:
  • Field Details

    • serialVersionUID

      private static final long serialVersionUID
      Serial number for inter-operability with different versions.
      See Also:
  • Constructor Details

    • NonSquareMatrix

      NonSquareMatrix(int numRow, int numCol, boolean setToIdentity, int precision)
      Creates a matrix of size numRow × numCol. If setToIdentity is true, then the elements on the diagonal (j == i) are set to 1.
      Parameters:
      numRow - number of rows.
      numCol - number of columns.
      setToIdentity - true for initializing the matrix to the identity matrix, or false for leaving it initialized to zero.
      precision - 1 for normal precision, or 2 for extended precision.
    • NonSquareMatrix

      NonSquareMatrix(int numRow, int numCol, double[] elements)
      Constructs a numRow × numCol matrix initialized to the values in the elements array. The array values are copied in one row at a time in row major fashion. The array shall be exactly numRow*numCol in length.
      Parameters:
      numRow - number of rows.
      numCol - number of columns.
      elements - initial values.
    • NonSquareMatrix

      NonSquareMatrix(org.opengis.referencing.operation.Matrix matrix)
      Constructs a new matrix and copies the initial values from the given matrix.
      Parameters:
      matrix - the matrix to copy.
    • NonSquareMatrix

      private NonSquareMatrix(GeneralMatrix matrix)
      Creates a clone of the given matrix, for clone() usage only.
  • Method Details

    • transpose

      public void transpose()
      Sets the value of this matrix to its transpose.
      Overrides:
      transpose in class GeneralMatrix
    • solve

      public MatrixSIS solve(org.opengis.referencing.operation.Matrix matrix) throws MismatchedMatrixSizeException, NoninvertibleMatrixException
      Returns the value of U which solves this × U = matrix. This is equivalent to first computing the inverse of this, then multiplying the result by the given matrix.

      This method delegates the work to inverse().multiply(matrix) in order to leverage the special handling done by inverse() for non-square matrices.

      Overrides:
      solve in class MatrixSIS
      Parameters:
      matrix - the matrix to solve.
      Returns:
      the U matrix that satisfies this × U = matrix.
      Throws:
      MismatchedMatrixSizeException - if the number of rows in the given matrix is not equals to the number of columns in this matrix.
      NoninvertibleMatrixException - if this matrix is not invertible.
    • inverse

      public MatrixSIS inverse() throws NoninvertibleMatrixException
      Returns the inverse of this matrix.

      This method performs a special check for non-square matrices in an attempt to invert them anyway. If this matrix has more columns than rows, then this method can invert that matrix if and only if some columns contain only 0 elements. In such case, the dimensions corresponding to those columns are considered independent of all other dimensions. This happen typically with the dimension of z and t coordinate values.

      Example: in a conversion from (x₁,y₁,z,t) to (x₂,y₂), if the (x,y) dimensions are independent of z and t dimensions, then we do not need those (z,t) dimensions for calculating the inverse of (x₁,y₁) to (x₂,y₂). We can omit the (z,t) dimensions in order to have a square matrix, perform the inversion, then insert NaN in place of the omitted dimensions. In the matrix below, we can see that (x,y) are independent of (z,t) because the 3th and 4th columns contains only 0 elements:

      There is an issue about whether the full row shall contain NaN, or only the last element (the translation term) as in the above example. The current implementation inserts a NaN value in the translation term and sets all other values to 0 on the assumption that if (x₂,y₂) do not depend on (z,t), then conversely (z,t) do not depend on (x₂,y₂) neither. Setting the scale factor to zero expresses that fact, while setting them to NaN would mean "don't know".

      Note that the above strategy assumes that the matrix is used for an affine transform, which is not always true (it could be the matrix of a map projection derivative for instance). If the matrix is not for an affine transform, then the last column has no special meaning and the above strategy is somewhat asymmetric. However, it will still produce NaN for the full row in matrix multiplications.

      Conversely, if the matrix has more rows than columns (in a system of linear equations, the system would be overdetermined), then we omit the rows containing only zero or NaN values. After the matrix inversion, we insert columns having only zero values for the dimensions associated to those rows. Semantically, the inverse matrix is a (x₁,y₁,z,t) → (x₂,y₂) transform that just discards the coordinate values at the dimensions corresponding to those rows.

      Overrides:
      inverse in class MatrixSIS
      Returns:
      the inverse of this matrix.
      Throws:
      NoninvertibleMatrixException - if this matrix is not invertible.
      See Also:
    • inverseDimensionReduction

      private MatrixSIS inverseDimensionReduction() throws NoninvertibleMatrixException
      Inverses a matrix for a transform where target points have fewer coordinates than source points. If a column contains only zero values, then this means that the coordinate at the corresponding column is simply deleted. We can omit that column. We check the last columns before the first columns on the assumption that last dimensions are more likely to be independent dimensions like time.
      Throws:
      NoninvertibleMatrixException
    • inverseDimensionIncrease

      private MatrixSIS inverseDimensionIncrease() throws NoninvertibleMatrixException
      Inverses a matrix for a transform where target points has more coordinates than source points. In other words, the target matrices will be a transform that discard some coordinate values. We will discard the ones for which the row contains only 0 or NaN elements.

      In the special case where the last row is of the form [0 0 … 0 1] as in affine transforms, this method also omits rows that contain only a translation term. We allow that because if we do not omit those rows, then the matrix will be non-invertible anyway. This is true only when the last row contains only zero except in the last column ([0 0 … 0 n] where n can be any value). We restrict n to 1 for now because a different value may indicate a matrix created for another purpose than coordinate conversions.

      Throws:
      NoninvertibleMatrixException
    • copyColumn

      private static void copyColumn(GeneralMatrix source, int srcIndex, GeneralMatrix target, int dstIndex)
      Copies a column between two matrices, including the double-double arithmetic error terms if any. The target matrix must have the same number of rows than the source matrix, and must have enough room for error terms (this is not verified).
      Parameters:
      source - the matrix from which to copy a column.
      srcIndex - index of the column to copy from the source matrix.
      target - the matrix where to copy the column.
      dstIndex - index of the column where to copy in the target matrix.
    • copyRow

      private static void copyRow(GeneralMatrix source, int srcIndex, GeneralMatrix target, int dstIndex)
      Copies a row between two matrices, including the double-double arithmetic error terms if any. The target matrix must have the same number of columns than the source matrix, and must have enough room for error terms (this is not verified).
      Parameters:
      source - the matrix from which to copy a row.
      srcIndex - index of the row to copy from the source matrix.
      target - the matrix where to copy the row.
      dstIndex - index of the row where to copy in the target matrix.
    • nonInvertible

      private NoninvertibleMatrixException nonInvertible()
      Returns the exception for a non-invertible transform.
    • clone

      public MatrixSIS clone()
      Returns a clone of this matrix.
      Specified by:
      clone in interface org.opengis.referencing.operation.Matrix
      Overrides:
      clone in class GeneralMatrix
      Returns:
      a new matrix of the same class and with the same values than this matrix.
      See Also: