001/* 002 * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences. 003 * Copyright (C) 2006 - JScience (http://jscience.org/) 004 * All rights reserved. 005 * 006 * Permission to use, copy, modify, and distribute this software is 007 * freely granted, provided that this notice is preserved. 008 */ 009package org.jscience.mathematics.vector; 010 011import java.util.Iterator; 012import java.util.List; 013import javolution.context.ArrayFactory; 014import javolution.lang.MathLib; 015import javolution.xml.XMLFormat; 016import javolution.xml.stream.XMLStreamException; 017 018import org.jscience.mathematics.number.Float64; 019import org.jscience.mathematics.structure.VectorSpaceNormed; 020 021/** 022 * <p> This class represents an optimized {@link Vector vector} implementation 023 * for 64 bits floating point elements.</p> 024 * 025 * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a> 026 * @version 3.3, January 2, 2007 027 */ 028public final class Float64Vector extends Vector<Float64> implements 029 VectorSpaceNormed<Vector<Float64>, Float64> { 030 031 /** 032 * Holds the default XML representation. For example: 033 * [code] 034 * <Float64Vector dimension="2"> 035 * <Float64 value="1.0" /> 036 * <Float64 value="0.0" /> 037 * </Float64Vector>[/code] 038 */ 039 protected static final XMLFormat<Float64Vector> XML = new XMLFormat<Float64Vector>( 040 Float64Vector.class) { 041 042 @Override 043 public Float64Vector newInstance(Class<Float64Vector> cls, InputElement xml) 044 throws XMLStreamException { 045 int dimension = xml.getAttribute("dimension", 0); 046 Float64Vector V = FACTORY.array(dimension); 047 V._dimension = dimension; 048 return V; 049 } 050 051 @SuppressWarnings("unchecked") 052 @Override 053 public void read(InputElement xml, Float64Vector V) 054 throws XMLStreamException { 055 for (int i=0, n=V._dimension; i < n;) { 056 V._values[i++] = ((Float64)xml.getNext()).doubleValue(); 057 } 058 if (xml.hasNext()) 059 throw new XMLStreamException("Too many elements"); 060 } 061 062 @Override 063 public void write(Float64Vector V, OutputElement xml) 064 throws XMLStreamException { 065 xml.setAttribute("dimension", V._dimension); 066 for (int i = 0, n=V._dimension; i < n;) { 067 xml.add(V.get(i++)); 068 } 069 } 070 }; 071 072 /** 073 * Holds factory for vectors with variable size arrays. 074 */ 075 private static final ArrayFactory<Float64Vector> FACTORY 076 = new ArrayFactory<Float64Vector>() { 077 078 @Override 079 protected Float64Vector create(int capacity) { 080 return new Float64Vector(capacity); 081 } 082 083 }; 084 085 /** 086 * Holds the dimension. 087 */ 088 private int _dimension; 089 090 /** 091 * Holds the values. 092 */ 093 private final double[] _values; 094 095 /** 096 * Creates a vector of specified capacity. 097 */ 098 private Float64Vector(int capacity) { 099 _values = new double[capacity]; 100 } 101 102 /** 103 * Returns a new vector holding the specified <code>double</code> values. 104 * 105 * @param values the vector values. 106 * @return the vector having the specified values. 107 */ 108 public static Float64Vector valueOf(double... values) { 109 int n = values.length; 110 Float64Vector V = FACTORY.array(n); 111 V._dimension = n; 112 System.arraycopy(values, 0, V._values, 0, n); 113 return V; 114 } 115 116 /** 117 * Returns a new vector holding the elements from the specified 118 * collection. 119 * 120 * @param elements the collection of floating-points numbers. 121 * @return the vector having the specified elements. 122 */ 123 public static Float64Vector valueOf(List<Float64> elements) { 124 int n = elements.size(); 125 Float64Vector V = FACTORY.array(n); 126 V._dimension = n; 127 Iterator<Float64> iterator = elements.iterator(); 128 for (int i = 0; i < n; i++) { 129 V._values[i] = iterator.next().doubleValue(); 130 } 131 return V; 132 } 133 134 /** 135 * Returns a {@link Float64Vector} instance equivalent to the 136 * specified vector. 137 * 138 * @param that the vector to convert. 139 * @return <code>that</code> or new equivalent Float64Vector. 140 */ 141 public static Float64Vector valueOf(Vector<Float64> that) { 142 if (that instanceof Float64Vector) 143 return (Float64Vector) that; 144 int n = that.getDimension(); 145 Float64Vector V = FACTORY.array(n); 146 V._dimension = n; 147 for (int i = 0; i < n; i++) { 148 V._values[i] = that.get(i).doubleValue(); 149 } 150 return V; 151 } 152 153 /** 154 * Returns the value of a floating point number from this vector (fast). 155 * 156 * @param i the floating point number index. 157 * @return the value of the floating point number at <code>i</code>. 158 * @throws IndexOutOfBoundsException <code>(i < 0) || (i >= dimension())</code> 159 */ 160 public double getValue(int i) { 161 if (i >= _dimension) 162 throw new ArrayIndexOutOfBoundsException(); 163 return _values[i]; 164 } 165 166 /** 167 * Returns the Euclidian norm of this vector (square root of the 168 * dot product of this vector and itself). 169 * 170 * @return <code>sqrt(this ยท this)</code>. 171 */ 172 public Float64 norm() { 173 return Float64.valueOf(normValue()); 174 } 175 176 /** 177 * Returns the {@link #norm()} value of this vector. 178 * 179 * @return <code>this.norm().doubleValue()</code>. 180 */ 181 public double normValue() { 182 double normSquared = 0; 183 for (int i = _dimension; --i >= 0;) { 184 double values = _values[i]; 185 normSquared += values * values; 186 } 187 return MathLib.sqrt(normSquared); 188 } 189 190 @Override 191 public int getDimension() { 192 return _dimension; 193 } 194 195 @Override 196 public Float64 get(int i) { 197 if (i >= _dimension) 198 throw new IndexOutOfBoundsException(); 199 return Float64.valueOf(_values[i]); 200 } 201 202 @Override 203 public Float64Vector opposite() { 204 Float64Vector V = FACTORY.array(_dimension); 205 V._dimension = _dimension; 206 for (int i = 0; i < _dimension; i++) { 207 V._values[i] = - _values[i]; 208 } 209 return V; 210 } 211 212 @Override 213 public Float64Vector plus(Vector<Float64> that) { 214 Float64Vector T = Float64Vector.valueOf(that); 215 if (T._dimension != _dimension) throw new DimensionException(); 216 Float64Vector V = FACTORY.array(_dimension); 217 V._dimension = _dimension; 218 for (int i = 0; i < _dimension; i++) { 219 V._values[i] = _values[i] + T._values[i]; 220 } 221 return V; 222 } 223 224 @Override 225 public Float64Vector minus(Vector<Float64> that) { 226 Float64Vector T = Float64Vector.valueOf(that); 227 if (T._dimension != _dimension) throw new DimensionException(); 228 Float64Vector V = FACTORY.array(_dimension); 229 V._dimension = _dimension; 230 for (int i = 0; i < _dimension; i++) { 231 V._values[i] = _values[i] - T._values[i]; 232 } 233 return V; 234 } 235 236 @Override 237 public Float64Vector times(Float64 k) { 238 Float64Vector V = FACTORY.array(_dimension); 239 V._dimension = _dimension; 240 double d = k.doubleValue(); 241 for (int i = 0; i < _dimension; i++) { 242 V._values[i] = _values[i] * d; 243 } 244 return V; 245 } 246 247 /** 248 * Equivalent to <code>this.times(Float64.valueOf(k))</code> 249 * 250 * @param k the coefficient. 251 * @return <code>this * k</code> 252 */ 253 public Float64Vector times(double k) { 254 Float64Vector V = FACTORY.array(_dimension); 255 V._dimension = _dimension; 256 for (int i = 0; i < _dimension; i++) { 257 V._values[i] = _values[i] * k; 258 } 259 return V; 260 } 261 262 @Override 263 public Float64 times(Vector<Float64> that) { 264 Float64Vector T = Float64Vector.valueOf(that); 265 if (T._dimension != _dimension) 266 throw new DimensionException(); 267 double[] T_values = T._values; 268 double sum = _values[0] * T_values[0]; 269 for (int i = 1; i < _dimension; i++) { 270 sum += _values[i] * T_values[i]; 271 } 272 return Float64.valueOf(sum); 273 } 274 275 276 @Override 277 public Float64Vector cross(Vector<Float64> that) { 278 Float64Vector T = Float64Vector.valueOf(that); 279 if ((this._dimension != 3) || (T._dimension != 3)) 280 throw new DimensionException( 281 "The cross product of two vectors requires " 282 + "3-dimensional vectors"); 283 double x = _values[1] * T._values[2] - _values[2] * T._values[1]; 284 double y = _values[2] * T._values[0] - _values[0] * T._values[2]; 285 double z = _values[0] * T._values[1] - _values[1] * T._values[0]; 286 return Float64Vector.valueOf(x, y, z); 287 } 288 289 @Override 290 public Float64Vector copy() { 291 Float64Vector V = FACTORY.array(_dimension); 292 V._dimension = _dimension; 293 for (int i = 0; i < _dimension; i++) { 294 V._values[i] = _values[i]; 295 } 296 return V; 297 } 298 299 /////////////////////////////// 300 // Package Private Utilities // 301 /////////////////////////////// 302 303 static Float64Vector newInstance(int n) { 304 Float64Vector V = FACTORY.array(n); 305 V._dimension = n; 306 return V; 307 } 308 309 void set(int i, double v) { 310 _values[i] = v; 311 } 312 313 private static final long serialVersionUID = 1L; 314 315}