1 package org.djunits.vecmat.def;
2
3 import org.djunits.quantity.SIQuantity;
4 import org.djunits.quantity.def.Quantity;
5 import org.djunits.unit.UnitInterface;
6 import org.djunits.unit.si.SIUnit;
7 import org.djunits.util.MatrixMath;
8 import org.djunits.vecmat.dnxm.MatrixNxM;
9 import org.djunits.vecmat.storage.DenseDoubleDataSi;
10 import org.djunits.vecmat.storage.DenseFloatDataSi;
11 import org.djutils.exceptions.Throw;
12
13 /**
14 * Matrix contains a number of standard operations on matrices of relative quantities.
15 * <p>
16 * Copyright (c) 2025-2026 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
17 * for project information <a href="https://djunits.org" target="_blank">https://djunits.org</a>. The DJUNITS project is
18 * distributed under a <a href="https://djunits.org/docs/license.html" target="_blank">three-clause BSD-style license</a>.
19 * @author Alexander Verbraeck
20 * @param <Q> the quantity type
21 * @param <U> the unit type
22 * @param <M> the 'SELF' matrix type
23 * @param <SI> the matrix type with generics <SIQuantity, SIUnit<
24 * @param <H> the generic matrix type with generics <?, ?< for Hadamard operations
25 */
26 public abstract class Matrix<Q extends Quantity<Q, U>, U extends UnitInterface<U, Q>, M extends Matrix<Q, U, M, SI, H>,
27 SI extends Matrix<SIQuantity, SIUnit, SI, ?, ?>, H extends Matrix<?, ?, ?, ?, ?>> extends VectorMatrix<Q, U, M, SI, H>
28 {
29 /** */
30 private static final long serialVersionUID = 600L;
31
32 /**
33 * Create a new matrix with a unit.
34 * @param displayUnit the display unit to use
35 */
36 public Matrix(final U displayUnit)
37 {
38 super(displayUnit);
39 }
40
41 /**
42 * Check if the multiplication with the other matrix is valid. A valid matrix multiplication is (M x N) x (N x P).
43 * @param matrix the other matrix
44 * @throws IllegalArgumentException when this.cols() != other.rows()
45 */
46 protected void checkMultiply(final Matrix<?, ?, ?, ?, ?> matrix)
47 {
48 Throw.whenNull(matrix, "matrix");
49 Throw.when(cols() != matrix.rows(), IllegalArgumentException.class,
50 "Matrix multiplication (M x N) x (N x P): this.cols (%d) != matrix.rows (%d)", cols(), matrix.rows());
51 }
52
53 /**
54 * Check if the multiplication with the other matrix is valid. A valid matrix multiplication is (M x N) x (N x P).
55 * @param vector the other matrix
56 * @throws IllegalArgumentException when this.cols() != other.rows()
57 */
58 protected void checkMultiply(final Vector<?, ?, ?, ?, ?> vector)
59 {
60 Throw.whenNull(vector, "matrix");
61 Throw.when(cols() != vector.rows(), IllegalArgumentException.class,
62 "Matrix multiplication (M x N) x (N x P): this.cols (%d) != vector.rows (%d)", cols(), vector.rows());
63 }
64
65 /**
66 * Multiply this vector or matrix with a MatrixNxM, resulting in a MatrixNxM. The multiplication is a (NxM) x (MxP) matrix
67 * multiplication resulting in an (NxP) matrix.
68 * @param matrix the matrix to multiply with
69 * @return a MatrixNxM of an SIQuantity as the result of the matrix multiplication
70 * @throws IllegalArgumentException when the number of columns of this matrix does not equal the number of rows of the
71 * matrix or vector to multiply with
72 */
73 public MatrixNxM<SIQuantity, SIUnit> multiply(final MatrixNxM<?, ?> matrix)
74 {
75 checkMultiply(matrix);
76 double[] result = MatrixMath.multiply(si(), matrix.si(), rows(), cols(), matrix.cols());
77 SIUnit siUnit = getDisplayUnit().siUnit().plus(matrix.getDisplayUnit().siUnit());
78 if (matrix.getDataGrid().isDouble())
79 {
80 return new MatrixNxM<SIQuantity, SIUnit>(new DenseDoubleDataSi(result, rows(), matrix.cols()), siUnit);
81 }
82 return new MatrixNxM<SIQuantity, SIUnit>(new DenseFloatDataSi(result, rows(), matrix.cols()), siUnit);
83 }
84
85 }