1 package org.djunits.value.vdouble.matrix.base;
2
3 import org.djunits.unit.SIUnit;
4 import org.djunits.unit.Unit;
5 import org.djunits.unit.util.UnitException;
6 import org.djunits.value.Relative;
7 import org.djunits.value.ValueRuntimeException;
8 import org.djunits.value.vdouble.function.DoubleMathFunctions;
9 import org.djunits.value.vdouble.matrix.SIMatrix;
10 import org.djunits.value.vdouble.matrix.data.DoubleMatrixData;
11 import org.djunits.value.vdouble.scalar.base.DoubleScalar;
12 import org.djunits.value.vdouble.scalar.base.DoubleScalarRel;
13 import org.djunits.value.vdouble.vector.base.DoubleVector;
14 import org.djunits.value.vdouble.vector.base.DoubleVectorRel;
15
16 /**
17 * DoubleMatrixRel.java.
18 * <p>
19 * Copyright (c) 2019-2025 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
20 * BSD-style license. See <a href="https://djunits.org/docs/license.html">DJUNITS License</a>.
21 * </p>
22 * @author <a href="https://www.tudelft.nl/averbraeck" target="_blank">Alexander Verbraeck</a>
23 * @param <U> the unit
24 * @param <S> the scalar type belonging to the matrix type
25 * @param <RV> the relative vector type belonging to the relative matrix type
26 * @param <RM> the relative matrix type with this unit
27 */
28 public abstract class DoubleMatrixRel<U extends Unit<U>, S extends DoubleScalarRel<U, S>, RV extends DoubleVectorRel<U, S, RV>,
29 RM extends DoubleMatrixRel<U, S, RV, RM>> extends DoubleMatrix<U, S, RV, RM> implements Relative<U, RM>
30 {
31 /** */
32 private static final long serialVersionUID = 20190908L;
33
34 /**
35 * Construct a new Relative Mutable DoubleMatrix.
36 * @param data an internal data object
37 * @param unit the unit
38 */
39 protected DoubleMatrixRel(final DoubleMatrixData data, final U unit)
40 {
41 super(data.copy(), unit);
42 }
43
44 /**
45 * Compute the sum of all SI values of this matrix.
46 * @return the sum of all SI values of this matrix with the same display unit as this matrix
47 */
48 public final S zSum()
49 {
50 return instantiateScalarSI(this.data.zSum(), getDisplayUnit());
51 }
52
53 @Override
54 public final RM plus(final RM rel) throws ValueRuntimeException
55 {
56 return instantiateMatrix(this.getData().plus(rel.getData()), getDisplayUnit());
57 }
58
59 @Override
60 public final RM minus(final RM rel) throws ValueRuntimeException
61 {
62 return instantiateMatrix(this.getData().minus(rel.getData()), getDisplayUnit());
63 }
64
65 /**
66 * Increment all values of this matrix by the increment. This only works if this matrix is mutable.
67 * @param increment the scalar by which to increment all values
68 * @return this modified matrix
69 * @throws ValueRuntimeException in case this matrix is immutable
70 */
71 @SuppressWarnings("unchecked")
72 public RM incrementBy(final S increment)
73 {
74 checkCopyOnWrite();
75 assign(DoubleMathFunctions.INC(increment.si));
76 return (RM) this;
77 }
78
79 /**
80 * Increment all values of this matrix by the increment on a value by value basis. This only works if this matrix is
81 * mutable.
82 * @param increment the matrix that contains the values by which to increment the corresponding values
83 * @return this modified matrix
84 * @throws ValueRuntimeException in case this matrix is immutable
85 * @throws ValueRuntimeException when the sizes of the matrices differ, or <code>increment</code> is null
86 */
87 @SuppressWarnings("unchecked")
88 public RM incrementBy(final RM increment)
89 {
90 checkCopyOnWrite();
91 this.data.incrementBy(increment.getData());
92 return (RM) this;
93 }
94
95 /**
96 * Decrement all values of this matrix by the decrement. This only works if this matrix is mutable.
97 * @param decrement the scalar by which to decrement all values
98 * @return this modified matrix
99 * @throws ValueRuntimeException in case this matrix is immutable
100 */
101 @SuppressWarnings("unchecked")
102 public RM decrementBy(final S decrement)
103 {
104 checkCopyOnWrite();
105 assign(DoubleMathFunctions.DEC(decrement.si));
106 return (RM) this;
107 }
108
109 /**
110 * Decrement this Relative matrix by another Relative matrix. The operation is done value by value. This is only allowed if
111 * this matrix is mutable.
112 * @param decrement the matrix that contains the values by which to decrement the corresponding values
113 * @return this modified matrix
114 * @throws ValueRuntimeException in case this matrix is immutable
115 * @throws ValueRuntimeException when the sizes of the matrices differ, or <code>decrement</code> is null
116 */
117 @SuppressWarnings("unchecked")
118 public final RM decrementBy(final RM decrement)
119 {
120 checkCopyOnWrite();
121 this.data.decrementBy(decrement.getData());
122 return (RM) this;
123 }
124
125 /**
126 * Multiply all values of this matrix by the multiplier. This only works if the matrix is mutable.
127 * @param multiplier the factor by which to multiply all values
128 * @return this modified matrix
129 * @throws ValueRuntimeException in case the matrix is immutable
130 */
131 public RM multiplyBy(final double multiplier)
132 {
133 return assign(DoubleMathFunctions.MULT(multiplier));
134 }
135
136 /**
137 * Divide all values of this matrix by the divisor. This only works if the matrix is mutable.
138 * @param divisor the value by which to divide all values
139 * @return this modified matrix
140 * @throws ValueRuntimeException in case the matrix is immutable
141 */
142 public RM divideBy(final double divisor)
143 {
144 return assign(DoubleMathFunctions.DIV(divisor));
145 }
146
147 /**
148 * Multiply a Relative value with this Relative value for a matrix or matrix. The multiplication is done value by value and
149 * store the result in a new Relative value. If both operands are dense, the result is a dense matrix or matrix, otherwise
150 * the result is a sparse matrix or matrix.
151 * @param rel the right operand, which can be any matrix type
152 * @return the multiplication of this matrix and the operand
153 * @throws ValueRuntimeException in case this matrix or matrix and the operand have a different size
154 * @throws UnitException on unit error
155 * @param <UT> the unit type of the multiplier
156 * @param <ST> the scalar type of the multiplier
157 * @param <VT> the vector type of the multiplier
158 * @param <MT> the matrix type of the multiplier
159 */
160 public final <UT extends Unit<UT>, ST extends DoubleScalar<UT, ST>, VT extends DoubleVector<UT, ST, VT>,
161 MT extends DoubleMatrix<UT, ST, VT, MT> & Relative<UT, MT>> SIMatrix times(final MT rel)
162 throws ValueRuntimeException, UnitException
163 {
164 return new SIMatrix(this.getData().times(rel.getData()), SIUnit.of(
165 getDisplayUnit().getQuantity().getSiDimensions().plus(rel.getDisplayUnit().getQuantity().getSiDimensions())));
166 }
167
168 @Override
169 public final RM times(final double multiplier)
170 {
171 RM result = clone().mutable();
172 result.assign(DoubleMathFunctions.MULT(multiplier));
173 return result.immutable();
174 }
175
176 @Override
177 public final RM times(final float multiplier)
178 {
179 return times((double) multiplier);
180 }
181
182 /**
183 * Divide this Relative matrix by another Relative matrix. The operation is done value by value and store the result is
184 * stored in a new Relative matrix. If both operands are dense, the result is a dense matrix, otherwise the result is a
185 * sparse matrix. TODO discuss dense or sparseness of result.
186 * @param rel the right operand, which can be any matrix type
187 * @return the division of this matrix and the operand
188 * @throws ValueRuntimeException in case this matrix or matrix and the operand have a different size
189 * @throws UnitException on unit error
190 * @param <UT> the unit type of the multiplier
191 * @param <ST> the scalar type of the multiplier
192 * @param <VT> the vector type of the multiplier
193 * @param <MT> the matrix type of the multiplier
194 */
195 public final <UT extends Unit<UT>, ST extends DoubleScalar<UT, ST>, VT extends DoubleVector<UT, ST, VT>,
196 MT extends DoubleMatrix<UT, ST, VT, MT> & Relative<UT, MT>> SIMatrix divide(final MT rel)
197 throws ValueRuntimeException, UnitException
198 {
199 return new SIMatrix(this.getData().divide(rel.getData()), SIUnit.of(
200 getDisplayUnit().getQuantity().getSiDimensions().minus(rel.getDisplayUnit().getQuantity().getSiDimensions())));
201 }
202
203 @Override
204 public final RM divide(final float divisor)
205 {
206 return divide((double) divisor);
207 }
208
209 @Override
210 public final RM divide(final double divisor)
211 {
212 RM result = clone().mutable();
213 result.assign(DoubleMathFunctions.DIV(divisor));
214 return result.immutable();
215 }
216
217 }