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