001: // Copyright (c) 1997 Per M.A. Bothner.
002: // This is free software; for terms and warranty disclaimer see ./COPYING.
003:
004: package gnu.math;
005:
006: public abstract class Complex extends Quantity {
007: public Complex number() {
008: return this ;
009: }
010:
011: public boolean isExact() {
012: // Should we return false if unit() != unit.Empty ?
013: return re().isExact() && im().isExact();
014: }
015:
016: private static CComplex imOne;
017: private static CComplex imMinusOne;
018:
019: public static CComplex imOne() {
020: if (imOne == null)
021: imOne = new CComplex(IntNum.zero(), IntNum.one());
022: return imOne;
023: }
024:
025: public static CComplex imMinusOne() {
026: if (imMinusOne == null)
027: imMinusOne = new CComplex(IntNum.zero(), IntNum.minusOne());
028: return imMinusOne;
029: }
030:
031: public double doubleValue() {
032: return re().doubleValue();
033: }
034:
035: public double doubleImagValue() {
036: return im().doubleValue();
037: }
038:
039: public final double doubleRealValue() {
040: return doubleValue();
041: }
042:
043: public long longValue() {
044: return re().longValue();
045: }
046:
047: public static Complex make(RealNum re, RealNum im) {
048: if (im.isZero())
049: return re;
050: if (!re.isExact() || !im.isExact())
051: return new DComplex(re.doubleValue(), im.doubleValue());
052: return new CComplex(re, im);
053: }
054:
055: public static Complex make(double re, double im) {
056: if (im == 0.0)
057: return new DFloNum(re);
058: return new DComplex(re, im);
059: }
060:
061: public static DComplex polar(double r, double t) {
062: return new DComplex(r * Math.cos(t), r * Math.sin(t));
063: }
064:
065: public static DComplex polar(RealNum r, RealNum t) {
066: return polar(r.doubleValue(), t.doubleValue());
067: }
068:
069: public static Complex power(Complex x, Complex y) {
070: if (y instanceof IntNum)
071: return (Complex) x.power((IntNum) y);
072: double x_re = x.doubleRealValue();
073: double x_im = x.doubleImagValue();
074: double y_re = y.doubleRealValue();
075: double y_im = y.doubleImagValue();
076: if (x_im == 0.0
077: && y_im == 0
078: && (x_re >= 0 || Double.isInfinite(x_re) || Double
079: .isNaN(x_re)))
080: return new DFloNum(Math.pow(x_re, y_re));
081: return DComplex.power(x_re, x_im, y_re, y_im);
082: }
083:
084: public Numeric abs() {
085: /* #ifdef JAVA5 */
086: // return new DFloNum(Math.hypot(doubleRealValue(), doubleImagValue()));
087: /* #else */
088: return new DFloNum(DComplex.hypot(doubleRealValue(),
089: doubleImagValue()));
090: /* #endif */
091: }
092:
093: public RealNum angle() {
094: return new DFloNum(Math.atan2(doubleImagValue(),
095: doubleRealValue()));
096: }
097:
098: public static boolean equals(Complex x, Complex y) {
099: return x.re().equals(y.re()) && x.im().equals(x.im());
100: }
101:
102: public boolean equals(Object obj) {
103: if (obj == null || !(obj instanceof Complex))
104: return false;
105: return Complex.equals(this , (Complex) obj);
106: }
107:
108: public static int compare(Complex x, Complex y) {
109: int code = x.im().compare(y.im());
110: if (code != 0)
111: return code;
112: return x.re().compare(y.re());
113: }
114:
115: public int compare(Object obj) {
116: if (!(obj instanceof Complex))
117: return ((Numeric) obj).compareReversed(this );
118: return compare(this , (Complex) obj);
119: }
120:
121: public boolean isZero() {
122: return re().isZero() && im().isZero();
123: }
124:
125: // public abstract Complex neg ();
126:
127: /*
128: Unit unit () { return Unit.Empty; }
129: Dimesions dims() { return unit().dims; }
130: */
131:
132: public String toString(int radix) {
133: // Note: The r4rs read syntax does not allow unsigned pure
134: // imaginary numbers, i.e. you must use +5i, not 5i.
135: // Although our reader allows the sign to be dropped, we always
136: // print it so that the number may be read by any r4rs system.
137: if (im().isZero())
138: return re().toString(radix);
139: String imString = im().toString(radix) + "i";
140: if (imString.charAt(0) != '-')
141: imString = "+" + imString;
142: if (re().isZero())
143: return imString;
144: return re().toString(radix) + imString;
145: }
146:
147: public static Complex neg(Complex x) {
148: return Complex.make(x.re().rneg(), x.im().rneg());
149: }
150:
151: public Numeric neg() {
152: return neg(this );
153: }
154:
155: public static Complex add(Complex x, Complex y, int k) {
156: return Complex.make(RealNum.add(x.re(), y.re(), k), RealNum
157: .add(x.im(), y.im(), k));
158: }
159:
160: public Numeric add(Object y, int k) {
161: if (y instanceof Complex)
162: return add(this , (Complex) y, k);
163: return ((Numeric) y).addReversed(this , k);
164: }
165:
166: public Numeric addReversed(Numeric x, int k) {
167: if (x instanceof Complex)
168: return add((Complex) x, this , k);
169: throw new IllegalArgumentException();
170: }
171:
172: public static Complex times(Complex x, Complex y) {
173: RealNum x_re = x.re();
174: RealNum x_im = x.im();
175: RealNum y_re = y.re();
176: RealNum y_im = y.im();
177: return Complex.make(RealNum.add(RealNum.times(x_re, y_re),
178: RealNum.times(x_im, y_im), -1), RealNum.add(RealNum
179: .times(x_re, y_im), RealNum.times(x_im, y_re), 1));
180: }
181:
182: public Numeric mul(Object y) {
183: if (y instanceof Complex)
184: return times(this , (Complex) y);
185: return ((Numeric) y).mulReversed(this );
186: }
187:
188: public Numeric mulReversed(Numeric x) {
189: if (x instanceof Complex)
190: return times((Complex) x, this );
191: throw new IllegalArgumentException();
192: }
193:
194: public static Complex divide(Complex x, Complex y) {
195: if (!x.isExact() || !y.isExact())
196: return DComplex.div(x.doubleRealValue(), x
197: .doubleImagValue(), y.doubleRealValue(), y
198: .doubleImagValue());
199:
200: RealNum x_re = x.re();
201: RealNum x_im = x.im();
202: RealNum y_re = y.re();
203: RealNum y_im = y.im();
204:
205: RealNum q = RealNum.add(RealNum.times(y_re, y_re), RealNum
206: .times(y_im, y_im), 1);
207: RealNum n = RealNum.add(RealNum.times(x_re, y_re), RealNum
208: .times(x_im, y_im), 1);
209: RealNum d = RealNum.add(RealNum.times(x_im, y_re), RealNum
210: .times(x_re, y_im), -1);
211: return Complex.make(RealNum.divide(n, q), RealNum.divide(d, q));
212: }
213:
214: public Numeric div(Object y) {
215: if (y instanceof Complex)
216: return divide(this , (Complex) y);
217: return ((Numeric) y).divReversed(this );
218: }
219:
220: public Numeric divReversed(Numeric x) {
221: if (x instanceof Complex)
222: return divide((Complex) x, this );
223: throw new IllegalArgumentException();
224: }
225:
226: public Complex exp() {
227: return polar(Math.exp(doubleRealValue()), doubleImagValue());
228: }
229:
230: public Complex log() {
231: return DComplex.log(doubleRealValue(), doubleImagValue());
232: }
233:
234: public Complex sqrt() {
235: return DComplex.sqrt(doubleRealValue(), doubleImagValue());
236: }
237: }
|