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

Last change on this file was 12431, checked in by Mark Evenson, 15 years ago

Replace FastStringBuffer? with java.lang.StringBuilder?.

Phil Hudson suggested in Feburary 2009 that "[FastStringBuffer?] should
be removed with all references to it replaced with
java.lang.StringBuilder? once enough confidence in this change has been
gained." After almost a year of using FastStringBuffer? as a delagate
for StringBuilder?, that confidence has indeed been gained.

One subtlety for use of StringBuilder?: there is no

StringBuilder?(char)

constructor, so use

StringBuilder?(String.valueOf(c))

to construct a new StringBuilder? containing a single char. Otherwise
that char will get promoted to an int, and you will invoke

StringBuilder?(int capacity)

which will "swallow" the first character that you thought you were adding.

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