001: package JSci.maths.vectors;
002:
003: import JSci.maths.Complex;
004: import JSci.maths.ComplexMapping;
005: import JSci.maths.MathDouble;
006: import JSci.maths.MathInteger;
007: import JSci.maths.algebras.Module;
008: import JSci.maths.algebras.VectorSpace;
009: import JSci.maths.algebras.HilbertSpace;
010: import JSci.maths.fields.Ring;
011: import JSci.maths.fields.Field;
012: import JSci.maths.groups.AbelianGroup;
013:
014: /**
015: * An array-based implementation of a complex vector.
016: * @version 2.2
017: * @author Mark Hale
018: */
019: public class ComplexVector extends AbstractComplexVector {
020: /**
021: * Arrays containing the components of the vector.
022: */
023: protected double vectorRe[];
024: protected double vectorIm[];
025:
026: /**
027: * Constructs an empty vector.
028: * @param dim the dimension of the vector.
029: */
030: public ComplexVector(final int dim) {
031: super (dim);
032: vectorRe = new double[dim];
033: vectorIm = new double[dim];
034: }
035:
036: /**
037: * Constructs a vector by wrapping two arrays.
038: * @param real an array of real values
039: * @param imag an array of imaginary values
040: */
041: public ComplexVector(final double real[], final double imag[]) {
042: super (real.length);
043: vectorRe = real;
044: vectorIm = imag;
045: }
046:
047: /**
048: * Constructs a vector from an array.
049: * @param array an assigned value
050: */
051: public ComplexVector(final Complex array[]) {
052: this (array.length);
053: for (int i = 0; i < N; i++) {
054: vectorRe[i] = array[i].real();
055: vectorIm[i] = array[i].imag();
056: }
057: }
058:
059: /**
060: * Compares two complex vectors for equality.
061: * @param a a complex vector
062: */
063: public boolean equals(Object a, double tol) {
064: if (a != null && (a instanceof ComplexVector)
065: && N == ((ComplexVector) a).N) {
066: final ComplexVector cv = (ComplexVector) a;
067: double sumSqr = 0.0;
068: for (int i = 0; i < N; i++) {
069: double deltaRe = vectorRe[i] - cv.getRealComponent(i);
070: double deltaIm = vectorIm[i] - cv.getImagComponent(i);
071: sumSqr += deltaRe * deltaRe + deltaIm * deltaIm;
072: }
073: return (sumSqr <= tol * tol);
074: } else
075: return false;
076: }
077:
078: /**
079: * Returns a comma delimited string representing the value of this vector.
080: */
081: public String toString() {
082: final StringBuffer buf = new StringBuffer(8 * N);
083: int i;
084: for (i = 0; i < N - 1; i++) {
085: buf.append(Complex.toString(vectorRe[i], vectorIm[i]));
086: buf.append(',');
087: }
088: buf.append(Complex.toString(vectorRe[i], vectorIm[i]));
089: return buf.toString();
090: }
091:
092: /**
093: * Returns the real part of this complex vector.
094: */
095: public AbstractDoubleVector real() {
096: return new DoubleVector(vectorRe);
097: }
098:
099: /**
100: * Returns the imaginary part of this complex vector.
101: */
102: public AbstractDoubleVector imag() {
103: return new DoubleVector(vectorIm);
104: }
105:
106: /**
107: * Returns a component of this vector.
108: * @param n index of the vector component
109: * @exception VectorDimensionException If attempting to access an invalid component.
110: */
111: public Complex getComponent(final int n) {
112: if (n >= 0 && n < N)
113: return new Complex(vectorRe[n], vectorIm[n]);
114: else
115: throw new VectorDimensionException(
116: getInvalidComponentMsg(n));
117: }
118:
119: public double getRealComponent(final int n) {
120: if (n >= 0 && n < N)
121: return vectorRe[n];
122: else
123: throw new VectorDimensionException(
124: getInvalidComponentMsg(n));
125: }
126:
127: public double getImagComponent(final int n) {
128: if (n >= 0 && n < N)
129: return vectorIm[n];
130: else
131: throw new VectorDimensionException(
132: getInvalidComponentMsg(n));
133: }
134:
135: /**
136: * Sets the value of a component of this vector.
137: * Should only be used to initialise this vector.
138: * @param n index of the vector component
139: * @param z a complex number
140: * @exception VectorDimensionException If attempting to access an invalid component.
141: */
142: public void setComponent(final int n, final Complex z) {
143: if (n >= 0 && n < N) {
144: vectorRe[n] = z.real();
145: vectorIm[n] = z.imag();
146: } else
147: throw new VectorDimensionException(
148: getInvalidComponentMsg(n));
149: }
150:
151: /**
152: * Sets the value of a component of this vector.
153: * Should only be used to initialise this vector.
154: * @param n index of the vector component
155: * @param x the real part of a complex number
156: * @param y the imaginary part of a complex number
157: * @exception VectorDimensionException If attempting to access an invalid component.
158: */
159: public void setComponent(final int n, final double x, final double y) {
160: if (n >= 0 && n < N) {
161: vectorRe[n] = x;
162: vectorIm[n] = y;
163: } else
164: throw new VectorDimensionException(
165: getInvalidComponentMsg(n));
166: }
167:
168: /**
169: * Returns the l<sup>2</sup>-norm (magnitude).
170: */
171: public double norm() {
172: double answer = vectorRe[0] * vectorRe[0] + vectorIm[0]
173: * vectorIm[0];
174: for (int i = 1; i < N; i++)
175: answer += vectorRe[i] * vectorRe[i] + vectorIm[i]
176: * vectorIm[i];
177: return Math.sqrt(answer);
178: }
179:
180: /**
181: * Returns the l<sup><img border=0 alt="infinity" src="doc-files/infinity.gif"></sup>-norm.
182: */
183: public double infNorm() {
184: double infNorm = vectorRe[0] * vectorRe[0] + vectorIm[0]
185: * vectorIm[0];
186: for (int i = 1; i < N; i++) {
187: double mod = vectorRe[i] * vectorRe[i] + vectorIm[i]
188: * vectorIm[i];
189: if (mod > infNorm)
190: infNorm = mod;
191: }
192: return Math.sqrt(infNorm);
193: }
194:
195: //============
196: // OPERATIONS
197: //============
198:
199: /**
200: * Returns the negative of this vector.
201: */
202: public AbelianGroup.Member negate() {
203: final double arrayRe[] = new double[N];
204: final double arrayIm[] = new double[N];
205: arrayRe[0] = -vectorRe[0];
206: arrayIm[0] = -vectorIm[0];
207: for (int i = 1; i < N; i++) {
208: arrayRe[i] = -vectorRe[i];
209: arrayIm[i] = -vectorIm[i];
210: }
211: return new ComplexVector(arrayRe, arrayIm);
212: }
213:
214: // COMPLEX CONJUGATE
215:
216: /**
217: * Returns the complex conjugate of this vector.
218: */
219: public AbstractComplexVector conjugate() {
220: final double arrayIm[] = new double[N];
221: arrayIm[0] = -vectorIm[0];
222: for (int i = 1; i < N; i++)
223: arrayIm[i] = -vectorIm[i];
224: return new ComplexVector(vectorRe, arrayIm);
225: }
226:
227: // ADDITION
228:
229: /**
230: * Returns the addition of this vector and another.
231: */
232: public AbelianGroup.Member add(final AbelianGroup.Member v) {
233: if (v instanceof ComplexVector)
234: return add((ComplexVector) v);
235: else if (v instanceof DoubleVector)
236: return add((DoubleVector) v);
237: else if (v instanceof IntegerVector)
238: return add((IntegerVector) v);
239: else
240: throw new IllegalArgumentException(
241: "Member class not recognised by this method.");
242: }
243:
244: /**
245: * Returns the addition of this vector and another.
246: * @param v a complex vector
247: * @exception VectorDimensionException If the vectors are different sizes.
248: */
249: public AbstractComplexVector add(final AbstractComplexVector v) {
250: if (v instanceof ComplexVector)
251: return add((ComplexVector) v);
252: else {
253: if (N == v.N) {
254: final double arrayRe[] = new double[N];
255: final double arrayIm[] = new double[N];
256: arrayRe[0] = vectorRe[0] + v.getComponent(0).real();
257: arrayIm[0] = vectorIm[0] + v.getComponent(0).imag();
258: for (int i = 1; i < N; i++) {
259: arrayRe[i] = vectorRe[i] + v.getComponent(i).real();
260: arrayIm[i] = vectorIm[i] + v.getComponent(i).imag();
261: }
262: return new ComplexVector(arrayRe, arrayIm);
263: } else
264: throw new VectorDimensionException(
265: "Vectors are different sizes.");
266: }
267: }
268:
269: public ComplexVector add(final ComplexVector v) {
270: if (N == v.N) {
271: final double arrayRe[] = new double[N];
272: final double arrayIm[] = new double[N];
273: arrayRe[0] = vectorRe[0] + v.vectorRe[0];
274: arrayIm[0] = vectorIm[0] + v.vectorIm[0];
275: for (int i = 1; i < N; i++) {
276: arrayRe[i] = vectorRe[i] + v.vectorRe[i];
277: arrayIm[i] = vectorIm[i] + v.vectorIm[i];
278: }
279: return new ComplexVector(arrayRe, arrayIm);
280: } else
281: throw new VectorDimensionException(
282: "Vectors are different sizes.");
283: }
284:
285: /**
286: * Returns the addition of this vector and another.
287: * @param v a double vector
288: * @exception VectorDimensionException If the vectors are different sizes.
289: */
290: public AbstractComplexVector add(final AbstractDoubleVector v) {
291: if (v instanceof DoubleVector)
292: return add((DoubleVector) v);
293: else {
294: if (N == v.N) {
295: final double arrayRe[] = new double[N];
296: arrayRe[0] = vectorRe[0] + v.getComponent(0);
297: for (int i = 1; i < N; i++)
298: arrayRe[i] = vectorRe[i] + v.getComponent(i);
299: return new ComplexVector(arrayRe, vectorIm);
300: } else
301: throw new VectorDimensionException(
302: "Vectors are different sizes.");
303: }
304: }
305:
306: public ComplexVector add(final DoubleVector v) {
307: if (N == v.N) {
308: final double arrayRe[] = new double[N];
309: arrayRe[0] = vectorRe[0] + v.vector[0];
310: for (int i = 1; i < N; i++)
311: arrayRe[i] = vectorRe[i] + v.vector[i];
312: return new ComplexVector(arrayRe, vectorIm);
313: } else
314: throw new VectorDimensionException(
315: "Vectors are different sizes.");
316: }
317:
318: /**
319: * Returns the addition of this vector and another.
320: * @param v an integer vector
321: * @exception VectorDimensionException If the vectors are different sizes.
322: */
323: public AbstractComplexVector add(final AbstractIntegerVector v) {
324: if (v instanceof IntegerVector)
325: return add((IntegerVector) v);
326: else {
327: if (N == v.N) {
328: final double arrayRe[] = new double[N];
329: arrayRe[0] = vectorRe[0] + v.getComponent(0);
330: for (int i = 1; i < N; i++)
331: arrayRe[i] = vectorRe[i] + v.getComponent(i);
332: return new ComplexVector(arrayRe, vectorIm);
333: } else
334: throw new VectorDimensionException(
335: "Vectors are different sizes.");
336: }
337: }
338:
339: public ComplexVector add(final IntegerVector v) {
340: if (N == v.N) {
341: final double arrayRe[] = new double[N];
342: arrayRe[0] = vectorRe[0] + v.vector[0];
343: for (int i = 1; i < N; i++)
344: arrayRe[i] = vectorRe[i] + v.vector[i];
345: return new ComplexVector(arrayRe, vectorIm);
346: } else
347: throw new VectorDimensionException(
348: "Vectors are different sizes.");
349: }
350:
351: // SUBTRACTION
352:
353: /**
354: * Returns the subtraction of this vector by another.
355: */
356: public AbelianGroup.Member subtract(final AbelianGroup.Member v) {
357: if (v instanceof ComplexVector)
358: return subtract((ComplexVector) v);
359: else if (v instanceof DoubleVector)
360: return subtract((DoubleVector) v);
361: else if (v instanceof IntegerVector)
362: return subtract((IntegerVector) v);
363: else
364: throw new IllegalArgumentException(
365: "Member class not recognised by this method.");
366: }
367:
368: /**
369: * Returns the subtraction of this vector by another.
370: * @param v a complex vector
371: * @exception VectorDimensionException If the vectors are different sizes.
372: */
373: public AbstractComplexVector subtract(final AbstractComplexVector v) {
374: if (v instanceof ComplexVector)
375: return subtract((ComplexVector) v);
376: else {
377: if (N == v.N) {
378: final double arrayRe[] = new double[N];
379: final double arrayIm[] = new double[N];
380: arrayRe[0] = vectorRe[0] - v.getComponent(0).real();
381: arrayIm[0] = vectorIm[0] - v.getComponent(0).imag();
382: for (int i = 1; i < N; i++) {
383: arrayRe[i] = vectorRe[i] - v.getComponent(i).real();
384: arrayIm[i] = vectorIm[i] - v.getComponent(i).imag();
385: }
386: return new ComplexVector(arrayRe, arrayIm);
387: } else
388: throw new VectorDimensionException(
389: "Vectors are different sizes.");
390: }
391: }
392:
393: public ComplexVector subtract(final ComplexVector v) {
394: if (N == v.N) {
395: final double arrayRe[] = new double[N];
396: final double arrayIm[] = new double[N];
397: arrayRe[0] = vectorRe[0] - v.vectorRe[0];
398: arrayIm[0] = vectorIm[0] - v.vectorIm[0];
399: for (int i = 1; i < N; i++) {
400: arrayRe[i] = vectorRe[i] - v.vectorRe[i];
401: arrayIm[i] = vectorIm[i] - v.vectorIm[i];
402: }
403: return new ComplexVector(arrayRe, arrayIm);
404: } else
405: throw new VectorDimensionException(
406: "Vectors are different sizes.");
407: }
408:
409: /**
410: * Returns the subtraction of this vector by another.
411: * @param v a double vector
412: * @exception VectorDimensionException If the vectors are different sizes.
413: */
414: public AbstractComplexVector subtract(final AbstractDoubleVector v) {
415: if (v instanceof DoubleVector)
416: return subtract((DoubleVector) v);
417: else {
418: if (N == v.N) {
419: final double arrayRe[] = new double[N];
420: arrayRe[0] = vectorRe[0] - v.getComponent(0);
421: for (int i = 1; i < N; i++)
422: arrayRe[i] = vectorRe[i] - v.getComponent(i);
423: return new ComplexVector(arrayRe, vectorIm);
424: } else
425: throw new VectorDimensionException(
426: "Vectors are different sizes.");
427: }
428: }
429:
430: public ComplexVector subtract(final DoubleVector v) {
431: if (N == v.N) {
432: final double arrayRe[] = new double[N];
433: arrayRe[0] = vectorRe[0] - v.vector[0];
434: for (int i = 1; i < N; i++)
435: arrayRe[i] = vectorRe[i] - v.vector[i];
436: return new ComplexVector(arrayRe, vectorIm);
437: } else
438: throw new VectorDimensionException(
439: "Vectors are different sizes.");
440: }
441:
442: /**
443: * Returns the subtraction of this vector by another.
444: * @param v an integer vector
445: * @exception VectorDimensionException If the vectors are different sizes.
446: */
447: public AbstractComplexVector subtract(final AbstractIntegerVector v) {
448: if (v instanceof IntegerVector)
449: return subtract((IntegerVector) v);
450: else {
451: if (N == v.N) {
452: final double arrayRe[] = new double[N];
453: arrayRe[0] = vectorRe[0] - v.getComponent(0);
454: for (int i = 1; i < N; i++)
455: arrayRe[i] = vectorRe[i] - v.getComponent(i);
456: return new ComplexVector(arrayRe, vectorIm);
457: } else
458: throw new VectorDimensionException(
459: "Vectors are different sizes.");
460: }
461: }
462:
463: public ComplexVector subtract(final IntegerVector v) {
464: if (N == v.N) {
465: final double arrayRe[] = new double[N];
466: arrayRe[0] = vectorRe[0] - v.vector[0];
467: for (int i = 1; i < N; i++)
468: arrayRe[i] = vectorRe[i] - v.vector[i];
469: return new ComplexVector(arrayRe, vectorIm);
470: } else
471: throw new VectorDimensionException(
472: "Vectors are different sizes.");
473: }
474:
475: // SCALAR MULTIPLICATION
476:
477: /**
478: * Returns the multiplication of this vector by a scalar.
479: */
480: public Module.Member scalarMultiply(Ring.Member x) {
481: if (x instanceof Complex)
482: return scalarMultiply((Complex) x);
483: else if (x instanceof MathDouble)
484: return scalarMultiply(((MathDouble) x).value());
485: else if (x instanceof MathInteger)
486: return scalarMultiply(((MathInteger) x).value());
487: else
488: throw new IllegalArgumentException(
489: "Member class not recognised by this method.");
490: }
491:
492: /**
493: * Returns the multiplication of this vector by a scalar.
494: * @param z a complex number
495: */
496: public AbstractComplexVector scalarMultiply(final Complex z) {
497: final double real = z.real();
498: final double imag = z.imag();
499: final double arrayRe[] = new double[N];
500: final double arrayIm[] = new double[N];
501: arrayRe[0] = vectorRe[0] * real - vectorIm[0] * imag;
502: arrayIm[0] = vectorRe[0] * imag + vectorIm[0] * real;
503: for (int i = 1; i < N; i++) {
504: arrayRe[i] = vectorRe[i] * real - vectorIm[i] * imag;
505: arrayIm[i] = vectorRe[i] * imag + vectorIm[i] * real;
506: }
507: return new ComplexVector(arrayRe, arrayIm);
508: }
509:
510: /**
511: * Returns the multiplication of this vector by a scalar.
512: * @param x a double
513: */
514: public AbstractComplexVector scalarMultiply(final double x) {
515: final double arrayRe[] = new double[N];
516: final double arrayIm[] = new double[N];
517: arrayRe[0] = x * vectorRe[0];
518: arrayIm[0] = x * vectorIm[0];
519: for (int i = 1; i < N; i++) {
520: arrayRe[i] = x * vectorRe[i];
521: arrayIm[i] = x * vectorIm[i];
522: }
523: return new ComplexVector(arrayRe, arrayIm);
524: }
525:
526: // SCALAR DIVISION
527:
528: /**
529: * Returns the division of this vector by a scalar.
530: */
531: public VectorSpace.Member scalarDivide(Field.Member x) {
532: if (x instanceof Complex)
533: return scalarDivide((Complex) x);
534: else if (x instanceof MathDouble)
535: return scalarDivide(((MathDouble) x).value());
536: else
537: throw new IllegalArgumentException(
538: "Member class not recognised by this method.");
539: }
540:
541: /**
542: * Returns the division of this vector by a scalar.
543: * @param z a complex number
544: * @exception ArithmeticException If divide by zero.
545: */
546: public AbstractComplexVector scalarDivide(final Complex z) {
547: final double real = z.real();
548: final double imag = z.imag();
549: final double arrayRe[] = new double[N];
550: final double arrayIm[] = new double[N];
551: final double a, denom;
552: if (Math.abs(real) < Math.abs(imag)) {
553: a = real / imag;
554: denom = real * a + imag;
555: for (int i = 0; i < N; i++) {
556: arrayRe[i] = (vectorRe[i] * a + vectorIm[i]) / denom;
557: arrayIm[i] = (vectorIm[i] * a - vectorRe[i]) / denom;
558: }
559: } else {
560: a = imag / real;
561: denom = real + imag * a;
562: for (int i = 0; i < N; i++) {
563: arrayRe[i] = (vectorRe[i] + vectorIm[i] * a) / denom;
564: arrayIm[i] = (vectorIm[i] - vectorRe[i] * a) / denom;
565: }
566: }
567: return new ComplexVector(arrayRe, arrayIm);
568: }
569:
570: /**
571: * Returns the division of this vector by a scalar.
572: * @param x a double
573: * @exception ArithmeticException If divide by zero.
574: */
575: public AbstractComplexVector scalarDivide(final double x) {
576: final double arrayRe[] = new double[N];
577: final double arrayIm[] = new double[N];
578: arrayRe[0] = vectorRe[0] / x;
579: arrayIm[0] = vectorIm[0] / x;
580: for (int i = 1; i < N; i++) {
581: arrayRe[i] = vectorRe[i] / x;
582: arrayIm[i] = vectorIm[i] / x;
583: }
584: return new ComplexVector(arrayRe, arrayIm);
585: }
586:
587: // SCALAR PRODUCT
588:
589: /**
590: * Returns the scalar product of this vector and another.
591: */
592: public Complex scalarProduct(HilbertSpace.Member v) {
593: if (v instanceof ComplexVector)
594: return scalarProduct((ComplexVector) v);
595: else
596: throw new IllegalArgumentException(
597: "Member class not recognised by this method.");
598: }
599:
600: /**
601: * Returns the scalar product of this vector and another.
602: * @param v a complex vector
603: * @exception VectorDimensionException If the vectors are different sizes.
604: */
605: public Complex scalarProduct(final AbstractComplexVector v) {
606: if (v instanceof ComplexVector)
607: return rawScalarProduct((ComplexVector) v);
608: else {
609: if (N == v.N) {
610: Complex comp = v.getComponent(0);
611: double real = vectorRe[0] * comp.real() + vectorIm[0]
612: * comp.imag();
613: double imag = vectorIm[0] * comp.real() - vectorRe[0]
614: * comp.imag();
615: for (int i = 1; i < N; i++) {
616: comp = v.getComponent(i);
617: real += vectorRe[i] * comp.real() + vectorIm[i]
618: * comp.imag();
619: imag += vectorIm[i] * comp.real() - vectorRe[i]
620: * comp.imag();
621: }
622: return new Complex(real, imag);
623: } else
624: throw new VectorDimensionException(
625: "Vectors are different sizes.");
626: }
627: }
628:
629: private Complex rawScalarProduct(final ComplexVector v) {
630: if (N == v.N) {
631: double real = vectorRe[0] * v.vectorRe[0] + vectorIm[0]
632: * v.vectorIm[0];
633: double imag = vectorIm[0] * v.vectorRe[0] - vectorRe[0]
634: * v.vectorIm[0];
635: for (int i = 1; i < N; i++) {
636: real += vectorRe[i] * v.vectorRe[i] + vectorIm[i]
637: * v.vectorIm[i];
638: imag += vectorIm[i] * v.vectorRe[i] - vectorRe[i]
639: * v.vectorIm[i];
640: }
641: return new Complex(real, imag);
642: } else
643: throw new VectorDimensionException(
644: "Vectors are different sizes.");
645: }
646:
647: // MAP COMPONENTS
648:
649: /**
650: * Applies a function on all the vector components.
651: * @param f a user-defined function
652: * @return a complex vector
653: */
654: public AbstractComplexVector mapComponents(final ComplexMapping f) {
655: final Complex array[] = new Complex[N];
656: array[0] = f.map(vectorRe[0], vectorIm[0]);
657: for (int i = 1; i < N; i++)
658: array[i] = f.map(vectorRe[i], vectorIm[i]);
659: return new ComplexVector(array);
660: }
661: }
|