View Javadoc
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 }