1 package org.djunits.value.vfloat.matrix; 2 3 import java.io.Serializable; 4 5 import org.djunits.unit.Unit; 6 import org.djunits.value.Relative; 7 import org.djunits.value.StorageType; 8 import org.djunits.value.ValueException; 9 import org.djunits.value.vfloat.scalar.AbstractFloatScalarRel; 10 11 /** 12 * Relative Immutable typed matrix. 13 * <p> 14 * Copyright (c) 2013-2018 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br> 15 * BSD-style license. See <a href="http://djunits.org/docs/license.html">DJUNITS License</a>. 16 * <p> 17 * $LastChangedDate: 2015-09-29 14:14:28 +0200 (Tue, 29 Sep 2015) $, @version $Revision: 73 $, by $Author: pknoppers $, initial 18 * version Sep 5, 2015 <br> 19 * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a> 20 * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a> 21 * @param <U> the unit 22 * @param <R> the relative matrix type 23 * @param <MR> the mutable relative matrix type 24 * @param <S> the relative scalar type 25 */ 26 abstract class AbstractFloatMatrixRel<U extends Unit<U>, R extends AbstractFloatMatrixRel<U, R, MR, S>, 27 MR extends AbstractMutableFloatMatrixRel<U, R, MR, S>, S extends AbstractFloatScalarRel<U, S>> 28 extends AbstractFloatMatrix<U, R> implements FloatMatrixInterface<U>, Relative, Serializable 29 { 30 /** */ 31 private static final long serialVersionUID = 20151006L; 32 33 /** 34 * Construct a new Relative Immutable FloatMatrix. 35 * @param values float[][]; the values of the entries in the new Relative Immutable FloatMatrix 36 * @param unit U; the unit of the new Relative Immutable FloatMatrix 37 * @param storageType the data type to use (e.g., DENSE or SPARSE) 38 * @throws ValueException when values is null 39 */ 40 AbstractFloatMatrixRel(final float[][] values, final U unit, final StorageType storageType) throws ValueException 41 { 42 super(unit, FloatMatrixData.instantiate(ensureRectangularAndNonEmpty(values), unit.getScale(), storageType)); 43 } 44 45 /** 46 * Construct a new Relative Immutable FloatMatrix. 47 * @param values S[][]; the values of the entries in the new Relative Immutable FloatMatrix 48 * @param storageType the data type to use (e.g., DENSE or SPARSE) 49 * @throws ValueException when values has zero entries 50 */ 51 AbstractFloatMatrixRel(final S[][] values, final StorageType storageType) throws ValueException 52 { 53 super(checkUnit(values), FloatMatrixData.instantiate(values, storageType)); 54 } 55 56 /** 57 * Construct a new Relative Immutable FloatMatrix. 58 * @param data an internal data object 59 * @param unit the unit 60 */ 61 AbstractFloatMatrixRel(final FloatMatrixData data, final U unit) 62 { 63 super(unit, data.copy()); 64 } 65 66 /** 67 * Create a mutable version of this FloatMatrix. <br> 68 * The mutable version is created with a shallow copy of the data and the internal copyOnWrite flag set. The first operation 69 * in the mutable version that modifies the data shall trigger a deep copy of the data. 70 * @return MA; mutable version of this FloatMatrix 71 */ 72 public MR mutable() 73 { 74 return instantiateMutableType(getData(), getUnit()); 75 } 76 77 /** 78 * Construct a new Relative Immutable FloatMatrix of the right type. Each extending class must implement this method. 79 * @param dmd an internal data object 80 * @param unit the unit 81 * @return M the Mutable FloatMatrix of the right type 82 */ 83 protected abstract R instantiateType(FloatMatrixData dmd, U unit); 84 85 /** 86 * Construct a new Relative Mutable FloatMatrix of the right type. Each extending class must implement this method. 87 * @param dmd an internal data object 88 * @param unit the unit 89 * @return M the Mutable FloatMatrix of the right type 90 */ 91 protected abstract MR instantiateMutableType(FloatMatrixData dmd, U unit); 92 93 /** 94 * Construct a new Relative Immutable FloatScalar of the right type. Each extending class must implement this method. 95 * @param value the value 96 * @param unit the unit 97 * @return S the Immutable FloatScalar of the right type 98 */ 99 protected abstract S instantiateScalar(float value, U unit); 100 101 /** 102 * Return the Scalar value at the index position. 103 * @param row the row position 104 * @param column the column position 105 * @return S the scalar 106 * @throws ValueException when index out of bounds 107 */ 108 @SuppressWarnings("checkstyle:designforextension") 109 public final S get(final int row, final int column) throws ValueException 110 { 111 checkIndex(row, column); 112 return instantiateScalar(getInUnit(row, column, getUnit()), getUnit()); 113 } 114 115 /**********************************************************************************/ 116 /**************************** TYPED CALCULATION METHODS ***************************/ 117 /**********************************************************************************/ 118 119 /** 120 * Add a Relative value to this Relative value for a matrix or matrix. The addition is done value by value and store the 121 * result in a new Relative value. If both operands are sparse, the result is a sparse matrix or matrix, otherwise the 122 * result is a dense matrix or matrix. 123 * @param rel the right operand 124 * @return the addition of this matrix and the operand 125 * @throws ValueException in case this matrix or matrix and the operand have a different size 126 */ 127 public final R plus(final R rel) throws ValueException 128 { 129 return instantiateType(this.getData().plus(rel.getData()), getUnit()); 130 } 131 132 /** 133 * Subtract a Relative value from this Relative value for a matrix or matrix. The subtraction is done value by value and 134 * store the result in a new Relative value. If both operands are sparse, the result is a sparse matrix or matrix, otherwise 135 * the result is a dense matrix or matrix. 136 * @param rel the right operand 137 * @return the subtraction of this matrix and the operand 138 * @throws ValueException in case this matrix or matrix and the operand have a different size 139 */ 140 public final R minus(final R rel) throws ValueException 141 { 142 return instantiateType(this.getData().minus(rel.getData()), getUnit()); 143 } 144 145 /** 146 * Multiply a Relative value with this Relative value for a matrix or matrix. The multiplication is done value by value and 147 * store the result in a new Relative value. If both operands are dense, the result is a dense matrix or matrix, otherwise 148 * the result is a sparse matrix or matrix. 149 * @param rel the right operand 150 * @return the multiplication of this matrix and the operand 151 * @throws ValueException in case this matrix or matrix and the operand have a different size 152 */ 153 public final R times(final R rel) throws ValueException 154 { 155 return instantiateType(this.getData().times(rel.getData()), getUnit()); 156 } 157 158 /** 159 * Divide this Relative value by a Relative value for a matrix or matrix. The division is done value by value and store the 160 * result in a new Relative value. If both operands are dense, the result is a dense matrix or matrix, otherwise the result 161 * is a sparse matrix or matrix. 162 * @param rel the right operand 163 * @return the division of this matrix and the operand 164 * @throws ValueException in case this matrix or matrix and the operand have a different size 165 */ 166 public final R divide(final R rel) throws ValueException 167 { 168 return instantiateType(this.getData().divide(rel.getData()), getUnit()); 169 } 170 171 /* ============================================================================================ */ 172 /* ============================= STATIC CONSTRUCTOR HELP METHODS ============================== */ 173 /* ============================================================================================ */ 174 175 /** 176 * Check that a provided array can be used to create some descendant of a FloatMatrix, and return the Unit. 177 * @param dsArray the array to check and get the unit for 178 * @param <U> the unit 179 * @param <S> the scalar type 180 * @return the unit of the object 181 * @throws ValueException when the array is null, has length equal to 0, or has first entry with length equal to 0 182 */ 183 static <U extends Unit<U>, S extends AbstractFloatScalarRel<U, S>> U checkUnit(final S[][] dsArray) throws ValueException 184 { 185 ensureRectangularAndNonEmpty(dsArray); 186 return dsArray[0][0].getUnit(); 187 } 188 189 /** 190 * Check that a 2D array of FloatScalar<?> is rectangular; i.e. all rows have the same length and is non empty. 191 * @param values FloatScalar<?>[][]; the 2D array to check 192 * @param <U> the unit 193 * @param <S> the scalar type 194 * @throws ValueException when values is not rectangular, or contains no data 195 */ 196 protected static <U extends Unit<U>, 197 S extends AbstractFloatScalarRel<U, S>> void ensureRectangularAndNonEmpty(final S[][] values) throws ValueException 198 { 199 if (null == values) 200 { 201 throw new ValueException("Cannot create a FloatVector or MutableFloatVector from an empty array of FloatScalar"); 202 } 203 if (0 == values.length || 0 == values[0].length) 204 { 205 throw new ValueException("Creating FloatVector or MutableFloatVector: " 206 + "Cannot determine unit for FloatMatrix from an empty array of FloatScalar"); 207 } 208 for (int row = values.length; --row >= 1;) 209 { 210 if (values[0].length != values[row].length) 211 { 212 throw new ValueException("Creating FloatVector or MutableFloatVector: Lengths of rows are not all the same"); 213 } 214 } 215 } 216 217 }