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-2019 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 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 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 FloatMatrixData; an internal data object 59 * @param unit U; 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 FloatMatrixData; an internal data object 80 * @param unit U; 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 FloatMatrixData; an internal data object 88 * @param unit U; 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 float; the value 96 * @param unit U; the unit 97 * @return S the Immutable FloatScalar of the right type 98 */ 99 protected abstract S instantiateScalar(float value, U unit); 100 101 /** {@inheritDoc} */ 102 @Override 103 @SuppressWarnings("checkstyle:designforextension") 104 public final S get(final int row, final int column) throws ValueException 105 { 106 checkIndex(row, column); 107 return instantiateScalar(getInUnit(row, column, getUnit()), getUnit()); 108 } 109 110 /**********************************************************************************/ 111 /**************************** TYPED CALCULATION METHODS ***************************/ 112 /**********************************************************************************/ 113 114 /** 115 * Add a Relative value to this Relative value for a matrix or matrix. The addition is done value by value and store the 116 * result in a new Relative value. If both operands are sparse, the result is a sparse matrix or matrix, otherwise the 117 * result is a dense matrix or matrix. 118 * @param rel R; the right operand 119 * @return the addition of this matrix and the operand 120 * @throws ValueException in case this matrix or matrix and the operand have a different size 121 */ 122 public final R plus(final R rel) throws ValueException 123 { 124 return instantiateType(this.getData().plus(rel.getData()), getUnit()); 125 } 126 127 /** 128 * Subtract a Relative value from this Relative value for a matrix or matrix. The subtraction is done value by value and 129 * store the result in a new Relative value. If both operands are sparse, the result is a sparse matrix or matrix, otherwise 130 * the result is a dense matrix or matrix. 131 * @param rel R; the right operand 132 * @return the subtraction of this matrix and the operand 133 * @throws ValueException in case this matrix or matrix and the operand have a different size 134 */ 135 public final R minus(final R rel) throws ValueException 136 { 137 return instantiateType(this.getData().minus(rel.getData()), getUnit()); 138 } 139 140 /** 141 * Multiply a Relative value with this Relative value for a matrix or matrix. The multiplication is done value by value and 142 * store the result in a new Relative value. If both operands are dense, the result is a dense matrix or matrix, otherwise 143 * the result is a sparse matrix or matrix. 144 * @param rel R; the right operand 145 * @return the multiplication of this matrix and the operand 146 * @throws ValueException in case this matrix or matrix and the operand have a different size 147 */ 148 public final R times(final R rel) throws ValueException 149 { 150 return instantiateType(this.getData().times(rel.getData()), getUnit()); 151 } 152 153 /** 154 * Divide this Relative value by a Relative value for a matrix or matrix. The division is done value by value and store the 155 * result in a new Relative value. If both operands are dense, the result is a dense matrix or matrix, otherwise the result 156 * is a sparse matrix or matrix. 157 * @param rel R; the right operand 158 * @return the division of this matrix and the operand 159 * @throws ValueException in case this matrix or matrix and the operand have a different size 160 */ 161 public final R divide(final R rel) throws ValueException 162 { 163 return instantiateType(this.getData().divide(rel.getData()), getUnit()); 164 } 165 166 /* ============================================================================================ */ 167 /* ============================= STATIC CONSTRUCTOR HELP METHODS ============================== */ 168 /* ============================================================================================ */ 169 170 /** 171 * Check that a provided array can be used to create some descendant of a FloatMatrix, and return the Unit. 172 * @param dsArray S[][]; the array to check and get the unit for 173 * @param <U> the unit 174 * @param <S> the scalar type 175 * @return the unit of the object 176 * @throws ValueException when the array is null, has length equal to 0, or has first entry with length equal to 0 177 */ 178 static <U extends Unit<U>, S extends AbstractFloatScalarRel<U, S>> U checkUnit(final S[][] dsArray) throws ValueException 179 { 180 ensureRectangularAndNonEmpty(dsArray); 181 return dsArray[0][0].getUnit(); 182 } 183 184 /** 185 * Check that a 2D array of FloatScalar<?> is rectangular; i.e. all rows have the same length and is non empty. 186 * @param values S[][]; the 2D array to check 187 * @param <U> the unit 188 * @param <S> the scalar type 189 * @throws ValueException when values is not rectangular, or contains no data 190 */ 191 protected static <U extends Unit<U>, 192 S extends AbstractFloatScalarRel<U, S>> void ensureRectangularAndNonEmpty(final S[][] values) throws ValueException 193 { 194 if (null == values) 195 { 196 throw new ValueException("Cannot create a FloatVector or MutableFloatVector from an empty array of FloatScalar"); 197 } 198 if (0 == values.length || 0 == values[0].length) 199 { 200 throw new ValueException("Creating FloatVector or MutableFloatVector: " 201 + "Cannot determine unit for FloatMatrix from an empty array of FloatScalar"); 202 } 203 for (int row = values.length; --row >= 1;) 204 { 205 if (values[0].length != values[row].length) 206 { 207 throw new ValueException("Creating FloatVector or MutableFloatVector: Lengths of rows are not all the same"); 208 } 209 } 210 } 211 212 }