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