source: trunk/abcl/src/org/armedbear/lisp/Complex.java @ 12192

Last change on this file since 12192 was 11954, checked in by ehuelsmann, 16 years ago

Remove workaround for the fact that Math.hypot() was added in Java 1.5:
We require 1.5 and hence don't need to work around it.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 10.0 KB
Line 
1/*
2 * Complex.java
3 *
4 * Copyright (C) 2003-2006 Peter Graves
5 * $Id: Complex.java 11954 2009-05-26 18:34:23Z ehuelsmann $
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 *
21 * As a special exception, the copyright holders of this library give you
22 * permission to link this library with independent modules to produce an
23 * executable, regardless of the license terms of these independent
24 * modules, and to copy and distribute the resulting executable under
25 * terms of your choice, provided that you also meet, for each linked
26 * independent module, the terms and conditions of the license of that
27 * module.  An independent module is a module which is not derived from
28 * or based on this library.  If you modify this library, you may extend
29 * this exception to your version of the library, but you are not
30 * obligated to do so.  If you do not wish to do so, delete this
31 * exception statement from your version.
32 */
33
34package org.armedbear.lisp;
35
36public final class Complex extends LispObject
37{
38  public final LispObject realpart;
39  public final LispObject imagpart;
40
41  private Complex(LispObject realpart, LispObject imagpart)
42  {
43    this.realpart = realpart;
44    this.imagpart = imagpart;
45  }
46
47  public static LispObject getInstance(LispObject realpart,
48                                       LispObject imagpart)
49    throws ConditionThrowable
50  {
51    if (!realpart.realp())
52      return type_error(realpart, Symbol.REAL);
53    if (!imagpart.realp())
54      return type_error(imagpart, Symbol.REAL);
55    if (realpart instanceof DoubleFloat)
56      imagpart = DoubleFloat.coerceToFloat(imagpart);
57    else if (imagpart instanceof DoubleFloat)
58      realpart = DoubleFloat.coerceToFloat(realpart);
59    else if (realpart instanceof SingleFloat)
60      imagpart = SingleFloat.coerceToFloat(imagpart);
61    else if (imagpart instanceof SingleFloat)
62      realpart = SingleFloat.coerceToFloat(realpart);
63    if (imagpart instanceof Fixnum)
64      {
65        if (((Fixnum)imagpart).value == 0)
66          return realpart;
67      }
68    return new Complex(realpart, imagpart);
69  }
70
71  public LispObject getRealPart()
72  {
73    return realpart;
74  }
75
76  public LispObject getImaginaryPart()
77  {
78    return imagpart;
79  }
80
81  @Override
82  public LispObject typeOf()
83  {
84    return Symbol.COMPLEX;
85  }
86
87  @Override
88  public LispObject classOf()
89  {
90    return BuiltInClass.COMPLEX;
91  }
92
93  @Override
94  public LispObject typep(LispObject type) throws ConditionThrowable
95  {
96    if (type == Symbol.COMPLEX)
97      return T;
98    if (type == Symbol.NUMBER)
99      return T;
100    if (type == BuiltInClass.COMPLEX)
101      return T;
102    if (type == BuiltInClass.NUMBER)
103      return T;
104    return super.typep(type);
105  }
106
107  @Override
108  public LispObject NUMBERP()
109  {
110    return T;
111  }
112
113  @Override
114  public boolean numberp()
115  {
116    return true;
117  }
118
119  @Override
120  public boolean eql(LispObject obj)
121  {
122    if (this == obj)
123      return true;
124    if (obj instanceof Complex)
125      {
126        Complex c = (Complex) obj;
127        return realpart.eql(c.realpart) && imagpart.eql(c.imagpart);
128      }
129    return false;
130  }
131
132  @Override
133  public boolean equal(LispObject obj)
134  {
135    return eql(obj);
136  }
137
138  @Override
139  public boolean equalp(LispObject obj) throws ConditionThrowable
140  {
141    if (this == obj)
142      return true;
143    if (obj instanceof Complex)
144      {
145        Complex c = (Complex) obj;
146        return (realpart.isEqualTo(c.realpart) &&
147                imagpart.isEqualTo(c.imagpart));
148      }
149    if (obj.numberp())
150      {
151        // obj is a number, but not complex.
152        if (imagpart instanceof SingleFloat)
153          {
154            if (((SingleFloat)imagpart).value == 0)
155              {
156                if (obj instanceof Fixnum)
157                  return ((Fixnum)obj).value == ((SingleFloat)realpart).value;
158                if (obj instanceof SingleFloat)
159                  return ((SingleFloat)obj).value == ((SingleFloat)realpart).value;
160              }
161          }
162        if (imagpart instanceof DoubleFloat)
163          {
164            if (((DoubleFloat)imagpart).value == 0)
165              {
166                if (obj instanceof Fixnum)
167                  return ((Fixnum)obj).value == ((DoubleFloat)realpart).value;
168                if (obj instanceof DoubleFloat)
169                  return ((DoubleFloat)obj).value == ((DoubleFloat)realpart).value;
170              }
171          }
172      }
173    return false;
174  }
175
176  @Override
177  public final LispObject incr() throws ConditionThrowable
178  {
179    return new Complex(realpart.add(Fixnum.ONE), imagpart);
180  }
181
182  @Override
183  public final LispObject decr() throws ConditionThrowable
184  {
185    return new Complex(realpart.subtract(Fixnum.ONE), imagpart);
186  }
187
188  @Override
189  public LispObject add(LispObject obj) throws ConditionThrowable
190  {
191    if (obj instanceof Complex)
192      {
193        Complex c = (Complex) obj;
194        return getInstance(realpart.add(c.realpart), imagpart.add(c.imagpart));
195      }
196    return getInstance(realpart.add(obj), imagpart);
197  }
198
199  @Override
200  public LispObject subtract(LispObject obj) throws ConditionThrowable
201  {
202    if (obj instanceof Complex)
203      {
204        Complex c = (Complex) obj;
205        return getInstance(realpart.subtract(c.realpart),
206                           imagpart.subtract(c.imagpart));
207      }
208    return getInstance(realpart.subtract(obj), imagpart);
209  }
210
211  @Override
212  public LispObject multiplyBy(LispObject obj) throws ConditionThrowable
213  {
214    if (obj instanceof Complex)
215      {
216        LispObject a = realpart;
217        LispObject b = imagpart;
218        LispObject c = ((Complex)obj).getRealPart();
219        LispObject d = ((Complex)obj).getImaginaryPart();
220        // xy = (ac - bd) + i(ad + bc)
221        // real part = ac - bd
222        // imag part = ad + bc
223        LispObject ac = a.multiplyBy(c);
224        LispObject bd = b.multiplyBy(d);
225        LispObject ad = a.multiplyBy(d);
226        LispObject bc = b.multiplyBy(c);
227        return Complex.getInstance(ac.subtract(bd), ad.add(bc));
228      }
229    return Complex.getInstance(realpart.multiplyBy(obj),
230                               imagpart.multiplyBy(obj));
231  }
232
233  @Override
234  public LispObject divideBy(LispObject obj) throws ConditionThrowable
235  {
236    if (obj instanceof Complex)
237      {
238        LispObject a = realpart;
239        LispObject b = imagpart;
240        LispObject c = ((Complex)obj).getRealPart();
241        LispObject d = ((Complex)obj).getImaginaryPart();
242        LispObject ac = a.multiplyBy(c);
243        LispObject bd = b.multiplyBy(d);
244        LispObject bc = b.multiplyBy(c);
245        LispObject ad = a.multiplyBy(d);
246        LispObject denominator = c.multiplyBy(c).add(d.multiplyBy(d));
247        return Complex.getInstance(ac.add(bd).divideBy(denominator),
248                                   bc.subtract(ad).divideBy(denominator));
249      }
250    return Complex.getInstance(realpart.divideBy(obj),
251                               imagpart.divideBy(obj));
252  }
253
254  @Override
255  public boolean isEqualTo(LispObject obj) throws ConditionThrowable
256  {
257    if (obj instanceof Complex)
258      {
259        Complex c = (Complex) obj;
260        return (realpart.isEqualTo(c.realpart) &&
261                imagpart.isEqualTo(c.imagpart));
262      }
263    if (obj.numberp())
264      {
265        // obj is a number, but not complex.
266        if (imagpart instanceof SingleFloat)
267          {
268            if (((SingleFloat)imagpart).value == 0)
269              {
270                if (obj instanceof Fixnum)
271                  return ((Fixnum)obj).value == ((SingleFloat)realpart).value;
272                if (obj instanceof SingleFloat)
273                  return ((SingleFloat)obj).value == ((SingleFloat)realpart).value;
274                if (obj instanceof DoubleFloat)
275                  return ((DoubleFloat)obj).value == ((SingleFloat)realpart).value;
276              }
277          }
278        if (imagpart instanceof DoubleFloat)
279          {
280            if (((DoubleFloat)imagpart).value == 0)
281              {
282                if (obj instanceof Fixnum)
283                  return ((Fixnum)obj).value == ((DoubleFloat)realpart).value;
284                if (obj instanceof SingleFloat)
285                  return ((SingleFloat)obj).value == ((DoubleFloat)realpart).value;
286                if (obj instanceof DoubleFloat)
287                  return ((DoubleFloat)obj).value == ((DoubleFloat)realpart).value;
288              }
289          }
290        return false;
291      }
292    type_error(obj, Symbol.NUMBER);
293    // Not reached.
294    return false;
295  }
296
297  @Override
298  public boolean isNotEqualTo(LispObject obj) throws ConditionThrowable
299  {
300    return !isEqualTo(obj);
301  }
302
303  @Override
304  public LispObject ABS() throws ConditionThrowable
305  {
306    if (realpart.zerop())
307      return imagpart.ABS();
308    double real = DoubleFloat.coerceToFloat(realpart).value;
309    double imag = DoubleFloat.coerceToFloat(imagpart).value;
310    if (realpart instanceof DoubleFloat)
311      return new DoubleFloat(Math.hypot(real, imag));
312    else
313      return new SingleFloat((float)Math.hypot(real, imag));
314  }
315
316  @Override
317  public boolean zerop() throws ConditionThrowable
318  {
319    return realpart.zerop() && imagpart.zerop();
320  }
321
322  @Override
323  public LispObject COMPLEXP()
324  {
325    return T;
326  }
327
328  @Override
329  public int sxhash()
330  {
331    return (mix(realpart.sxhash(), imagpart.sxhash()) & 0x7fffffff);
332  }
333
334  @Override
335  public int psxhash()
336  {
337    return (mix(realpart.psxhash(), imagpart.psxhash()) & 0x7fffffff);
338  }
339
340  @Override
341  public String writeToString() throws ConditionThrowable
342  {
343    FastStringBuffer sb = new FastStringBuffer("#C(");
344    sb.append(realpart.writeToString());
345    sb.append(' ');
346    sb.append(imagpart.writeToString());
347    sb.append(')');
348    return sb.toString();
349  }
350}
Note: See TracBrowser for help on using the repository browser.