001/* 002 * AbstractParamVector -- A partial implementation of a vector of Parameter objects. 003 * 004 * Copyright (C) 2008-2015, by Joseph A. Huwaldt. 005 * All rights reserved. 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * You should have received a copy of the GNU Lesser General Public License 018 * along with this program; if not, write to the Free Software 019 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 020 * Or visit: http://www.gnu.org/licenses/lgpl.html 021 */ 022package jahuwaldt.js.param; 023 024import java.text.MessageFormat; 025import java.util.ResourceBundle; 026import javax.measure.Measurable; 027import javax.measure.converter.ConversionException; 028import javax.measure.quantity.Angle; 029import javax.measure.quantity.Quantity; 030import javax.measure.unit.SI; 031import javax.measure.unit.Unit; 032import javolution.lang.MathLib; 033import javolution.lang.Realtime; 034import org.jscience.mathematics.structure.VectorSpaceNormed; 035import org.jscience.mathematics.vector.DimensionException; 036import org.jscience.mathematics.vector.Vector; 037 038/** 039 * This class represents an n-dimensional {@link Vector vector} of {@link Parameter} 040 * elements. 041 * 042 * <p> Modified by: Joseph A. Huwaldt </p> 043 * 044 * @author Joseph A. Huwaldt, Date: November 21, 2008 045 * @version October 31, 2015 046 * 047 * @param <Q> The Quantity (unit type, such as Length or Volume) of this parameter. 048 * @param <T> The type of AbstractParamVector. 049 */ 050public abstract class AbstractParamVector<Q extends Quantity, T extends AbstractParamVector<Q, T>> extends 051 Vector<Parameter<Q>> implements 052 VectorSpaceNormed<Vector<Parameter<Q>>, Parameter<Q>>, Measurable<Q>, Realtime { 053 054 /** 055 * The resource bundle for this package. 056 */ 057 protected static final ResourceBundle RESOURCES = Parameter.RESOURCES; 058 059 /** 060 * Returns a Vector3D representation of this vector if possible. 061 * 062 * @return A Vector3D that is equivalent to this vector 063 * @throws DimensionException if this vector has any number of dimensions other than 064 * 3. 065 */ 066 public abstract Vector3D<Q> toVector3D(); 067 068 /** 069 * Return the specified {@link Vector3D} object as a vector of a particular subtype of 070 * this class. 071 * 072 * @param vector The <code>Vector3D</code> object to be converted to a specific subtype 073 * of this class. 074 * @return An instance of a specific subtype of this class that is equivalent to the 075 * supplied <code>Vector3D</code> object. 076 * @throws ConversionException if the sub-type can not represent the units used in the 077 * supplied vector. 078 */ 079 public abstract T fromVector3D(Vector3D<Q> vector) throws ConversionException; 080 081 /** 082 * Returns the value of the Parameter in this vector as a <code>double</code> in the 083 * current units of the specified dimension of this vector. 084 * 085 * @param i the dimension index. 086 * @return the value of the Parameter at <code>i</code>. 087 * @throws IndexOutOfBoundsException <code>(i < 0) || (i > dimension()-1)</code> 088 */ 089 public double getValue(int i) { 090 return get(i).getValue(); 091 } 092 093 /** 094 * Returns the Euclidian norm, magnitude, or length of this vector (square root of the 095 * dot product of this vector and itself). 096 * 097 * @return <code>sqrt(this · this)</code>. 098 */ 099 @Override 100 public Parameter<Q> norm() { 101 return Parameter.valueOf(normValue(), getUnit()); 102 } 103 104 /** 105 * Returns the {@link #norm}, magnitude, or length value of this vector. 106 * 107 * @return <code>this.norm().getValue()</code>. 108 */ 109 public abstract double normValue(); 110 111 /** 112 * Returns the Euclidian norm, magnitude, or length of this vector (square root of the 113 * dot product of this vector and itself). 114 * 115 * @return <code>sqrt(this · this)</code>. 116 */ 117 public Parameter<Q> mag() { 118 return norm(); 119 } 120 121 /** 122 * Returns the {@link #norm}, magnitude, or length value of this vector. 123 * 124 * @return <code>this.norm().doubleValue()</code>. 125 */ 126 public double magValue() { 127 return normValue(); 128 } 129 130 /** 131 * Returns the sum of this vector with the parameter specified. The unit of the output 132 * vector will be the units of this vector. 133 * 134 * @param that the parameter to be added to this vector. 135 * @return <code>this + that</code>. 136 */ 137 public abstract T plus(Parameter<Q> that); 138 139 /** 140 * Subtracts the supplied Parameter from this vector. The unit of the output vector 141 * will be the units of this vector. 142 * 143 * @param that the Parameter to be subtracted from this vector. 144 * @return <code>this - that</code>. 145 */ 146 public abstract T minus(Parameter<Q> that); 147 148 /** 149 * Returns the product of this vector with the specified coefficient. 150 * 151 * @param k the coefficient multiplier. 152 * @return <code>this · k</code> 153 */ 154 public abstract T times(double k); 155 156 /** 157 * Returns the dot product of this vector with the one specified. 158 * 159 * @param that the vector multiplier. 160 * @return <code>this · that</code> 161 * @throws DimensionException if <code>this.dimension() != that.dimension()</code> 162 * @see <a href="http://en.wikipedia.org/wiki/Dot_product"> 163 * Wikipedia: Dot Product</a> 164 */ 165 public Parameter<?> dot(Vector that) { 166 return times(that); 167 } 168 169 /** 170 * Returns this vector with each element divided by the specified divisor 171 * (dimensionless). 172 * 173 * @param divisor the divisor. 174 * @return <code>this / divisor</code>. 175 */ 176 public T divide(double divisor) { 177 return times(1. / divisor); 178 } 179 180 /** 181 * Returns the angle between this vector and the specified vector. 182 * 183 * @param that the vector to which the angle will be determined. 184 * @return <code>acos(this · that)/(norm(this)*norm(that))</code> 185 */ 186 public Parameter<Angle> angle(AbstractParamVector that) { 187 double scalar = this.times(that).getValue(); 188 double abs1 = this.normValue(); 189 double abs2 = that.to(this.getUnit()).normValue(); 190 191 double argument = 1.; 192 double dum = abs1 * abs2; 193 if (dum > Parameter.SQRT_EPS) 194 argument = scalar / dum; 195 196 if (argument > 1.) 197 argument = 1.; 198 else if (argument < -1.) 199 argument = -1.; 200 201 return Parameter.valueOf(MathLib.acos(argument), SI.RADIAN); 202 } 203 204 /** 205 * Returns the unit in which the values in this vector are stated. 206 * 207 * @return The unit in which the values in this vector are stated 208 */ 209 public abstract Unit<Q> getUnit(); 210 211 /** 212 * Returns the equivalent to this vector but stated in the specified unit. 213 * 214 * @param <R> The Quantity (unit type) of the vector being output. 215 * @param unit the unit of the vector to be returned. 216 * @return a vector equivalent to this vector but stated in the specified unit. 217 * @throws ConversionException if the current model does not allows for conversion to 218 * the specified unit. 219 */ 220 public abstract <R extends Quantity> AbstractParamVector<R, ? extends AbstractParamVector> to(Unit<R> unit); 221 222 /** 223 * Returns the value of this measurable stated in the specified unit as a 224 * <code>double</code>. This implementation returns the {@link #normValue} stated in 225 * the specified units. 226 * 227 * @param unit the unit in which this measurable value is stated. 228 * @return the numeric value after conversion to type <code>double</code>. 229 */ 230 @Override 231 public double doubleValue(Unit<Q> unit) { 232 Unit<?> thisUnit = getUnit(); 233 return ((thisUnit == unit) || thisUnit.equals(unit)) ? this.normValue() : this.to(unit).normValue(); 234 } 235 236 /** 237 * Returns the estimated integral value of this measurable stated in the specified 238 * unit as a <code>long</code>. This implementation returns the {@link #normValue} 239 * stated in the specified units. 240 * 241 * <p> 242 * Note: This method differs from the <code>Number.longValue()</code> in the sense 243 * that the closest integer value is returned and an ArithmeticException is raised 244 * instead of a bit truncation in case of overflow (safety critical).</p> 245 * 246 * @param unit the unit in which the measurable value is stated. 247 * @return the numeric value after conversion to type <code>long</code>. 248 * @throws ArithmeticException if this quantity cannot be represented as a 249 * <code>long</code> number in the specified unit. 250 */ 251 @Override 252 public final long longValue(Unit<Q> unit) { 253 if (!getUnit().equals(unit)) 254 return this.to(unit).longValue(unit); 255 double doubleValue = this.normValue(); 256 if ((doubleValue >= Long.MIN_VALUE) && (doubleValue <= Long.MAX_VALUE)) 257 return Math.round(doubleValue); 258 throw new ArithmeticException( 259 MessageFormat.format(RESOURCES.getString("canNotBeLong"), doubleValue, getUnit())); 260 } 261 262 /** 263 * Compares the {@link #norm} of this measure with the specified measurable object. 264 * 265 * @param that the measure to compare with. 266 * @return a negative integer, zero, or a positive integer as this measure is less 267 * than, equal to, or greater than that measurable. 268 * @throws ConversionException if the current model does not allows for these measure 269 * to be compared. 270 */ 271 @Override 272 public int compareTo(Measurable<Q> that) { 273 double thatValue = that.doubleValue(getUnit()); 274 return Double.compare(this.normValue(), thatValue); 275 } 276 277 /** 278 * Fills the input Java array with the values of the coordinates of this vector in 279 * the current units. 280 * 281 * @param array An existing array of at least this.getDimension() size that will be 282 * filled with the values from this vector. 283 * @return The input Java array filled with the coordinate values from this vector. 284 */ 285 public double[] toArray(double[] array) { 286 int size = this.getDimension(); 287 for (int i=size-1; i >= 0; --i) { 288 array[i] = this.getValue(i); 289 } 290 return array; 291 } 292 293 /** 294 * Returns a new Java array that contains the values of the coordinates of this vector in 295 * the current units. 296 * 297 * @return A new Java array of values from this vector. 298 */ 299 public double[] toArray() { 300 double[] arr = new double[this.getDimension()]; 301 return toArray(arr); 302 } 303}