View Javadoc
1   package org.djunits.vecmat.def;
2   
3   import java.lang.reflect.Array;
4   
5   import org.djunits.quantity.def.AbsQuantity;
6   import org.djunits.quantity.def.Quantity;
7   import org.djunits.quantity.def.Reference;
8   
9   /**
10   * AbsTable contains a number of standard operations on 2-dimensional tables that contain absolute quantities.
11   * <p>
12   * Copyright (c) 2025-2026 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
13   * for project information <a href="https://djunits.org" target="_blank">https://djunits.org</a>. The DJUNITS project is
14   * distributed under a <a href="https://djunits.org/docs/license.html" target="_blank">three-clause BSD-style license</a>.
15   * @author Alexander Verbraeck
16   * @param <A> the absolute quantity type
17   * @param <Q> the quantity type
18   * @param <MA> the absolute table type
19   * @param <MQ> the relative table type
20   * @param <MAT> the type of the transposed version of the absolute table
21   */
22  public abstract class AbsTable<A extends AbsQuantity<A, Q, ?>, Q extends Quantity<Q>, MA extends AbsTable<A, Q, MA, MQ, MAT>,
23          MQ extends Table<Q, MQ, ?, ?, ?>, MAT extends AbsTable<A, Q, MAT, ?, MA>> extends AbsVectorMatrix<A, Q, MA, MQ, MAT>
24  {
25      /** */
26      private static final long serialVersionUID = 600L;
27  
28      /**
29       * Create a new matrix of absolute values with a reference point.
30       * @param matrix the underlying relative matrix with SI values relative to the reference point
31       * @param reference the reference point for the absolute values
32       */
33      public AbsTable(final MQ matrix, final Reference<?, A, Q> reference)
34      {
35          super(matrix, reference);
36      }
37  
38      /**
39       * Return the si-value at position (row, col), where both row and col are 0-based values.
40       * @param row the row (0-based)
41       * @param col the column (0-based)
42       * @return the si-value at position (row, col)
43       * @throws IndexOutOfBoundsException when row or col &lt; 0 or larger than number of rows/columns - 1.
44       */
45      public double si(final int row, final int col) throws IndexOutOfBoundsException
46      {
47          return getRelativeVecMat().si(row, col);
48      }
49  
50      /**
51       * Return the si-value at position (row, col), where both row and col are 1-based values.
52       * @param mRow the row (1-based)
53       * @param mCol the column (1-based)
54       * @return the si-value at position (row, col)
55       * @throws IndexOutOfBoundsException when row or col &lt; 1 or larger than number of rows/columns.
56       */
57      public double msi(final int mRow, final int mCol) throws IndexOutOfBoundsException
58      {
59          return si(mRow - 1, mCol - 1);
60      }
61  
62      /**
63       * Return the quantity at position (row, col), where both row and col are 0-based values.
64       * @param row the row (0-based)
65       * @param col the column (0-based)
66       * @return the quantity at position (row, col)
67       * @throws IndexOutOfBoundsException when row or col &lt; 0 or larger than number of rows/columns - 1.
68       */
69      public A get(final int row, final int col) throws IndexOutOfBoundsException
70      {
71          return getReference().instantiate(getDisplayUnit().ofSi(si(row, col))).setDisplayUnit(getDisplayUnit());
72      }
73  
74      /**
75       * Return the quantity at position (row, col), where both row and col are 1-based values.
76       * @param mRow the row (1-based)
77       * @param mCol the column (1-based)
78       * @return the quantity at position (row, col)
79       * @throws IndexOutOfBoundsException when row or col &lt; 1 or larger than number of rows/columns.
80       */
81      public A mget(final int mRow, final int mCol) throws IndexOutOfBoundsException
82      {
83          return getReference().instantiate(getDisplayUnit().ofSi(msi(mRow, mCol))).setDisplayUnit(getDisplayUnit());
84      }
85  
86      /**
87       * Return the vector or matrix as a 2D array of scalars.
88       * @return a new A[rows()][cols()] array; entry [i][j] contains get(i, j).
89       */
90      @SuppressWarnings("unchecked") // cast from Array.newInstance(...) to Q[][]
91      public A[][] getScalarGrid()
92      {
93          // Determine the runtime type of Q using the first cell; constructors guarantee rows, cols >= 0.
94          final A first = get(0, 0);
95          final Class<?> qClass = first.getClass();
96  
97          // Allocate a Q[rows()][cols()] array and fill it.
98          final A[][] out = (A[][]) Array.newInstance(qClass, rows(), cols());
99          for (int i = 0; i < rows(); i++)
100         {
101             for (int j = 0; j < cols(); j++)
102             {
103                 out[i][j] = get(i, j);
104             }
105         }
106         return out;
107     }
108 
109     /**
110      * Return the vector or matrix as a 2D array of double SI values.
111      * @return a new double[rows()][cols()] array; entry [i][j] contains si(i, j).
112      */
113     public double[][] getSiGrid()
114     {
115         // Allocate a double[rows()][cols()] array and fill it.
116         final double[][] out = (double[][]) Array.newInstance(double.class, rows(), cols());
117         for (int r = 0; r < rows(); r++)
118         {
119             for (int c = 0; c < cols(); c++)
120             {
121                 out[r][c] = si(r, c);
122             }
123         }
124         return out;
125     }
126 
127     /**
128      * Return the vector or matrix as a row-major array of scalars.
129      * @return a new A[rows() * cols()] array.
130      */
131     @SuppressWarnings("unchecked") // cast from Array.newInstance(...) to A[][]
132     public A[] getScalarArray()
133     {
134         // Determine the runtime type of Q using the first cell; constructors guarantee rows, cols >= 0.
135         final A first = get(0, 0);
136         final Class<?> qClass = first.getClass();
137         int cols = cols();
138 
139         // Allocate a Q[rows() * cols()] array and fill it.
140         final A[] out = (A[]) Array.newInstance(qClass, rows() * cols());
141         for (int r = 0; r < rows(); r++)
142         {
143             for (int c = 0; c < cols; c++)
144             {
145                 out[r * cols + c] = get(r, c);
146             }
147         }
148         return out;
149     }
150 
151     /**
152      * Return the vector or matrix as a row-major array of double SI values.
153      * @return a new double[rows() * cols()] array.
154      */
155     public double[] getSiArray()
156     {
157         // Allocate a double[rows()][cols()] array and fill it.
158         final double[] out = new double[rows() * cols()];
159         int cols = cols();
160         for (int r = 0; r < rows(); r++)
161         {
162             for (int c = 0; c < cols; c++)
163             {
164                 out[r * cols + c] = si(r, c);
165             }
166         }
167         return out;
168     }
169 
170     /**
171      * Return a quantity row (0-based) from the vector or matrix. Note that the specific vector to return can be tightened by
172      * the implementing class.
173      * @param row the row number to retrieve (0-based)
174      * @return a row vector with the data at the given row
175      */
176     public abstract AbsVector<A, Q, ?, ?, ?> getRowVector(int row);
177 
178     /**
179      * Return a quantity row (1-based) from the vector or matrix. Note that the specific vector to return can be tightened by
180      * the implementing class.
181      * @param mRow the row number to retrieve (1-based)
182      * @return a row vector with the data at the given row
183      */
184     public abstract AbsVector<A, Q, ?, ?, ?> mgetRowVector(int mRow);
185 
186     /**
187      * Return a quantity column (0-based) from the vector or matrix. Note that the specific vector to return can be tightened by
188      * the implementing class.
189      * @param col the column number to retrieve (0-based)
190      * @return a column vector with the data at the given column
191      */
192     public abstract AbsVector<A, Q, ?, ?, ?> getColumnVector(int col);
193 
194     /**
195      * Return a quantity column (1-based) from the vector or matrix. Note that the specific vector to return can be tightened by
196      * the implementing class.
197      * @param mCol the column number to retrieve (1-based)
198      * @return a column vector with the data at the given column
199      */
200     public abstract AbsVector<A, Q, ?, ?, ?> mgetColumnVector(int mCol);
201 
202     /**
203      * Return an array with SI-values for the given row (0-based) from the vector or matrix.
204      * @param row the row number to retrieve (0-based)
205      * @return an array with SI-values with the data at the given row
206      */
207     public double[] getRowSi(final int row)
208     {
209         return getRelativeVecMat().getRowSi(row);
210     }
211 
212     /**
213      * Return an array with SI-values for the given row (1-based) from the vector or matrix.
214      * @param mRow the row number to retrieve (1-based)
215      * @return an array with SI-values with the data at the given row
216      */
217     public double[] mgetRowSi(final int mRow)
218     {
219         return getRelativeVecMat().mgetRowSi(mRow);
220     }
221 
222     /**
223      * Return an array with SI-values for the given column (0-based) from the vector or matrix.
224      * @param col the column number to retrieve (0-based)
225      * @return an array with SI-values with the data at the given column
226      */
227     public double[] getColumnSi(final int col)
228     {
229         return getRelativeVecMat().getColumnSi(col);
230     }
231 
232     /**
233      * Return an array with SI-values for the given column (1-based) from the vector or matrix.
234      * @param mCol the column number to retrieve (1-based)
235      * @return an array with SI-values with the data at the given column
236      */
237     public double[] mgetColumnSi(final int mCol)
238     {
239         return getRelativeVecMat().mgetColumnSi(mCol);
240     }
241 
242     /**
243      * Retrieve a row (0-based) from the matrix as an array of scalars.
244      * @param row row of the values to retrieve (0-based)
245      * @return the row as a Scalar array
246      * @throws IndexOutOfBoundsException in case row is out of bounds
247      */
248     @SuppressWarnings("unchecked")
249     public A[] getRowScalars(final int row) throws IndexOutOfBoundsException
250     {
251         checkRow(row);
252 
253         // Build a Q[] of length cols() using the runtime class of the first element
254         A first = get(row, 0);
255         A[] out = (A[]) Array.newInstance(first.getClass(), cols());
256         for (int c = 0; c < cols(); c++)
257         {
258             out[c] = get(row, c);
259         }
260         return out;
261     }
262 
263     /**
264      * Retrieve a row (1-based) from the matrix as an array of scalars.
265      * @param mRow row of the values to retrieve (1-based)
266      * @return the row as a Scalar array
267      * @throws IndexOutOfBoundsException in case row is out of bounds
268      */
269     public A[] mgetRowScalars(final int mRow) throws IndexOutOfBoundsException
270     {
271         mcheckRow(mRow);
272         return getRowScalars(mRow - 1);
273     }
274 
275     /**
276      * Retrieve a column (0-based) from the matrix as an array of scalars.
277      * @param col column of the values to retrieve (0-based)
278      * @return the column as a Scalar array
279      * @throws IndexOutOfBoundsException in case column is out of bounds
280      */
281     @SuppressWarnings("unchecked")
282     public A[] getColumnScalars(final int col) throws IndexOutOfBoundsException
283     {
284         checkCol(col);
285 
286         A first = get(0, col);
287         A[] out = (A[]) Array.newInstance(first.getClass(), rows());
288         for (int r = 0; r < rows(); r++)
289         {
290             out[r] = get(r, col);
291         }
292         return out;
293     }
294 
295     /**
296      * Retrieve a column (1-based) from the matrix as an array of scalars.
297      * @param mCol column of the values to retrieve (1-based)
298      * @return the column as a Scalar array
299      * @throws IndexOutOfBoundsException in case column is out of bounds
300      */
301     public A[] mgetColumnScalars(final int mCol) throws IndexOutOfBoundsException
302     {
303         mcheckCol(mCol);
304         return getColumnScalars(mCol - 1);
305     }
306 
307 }