source: branches/1.1.x/src/org/armedbear/lisp/Complex.java

Last change on this file was 13440, checked in by ehuelsmann, 13 years ago

Rename writeToString() to printObject() since that's what it's being used for.
Additionally, create princToString() for use in error messages, making the

required replacement where appropriate.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 9.9 KB
Line 
1/*
2 * Complex.java
3 *
4 * Copyright (C) 2003-2006 Peter Graves
5 * $Id: Complex.java 13440 2011-08-05 21:25:10Z 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
36import static org.armedbear.lisp.Lisp.*;
37
38public final class Complex extends LispObject
39{
40  public final LispObject realpart;
41  public final LispObject imagpart;
42
43  private Complex(LispObject realpart, LispObject imagpart)
44  {
45    this.realpart = realpart;
46    this.imagpart = imagpart;
47  }
48
49  public static LispObject getInstance(LispObject realpart,
50                                       LispObject imagpart)
51
52  {
53    if (!realpart.realp())
54      return type_error(realpart, Symbol.REAL);
55    if (!imagpart.realp())
56      return type_error(imagpart, Symbol.REAL);
57    if (realpart instanceof DoubleFloat)
58      imagpart = DoubleFloat.coerceToFloat(imagpart);
59    else if (imagpart instanceof DoubleFloat)
60      realpart = DoubleFloat.coerceToFloat(realpart);
61    else if (realpart instanceof SingleFloat)
62      imagpart = SingleFloat.coerceToFloat(imagpart);
63    else if (imagpart instanceof SingleFloat)
64      realpart = SingleFloat.coerceToFloat(realpart);
65    if (imagpart instanceof Fixnum)
66      {
67        if (((Fixnum)imagpart).value == 0)
68          return realpart;
69      }
70    return new Complex(realpart, imagpart);
71  }
72
73  public LispObject getRealPart()
74  {
75    return realpart;
76  }
77
78  public LispObject getImaginaryPart()
79  {
80    return imagpart;
81  }
82
83  /** Coerces the complex parts into DoubleFloats
84   *
85   * @return a new complex with double-float real and imaginary parts
86   */
87  public LispObject coerceToDoubleFloat() {
88      return getInstance(DoubleFloat.coerceToFloat(realpart),
89                         DoubleFloat.coerceToFloat(imagpart));
90  }
91
92  @Override
93  public LispObject typeOf()
94  {
95    return Symbol.COMPLEX;
96  }
97
98  @Override
99  public LispObject classOf()
100  {
101    return BuiltInClass.COMPLEX;
102  }
103
104  @Override
105  public LispObject typep(LispObject type)
106  {
107    if (type == Symbol.COMPLEX)
108      return T;
109    if (type == Symbol.NUMBER)
110      return T;
111    if (type == BuiltInClass.COMPLEX)
112      return T;
113    if (type == BuiltInClass.NUMBER)
114      return T;
115    return super.typep(type);
116  }
117
118  @Override
119  public boolean numberp()
120  {
121    return true;
122  }
123
124  @Override
125  public boolean eql(LispObject obj)
126  {
127    if (this == obj)
128      return true;
129    if (obj instanceof Complex)
130      {
131        Complex c = (Complex) obj;
132        return realpart.eql(c.realpart) && imagpart.eql(c.imagpart);
133      }
134    return false;
135  }
136
137  @Override
138  public boolean equal(LispObject obj)
139  {
140    return eql(obj);
141  }
142
143  @Override
144  public boolean equalp(LispObject obj)
145  {
146    if (this == obj)
147      return true;
148    if (obj instanceof Complex)
149      {
150        Complex c = (Complex) obj;
151        return (realpart.isEqualTo(c.realpart) &&
152                imagpart.isEqualTo(c.imagpart));
153      }
154    if (obj.numberp())
155      {
156        // obj is a number, but not complex.
157        if (imagpart instanceof SingleFloat)
158          {
159            if (((SingleFloat)imagpart).value == 0)
160              {
161                if (obj instanceof Fixnum)
162                  return ((Fixnum)obj).value == ((SingleFloat)realpart).value;
163                if (obj instanceof SingleFloat)
164                  return ((SingleFloat)obj).value == ((SingleFloat)realpart).value;
165              }
166          }
167        if (imagpart instanceof DoubleFloat)
168          {
169            if (((DoubleFloat)imagpart).value == 0)
170              {
171                if (obj instanceof Fixnum)
172                  return ((Fixnum)obj).value == ((DoubleFloat)realpart).value;
173                if (obj instanceof DoubleFloat)
174                  return ((DoubleFloat)obj).value == ((DoubleFloat)realpart).value;
175              }
176          }
177      }
178    return false;
179  }
180
181  @Override
182  public final LispObject incr()
183  {
184    return new Complex(realpart.add(Fixnum.ONE), imagpart);
185  }
186
187  @Override
188  public final LispObject decr()
189  {
190    return new Complex(realpart.subtract(Fixnum.ONE), imagpart);
191  }
192
193  @Override
194  public LispObject add(LispObject obj)
195  {
196    if (obj instanceof Complex)
197      {
198        Complex c = (Complex) obj;
199        return getInstance(realpart.add(c.realpart), imagpart.add(c.imagpart));
200      }
201    return getInstance(realpart.add(obj), imagpart);
202  }
203
204  @Override
205  public LispObject subtract(LispObject obj)
206  {
207    if (obj instanceof Complex)
208      {
209        Complex c = (Complex) obj;
210        return getInstance(realpart.subtract(c.realpart),
211                           imagpart.subtract(c.imagpart));
212      }
213    return getInstance(realpart.subtract(obj), imagpart);
214  }
215
216  @Override
217  public LispObject multiplyBy(LispObject obj)
218  {
219    if (obj instanceof Complex)
220      {
221        LispObject a = realpart;
222        LispObject b = imagpart;
223        LispObject c = ((Complex)obj).getRealPart();
224        LispObject d = ((Complex)obj).getImaginaryPart();
225        // xy = (ac - bd) + i(ad + bc)
226        // real part = ac - bd
227        // imag part = ad + bc
228        LispObject ac = a.multiplyBy(c);
229        LispObject bd = b.multiplyBy(d);
230        LispObject ad = a.multiplyBy(d);
231        LispObject bc = b.multiplyBy(c);
232        return Complex.getInstance(ac.subtract(bd), ad.add(bc));
233      }
234    return Complex.getInstance(realpart.multiplyBy(obj),
235                               imagpart.multiplyBy(obj));
236  }
237
238  @Override
239  public LispObject divideBy(LispObject obj)
240  {
241    if (obj instanceof Complex)
242      {
243        LispObject a = realpart;
244        LispObject b = imagpart;
245        LispObject c = ((Complex)obj).getRealPart();
246        LispObject d = ((Complex)obj).getImaginaryPart();
247        LispObject ac = a.multiplyBy(c);
248        LispObject bd = b.multiplyBy(d);
249        LispObject bc = b.multiplyBy(c);
250        LispObject ad = a.multiplyBy(d);
251        LispObject denominator = c.multiplyBy(c).add(d.multiplyBy(d));
252        return Complex.getInstance(ac.add(bd).divideBy(denominator),
253                                   bc.subtract(ad).divideBy(denominator));
254      }
255    return Complex.getInstance(realpart.divideBy(obj),
256                               imagpart.divideBy(obj));
257  }
258
259  @Override
260  public boolean isEqualTo(LispObject obj)
261  {
262    if (obj instanceof Complex)
263      {
264        Complex c = (Complex) obj;
265        return (realpart.isEqualTo(c.realpart) &&
266                imagpart.isEqualTo(c.imagpart));
267      }
268    if (obj.numberp())
269      {
270        // obj is a number, but not complex.
271        if (imagpart instanceof SingleFloat)
272          {
273            if (((SingleFloat)imagpart).value == 0)
274              {
275                if (obj instanceof Fixnum)
276                  return ((Fixnum)obj).value == ((SingleFloat)realpart).value;
277                if (obj instanceof SingleFloat)
278                  return ((SingleFloat)obj).value == ((SingleFloat)realpart).value;
279                if (obj instanceof DoubleFloat)
280                  return ((DoubleFloat)obj).value == ((SingleFloat)realpart).value;
281              }
282          }
283        if (imagpart instanceof DoubleFloat)
284          {
285            if (((DoubleFloat)imagpart).value == 0)
286              {
287                if (obj instanceof Fixnum)
288                  return ((Fixnum)obj).value == ((DoubleFloat)realpart).value;
289                if (obj instanceof SingleFloat)
290                  return ((SingleFloat)obj).value == ((DoubleFloat)realpart).value;
291                if (obj instanceof DoubleFloat)
292                  return ((DoubleFloat)obj).value == ((DoubleFloat)realpart).value;
293              }
294          }
295        return false;
296      }
297    type_error(obj, Symbol.NUMBER);
298    // Not reached.
299    return false;
300  }
301
302  @Override
303  public boolean isNotEqualTo(LispObject obj)
304  {
305    return !isEqualTo(obj);
306  }
307
308  @Override
309  public LispObject ABS()
310  {
311    if (realpart.zerop())
312      return imagpart.ABS();
313    double real = DoubleFloat.coerceToFloat(realpart).value;
314    double imag = DoubleFloat.coerceToFloat(imagpart).value;
315    if (realpart instanceof DoubleFloat)
316      return new DoubleFloat(Math.hypot(real, imag));
317    else
318      return new SingleFloat((float)Math.hypot(real, imag));
319  }
320
321  @Override
322  public boolean zerop()
323  {
324    return realpart.zerop() && imagpart.zerop();
325  }
326
327  @Override
328  public LispObject COMPLEXP()
329  {
330    return T;
331  }
332
333  @Override
334  public int sxhash()
335  {
336    return (mix(realpart.sxhash(), imagpart.sxhash()) & 0x7fffffff);
337  }
338
339  @Override
340  public int psxhash()
341  {
342    return (mix(realpart.psxhash(), imagpart.psxhash()) & 0x7fffffff);
343  }
344
345  @Override
346  public String printObject()
347  {
348    StringBuilder sb = new StringBuilder("#C(");
349    sb.append(realpart.printObject());
350    sb.append(' ');
351    sb.append(imagpart.printObject());
352    sb.append(')');
353    return sb.toString();
354  }
355}
Note: See TracBrowser for help on using the repository browser.