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