1 package org.djunits.vecmat.dnxm;
2
3 import org.djunits.quantity.def.AbsQuantity;
4 import org.djunits.quantity.def.Quantity;
5 import org.djunits.quantity.def.Reference;
6 import org.djunits.unit.Unit;
7 import org.djunits.vecmat.def.AbsMatrix;
8 import org.djunits.vecmat.dn.AbsVectorN;
9 import org.djunits.vecmat.storage.DenseDoubleDataSi;
10 import org.djutils.exceptions.Throw;
11
12 /**
13 * AbsMatrixNxM implements a matrix with NxM absolute quantities with a reference point. The matrix is immutable, except for the
14 * display unit, which can be changed.
15 * <p>
16 * Copyright (c) 2026-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 <A> the absolute quantity type
21 * @param <Q> the corresponding relative quantity type
22 */
23 public class AbsMatrixNxM<A extends AbsQuantity<A, Q, ?>, Q extends Quantity<Q>>
24 extends AbsMatrix<A, Q, AbsMatrixNxM<A, Q>, MatrixNxM<Q>, AbsMatrixNxM<A, Q>>
25 {
26 /** */
27 private static final long serialVersionUID = 600L;
28
29 /**
30 * Create a new AbsMatrixNxM with a display unit and a reference point.
31 * @param relativeMatrix the matrix values {a_ij} expressed in the displayUnit
32 * @param reference the reference point for the absolute values
33 */
34 public AbsMatrixNxM(final MatrixNxM<Q> relativeMatrix, final Reference<?, A, Q> reference)
35 {
36 super(relativeMatrix, reference);
37 }
38
39 @Override
40 public AbsMatrixNxM<A, Q> instantiate(final MatrixNxM<Q> relativeMatrix, final Reference<?, A, Q> reference)
41 {
42 return new AbsMatrixNxM<>(relativeMatrix, reference);
43 }
44
45 @Override
46 public AbsVectorN.Row<A, Q> getRowVector(final int row)
47 {
48 return new AbsVectorN.Row<>(getRelativeVecMat().getRowVector(row), getReference());
49 }
50
51 @Override
52 public AbsVectorN.Row<A, Q> mgetRowVector(final int mRow)
53 {
54 return new AbsVectorN.Row<>(getRelativeVecMat().mgetRowVector(mRow), getReference());
55 }
56
57 @Override
58 public AbsVectorN.Col<A, Q> getColumnVector(final int col)
59 {
60 return new AbsVectorN.Col<>(getRelativeVecMat().getColumnVector(col), getReference());
61 }
62
63 @Override
64 public AbsVectorN.Col<A, Q> mgetColumnVector(final int mCol)
65 {
66 return new AbsVectorN.Col<>(getRelativeVecMat().mgetColumnVector(mCol), getReference());
67 }
68
69 @Override
70 public AbsMatrixNxM<A, Q> transpose()
71 {
72 return instantiate(getRelativeVecMat().transpose(), getReference()).setDisplayUnit(getDisplayUnit());
73 }
74
75 // ------------------------------------------ OF METHODS ------------------------------------------
76
77 /**
78 * Create a new AbsMatrixNxM with a unit, based on a row-major array with values in the given unit.
79 * @param dataInUnit the matrix values {a11, a12, ..., A1M, ..., aN1, aN2, ..., aNM} expressed in the unit
80 * @param rows the number of rows
81 * @param cols the number of columns
82 * @param unit the unit of the data, also used as the display unit
83 * @param reference the reference point for the absolute quantities
84 * @return a new AbsMatrixNxM with a unit
85 * @param <A> the absolute quantity type
86 * @param <Q> the quantity type
87 * @param <R> the reference type
88 * @throws IllegalArgumentException when the size of the data object is not equal to rows*cols, or when the number of rows
89 * or columns is not positive
90 */
91 public static <A extends AbsQuantity<A, Q, R>, Q extends Quantity<Q>, R extends Reference<R, A, Q>> AbsMatrixNxM<A, Q> of(
92 final double[] dataInUnit, final int rows, final int cols, final Unit<?, Q> unit, final R reference)
93 {
94 return new AbsMatrixNxM<A, Q>(MatrixNxM.of(dataInUnit, rows, cols, unit), reference);
95 }
96
97 /**
98 * Create a AbsMatrixNxM without needing generics, based on a row-major array with SI-values.
99 * @param dataSi the matrix values {a11, a12, ..., A1M, ..., aN1, aN2, ..., aNM} as an array using SI units
100 * @param rows the number of rows
101 * @param cols the number of columns
102 * @param displayUnit the display unit to use
103 * @param reference the reference point for the absolute quantities
104 * @return a new AbsMatrixNxM with a unit
105 * @param <A> the absolute quantity type
106 * @param <Q> the quantity type
107 * @param <R> the reference type
108 * @throws IllegalArgumentException when the size of the data object is not equal to rows*cols, or when the number of rows
109 * or columns is not positive
110 */
111 public static <A extends AbsQuantity<A, Q, R>, Q extends Quantity<Q>, R extends Reference<R, A, Q>> AbsMatrixNxM<A, Q> ofSi(
112 final double[] dataSi, final int rows, final int cols, final Unit<?, Q> displayUnit, final R reference)
113 {
114 return new AbsMatrixNxM<A, Q>(MatrixNxM.ofSi(dataSi, rows, cols, displayUnit), reference);
115 }
116
117 /**
118 * Create a AbsMatrixNxM without needing generics, based on a row-major array of quantities. The unit is taken from the
119 * first quantity in the array.
120 * @param data the matrix values {a11, a12, ..., A1M, ..., aN1, aN2, ..., aNM} expressed as an array of quantities
121 * @param rows the number of rows
122 * @param cols the number of columns
123 * @param reference the reference point for the absolute quantities
124 * @return a new AbsMatrixNxM with a unit
125 * @param <A> the absolute quantity type
126 * @param <Q> the quantity type
127 * @param <R> the reference type
128 * @throws IllegalArgumentException when the size of the data object is not equal to rows*cols, or when the number of rows
129 * or columns is not positive
130 */
131 public static <A extends AbsQuantity<A, Q, R>, Q extends Quantity<Q>, R extends Reference<R, A, Q>> AbsMatrixNxM<A, Q> of(
132 final Q[] data, final int rows, final int cols, final R reference)
133 {
134 return new AbsMatrixNxM<A, Q>(MatrixNxM.of(data, rows, cols), reference);
135 }
136
137 /**
138 * Create a AbsMatrixNxM without needing generics, based on a row-major array of absolute quantities. The unit is
139 * taken from the first quantity in the grid. The reference points have to be all the same.
140 * @param absData the table values {a11, a12, ..., A1M, ..., aN1, aN2, ..., aNM} expressed as an array of
141 * absolute quantities
142 * @param rows the number of rows
143 * @param cols the number of columns
144 * @return a new AbsMatrixNxM with a display unit and reference point
145 * @param <A> the absolute quantity type
146 * @param <Q> the quantity type
147 * @param <R> the reference type
148 * @throws IllegalArgumentException when the size of the data object is not equal to rows*cols
149 */
150 public static <A extends AbsQuantity<A, Q, R>, Q extends Quantity<Q>,
151 R extends Reference<R, A, Q>> AbsMatrixNxM<A, Q> of(final A[] absData, final int rows, final int cols)
152 {
153 Throw.whenNull(absData, "absData");
154 var ddd = DenseDoubleDataSi.of(absData, rows, cols); // guarantees that absGrid[0][0] exists
155 return new AbsMatrixNxM<>(new MatrixNxM<Q>(ddd, absData[0].getDisplayUnit()), absData[0].getReference());
156 }
157
158 /**
159 * Create a new AbsMatrixNxM with a unit, based on a 2-dimensional grid with SI-values.
160 * @param gridSi the matrix values {{a11, a12, ..., A1M}, ..., {aN1, aN2, ..., aNM}} expressed in the SI or base unit
161 * @param displayUnit the unit of the data, which will also be used as the display unit
162 * @param reference the reference point for the absolute quantities
163 * @return a new AbsMatrixNxM with a unit
164 * @param <A> the absolute quantity type
165 * @param <Q> the quantity type
166 * @param <R> the reference type
167 * @throws IllegalArgumentException when the size of the data object is not equal to rows*cols
168 */
169 @SuppressWarnings("checkstyle:needbraces")
170 public static <A extends AbsQuantity<A, Q, R>, Q extends Quantity<Q>, R extends Reference<R, A, Q>> AbsMatrixNxM<A, Q> ofSi(
171 final double[][] gridSi, final Unit<?, Q> displayUnit, final R reference)
172 {
173 Throw.whenNull(displayUnit, "displayUnit");
174 return new AbsMatrixNxM<>(MatrixNxM.ofSi(gridSi, displayUnit), reference);
175 }
176
177 /**
178 * Create a new AbsMatrixNxM with a unit, based on a 2-dimensional grid with values in the given unit.
179 * @param gridInUnit the matrix values {{a11, a12, ..., A1M}, ..., {aN1, aN2, ..., aNM}} expressed in the unit
180 * @param unit the unit of the values, also used as the display unit
181 * @param reference the reference point for the absolute quantities
182 * @return a new AbsMatrixNxM with a unit
183 * @param <A> the absolute quantity type
184 * @param <Q> the quantity type
185 * @param <R> the reference type
186 * @throws IllegalArgumentException when the size of the data object is not equal to rows*cols
187 */
188 @SuppressWarnings("checkstyle:needbraces")
189 public static <A extends AbsQuantity<A, Q, R>, Q extends Quantity<Q>, R extends Reference<R, A, Q>> AbsMatrixNxM<A, Q> of(
190 final double[][] gridInUnit, final Unit<?, Q> unit, final R reference)
191 {
192 return new AbsMatrixNxM<>(MatrixNxM.of(gridInUnit, unit), reference);
193 }
194
195 /**
196 * Create a AbsMatrixNxM without needing generics, based on a 2-dimensional grid of quantities. The unit is taken from the
197 * first quantity in the grid.
198 * @param grid the matrix values {{a11, a12, ..., A1M}, ..., {aN1, aN2, ..., aNM}} expressed as a 2-dimensional array of
199 * quantities
200 * @param reference the reference point for the absolute quantities
201 * @return a new AbsMatrixNxM with a unit
202 * @param <A> the absolute quantity type
203 * @param <Q> the quantity type
204 * @param <R> the reference type
205 * @throws IllegalArgumentException when the size of the data object is not equal to rows*cols
206 */
207 public static <A extends AbsQuantity<A, Q, R>, Q extends Quantity<Q>,
208 R extends Reference<R, A, Q>> AbsMatrixNxM<A, Q> of(final Q[][] grid, final R reference)
209 {
210 return new AbsMatrixNxM<>(MatrixNxM.of(grid), reference);
211 }
212
213 /**
214 * Create a AbsMatrixNxM without needing generics, based on a 2-dimensional grid of absolute quantities. The unit is
215 * taken from the first quantity in the grid. The reference points have to be all the same.
216 * @param absGrid the table values {{a11, a12, ..., A1M}, ..., {aN1, aN2, ..., aNM}} expressed as a 2-dimensional array of
217 * absolute quantities
218 * @return a new AbsMatrixNxM with a display unit and reference point
219 * @param <A> the absolute quantity type
220 * @param <Q> the quantity type
221 * @param <R> the reference type
222 * @throws IllegalArgumentException when the size of the data object is not equal to rows*cols
223 */
224 public static <A extends AbsQuantity<A, Q, R>, Q extends Quantity<Q>,
225 R extends Reference<R, A, Q>> AbsMatrixNxM<A, Q> of(final A[][] absGrid)
226 {
227 Throw.whenNull(absGrid, "absGrid");
228 var ddd = DenseDoubleDataSi.of(absGrid); // guarantees that absGrid[0][0] exists
229 return new AbsMatrixNxM<>(new MatrixNxM<Q>(ddd, absGrid[0][0].getDisplayUnit()), absGrid[0][0].getReference());
230 }
231
232 /**
233 * Create a AbsMatrixNxM without needing generics, based on a relative matrix. The unit is taken from the first quantity in
234 * the grid.
235 * @param relativeMatrix the relative matrix with values relative to the reference point
236 * @param reference the reference point for the absolute quantities
237 * @return a new AbsMatrixNxM with a unit
238 * @param <A> the absolute quantity type
239 * @param <Q> the quantity type
240 * @param <R> the reference type
241 * @throws IllegalArgumentException when the size of the data object is not equal to rows*cols
242 */
243 public static <A extends AbsQuantity<A, Q, R>, Q extends Quantity<Q>,
244 R extends Reference<R, A, Q>> AbsMatrixNxM<A, Q> of(final MatrixNxM<Q> relativeMatrix, final R reference)
245 {
246 return new AbsMatrixNxM<>(relativeMatrix, reference);
247 }
248
249 }