KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > armedbear > lisp > MathFunctions


1 /*
2  * Math.java
3  *
4  * Copyright (C) 2004 Peter Graves
5  * $Id: MathFunctions.java,v 1.8 2004/06/10 23:21:19 piso Exp $
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
22 package org.armedbear.lisp;
23
24 import java.lang.reflect.Method JavaDoc;
25
26 public final class MathFunctions extends Lisp
27 {
28     // Java 1.5 provides native implementations of sinh and tanh.
29
private static final boolean isJava15;
30     static {
31         isJava15 = System.getProperty("java.version").startsWith("1.5");
32     }
33
34     // ### sin
35
private static final Primitive1 SIN = new Primitive1("sin", "radians")
36     {
37         public LispObject execute(LispObject arg) throws ConditionThrowable
38         {
39             return sin(arg);
40         }
41     };
42
43     private static LispObject sin(LispObject arg) throws ConditionThrowable
44     {
45         if (arg.realp())
46             return new LispFloat(Math.sin(LispFloat.coerceToFloat(arg).getValue()));
47         if (arg instanceof Complex) {
48             LispObject n = arg.multiplyBy(Complex.getInstance(Fixnum.ZERO,
49                                                               Fixnum.ONE));
50             LispObject result = exp(n);
51             result = result.subtract(exp(n.multiplyBy(Fixnum.MINUS_ONE)));
52             return result.divideBy(Fixnum.TWO.multiplyBy(Complex.getInstance(Fixnum.ZERO,
53                                                                              Fixnum.ONE)));
54         }
55         return signal(new TypeError(arg, Symbol.NUMBER));
56     }
57
58     // ### cos
59
private static final Primitive1 COS = new Primitive1("cos", "radians")
60     {
61         public LispObject execute(LispObject arg) throws ConditionThrowable
62         {
63             return cos(arg);
64         }
65     };
66
67     private static LispObject cos(LispObject arg) throws ConditionThrowable
68     {
69         if (arg.realp())
70             return new LispFloat(Math.cos(LispFloat.coerceToFloat(arg).getValue()));
71         if (arg instanceof Complex) {
72             LispObject n = arg.multiplyBy(Complex.getInstance(Fixnum.ZERO,
73                                                               Fixnum.ONE));
74             LispObject result = exp(n);
75             result = result.add(exp(n.multiplyBy(Fixnum.MINUS_ONE)));
76             return result.divideBy(Fixnum.TWO);
77         }
78         return signal(new TypeError(arg, "number"));
79     }
80
81     // ### tan
82
private static final Primitive1 TAN = new Primitive1("tan", "radians")
83     {
84         public LispObject execute(LispObject arg) throws ConditionThrowable
85         {
86             if (arg.realp())
87                 return new LispFloat(Math.tan(LispFloat.coerceToFloat(arg).value));
88             return sin(arg).divideBy(cos(arg));
89         }
90     };
91
92     // ### asin
93
private static final Primitive1 ASIN = new Primitive1("asin", "number")
94     {
95         public LispObject execute(LispObject arg) throws ConditionThrowable
96         {
97             return asin(arg);
98         }
99     };
100
101     private static LispObject asin(LispObject arg) throws ConditionThrowable
102     {
103         if (arg instanceof Complex) {
104             LispObject im = ((Complex)arg).getImaginaryPart();
105             if (im.zerop())
106                 return Complex.getInstance(asin(((Complex)arg).getRealPart()),
107                                            im);
108         }
109         if (arg instanceof LispFloat)
110             return new LispFloat(Math.asin(((LispFloat)arg).value));
111         LispObject result = arg.multiplyBy(arg);
112         result = Fixnum.ONE.subtract(result);
113         result = sqrt(result);
114         LispObject n = Complex.getInstance(Fixnum.ZERO, Fixnum.ONE);
115         n = n.multiplyBy(arg);
116         result = n.add(result);
117         result = log(result);
118         result = result.multiplyBy(Complex.getInstance(Fixnum.ZERO, Fixnum.MINUS_ONE));
119         if (result instanceof Complex) {
120             if (arg instanceof Complex)
121                 return result;
122             LispObject im = ((Complex)result).getImaginaryPart();
123             if (im.zerop())
124                 return ((Complex)result).getRealPart();
125         }
126         return result;
127     }
128
129     // ### acos
130
private static final Primitive1 ACOS = new Primitive1("acos", "number")
131     {
132         public LispObject execute(LispObject arg) throws ConditionThrowable
133         {
134             return acos(arg);
135         }
136     };
137
138     private static LispObject acos(LispObject arg) throws ConditionThrowable
139     {
140         if (arg instanceof Complex) {
141             LispObject im = ((Complex)arg).getImaginaryPart();
142             if (im.zerop())
143                 return Complex.getInstance(acos(((Complex)arg).getRealPart()),
144                                            im);
145         }
146         if (arg instanceof LispFloat)
147             return new LispFloat(Math.acos(((LispFloat)arg).value));
148         LispObject result = LispFloat.PI.divideBy(Fixnum.TWO);
149         result = result.subtract(asin(arg));
150         if (result instanceof Complex) {
151             if (arg instanceof Complex)
152                 return result;
153             LispObject im = ((Complex)result).getImaginaryPart();
154             if (im.zerop())
155                 return ((Complex)result).getRealPart();
156         }
157         return result;
158     }
159
160     // ### atan
161
private static final Primitive ATAN =
162         new Primitive("atan", "number1 &optional number2")
163     {
164         public LispObject execute(LispObject arg) throws ConditionThrowable
165         {
166             return atan(arg);
167         }
168
169         public LispObject execute(LispObject first, LispObject second)
170             throws ConditionThrowable
171         {
172             return atan(first.divideBy(second));
173         }
174     };
175
176     private static LispObject atan(LispObject arg) throws ConditionThrowable
177     {
178         if (arg instanceof Complex) {
179             LispObject im = ((Complex)arg).getImaginaryPart();
180             if (im.zerop())
181                 return Complex.getInstance(atan(((Complex)arg).getRealPart()),
182                                            im);
183             LispObject result = arg.multiplyBy(arg);
184             result = result.add(Fixnum.ONE);
185             result = Fixnum.ONE.divideBy(result);
186             result = sqrt(result);
187             LispObject n = Complex.getInstance(Fixnum.ZERO, Fixnum.ONE);
188             n = n.multiplyBy(arg);
189             n = n.add(Fixnum.ONE);
190             result = n.multiplyBy(result);
191             result = log(result);
192             result = result.multiplyBy(Complex.getInstance(Fixnum.ZERO, Fixnum.MINUS_ONE));
193             return result;
194         }
195         return new LispFloat(Math.atan(LispFloat.coerceToFloat(arg).getValue()));
196     }
197
198     // ### sinh
199
private static final Primitive1 SINH = new Primitive1("sinh", "number")
200     {
201         public LispObject execute(LispObject arg) throws ConditionThrowable
202         {
203             return sinh(arg);
204         }
205     };
206
207     private static Method JavaDoc sinhMethod = null;
208
209     private static LispObject sinh(LispObject arg) throws ConditionThrowable
210     {
211         if (arg instanceof Complex) {
212             LispObject im = ((Complex)arg).getImaginaryPart();
213             if (im.zerop())
214                 return Complex.getInstance(sinh(((Complex)arg).getRealPart()),
215                                            im);
216         }
217         if (isJava15 && arg instanceof LispFloat) {
218             try {
219                 if (sinhMethod == null) {
220                     Class JavaDoc c = Class.forName("java.lang.Math");
221                     Class JavaDoc[] parameterTypes = new Class JavaDoc[1];
222                     parameterTypes[0] = Double.TYPE;
223                     sinhMethod = c.getMethod("sinh", parameterTypes);
224                 }
225                 if (sinhMethod != null) {
226                     Object JavaDoc[] args;
227                     args = new Object JavaDoc[1];
228                     args[0] = new Double JavaDoc(((LispFloat)arg).value);
229                     Double JavaDoc d = (Double JavaDoc) sinhMethod.invoke(null, args);
230                     return new LispFloat(d.doubleValue());
231                 }
232             }
233             catch (Throwable JavaDoc t) {
234                 Debug.trace(t);
235                 // Fall through...
236
}
237         }
238         LispObject result = exp(arg);
239         result = result.subtract(exp(arg.multiplyBy(Fixnum.MINUS_ONE)));
240         result = result.divideBy(Fixnum.TWO);
241         if (result instanceof Complex) {
242             if (arg instanceof Complex)
243                 return result;
244             LispObject im = ((Complex)result).getImaginaryPart();
245             if (im.zerop())
246                 return ((Complex)result).getRealPart();
247         }
248         return result;
249     }
250
251     // ### cosh
252
private static final Primitive1 COSH = new Primitive1("cosh", "number")
253     {
254         public LispObject execute(LispObject arg) throws ConditionThrowable
255         {
256             return cosh(arg);
257         }
258     };
259
260     private static Method JavaDoc coshMethod = null;
261
262     private static LispObject cosh(LispObject arg) throws ConditionThrowable
263     {
264         if (arg instanceof Complex) {
265             LispObject im = ((Complex)arg).getImaginaryPart();
266             if (im.zerop())
267                 return Complex.getInstance(cosh(((Complex)arg).getRealPart()),
268                                            im);
269         }
270         if (isJava15 && arg instanceof LispFloat) {
271             try {
272                 if (coshMethod == null) {
273                     Class JavaDoc c = Class.forName("java.lang.Math");
274                     Class JavaDoc[] parameterTypes = new Class JavaDoc[1];
275                     parameterTypes[0] = Double.TYPE;
276                     coshMethod = c.getMethod("cosh", parameterTypes);
277                 }
278                 if (coshMethod != null) {
279                     Object JavaDoc[] args;
280                     args = new Object JavaDoc[1];
281                     args[0] = new Double JavaDoc(((LispFloat)arg).value);
282                     Double JavaDoc d = (Double JavaDoc) coshMethod.invoke(null, args);
283                     return new LispFloat(d.doubleValue());
284                 }
285             }
286             catch (Throwable JavaDoc t) {
287                 Debug.trace(t);
288                 // Fall through...
289
}
290         }
291         LispObject result = exp(arg);
292         result = result.add(exp(arg.multiplyBy(Fixnum.MINUS_ONE)));
293         result = result.divideBy(Fixnum.TWO);
294         if (result instanceof Complex) {
295             if (arg instanceof Complex)
296                 return result;
297             LispObject im = ((Complex)result).getImaginaryPart();
298             if (im.zerop())
299                 return ((Complex)result).getRealPart();
300         }
301         return result;
302     }
303
304     private static Method JavaDoc tanhMethod = null;
305
306     // ### tanh
307
private static final Primitive1 TANH = new Primitive1("tanh", "number")
308     {
309         public LispObject execute(LispObject arg) throws ConditionThrowable
310         {
311             if (isJava15 && arg instanceof LispFloat) {
312                 try {
313                     if (tanhMethod == null) {
314                         Class JavaDoc c = Class.forName("java.lang.Math");
315                         Class JavaDoc[] parameterTypes = new Class JavaDoc[1];
316                         parameterTypes[0] = Double.TYPE;
317                         tanhMethod = c.getMethod("tanh", parameterTypes);
318                     }
319                     if (tanhMethod != null) {
320                         Object JavaDoc[] args;
321                         args = new Object JavaDoc[1];
322                         args[0] = new Double JavaDoc(((LispFloat)arg).value);
323                         Double JavaDoc d = (Double JavaDoc) tanhMethod.invoke(null, args);
324                         return new LispFloat(d.doubleValue());
325                     }
326                 }
327                 catch (Throwable JavaDoc t) {
328                     Debug.trace(t);
329                     // Fall through...
330
}
331             }
332             return sinh(arg).divideBy(cosh(arg));
333         }
334     };
335
336     // ### asinh
337
private static final Primitive1 ASINH = new Primitive1("asinh", "number")
338     {
339         public LispObject execute(LispObject arg) throws ConditionThrowable
340         {
341             return asinh(arg);
342         }
343     };
344
345     private static LispObject asinh(LispObject arg) throws ConditionThrowable
346     {
347         if (arg instanceof Complex) {
348             LispObject im = ((Complex)arg).getImaginaryPart();
349             if (im.zerop())
350                 return Complex.getInstance(asinh(((Complex)arg).getRealPart()),
351                                            im);
352         }
353         LispObject result = arg.multiplyBy(arg);
354         result = Fixnum.ONE.add(result);
355         result = sqrt(result);
356         result = result.add(arg);
357         result = log(result);
358         if (result instanceof Complex) {
359             if (arg instanceof Complex)
360                 return result;
361             LispObject im = ((Complex)result).getImaginaryPart();
362             if (im.zerop())
363                 return ((Complex)result).getRealPart();
364         }
365         return result;
366     }
367
368     // ### acosh
369
private static final Primitive1 ACOSH = new Primitive1("acosh", "number")
370     {
371         public LispObject execute(LispObject arg) throws ConditionThrowable
372         {
373             return acosh(arg);
374         }
375     };
376
377     private static LispObject acosh(LispObject arg) throws ConditionThrowable
378     {
379         if (arg instanceof Complex) {
380             LispObject im = ((Complex)arg).getImaginaryPart();
381             if (im.zerop())
382                 return Complex.getInstance(acosh(((Complex)arg).getRealPart()),
383                                            im);
384         }
385         LispObject n1 = arg.add(Fixnum.ONE);
386         n1 = n1.divideBy(Fixnum.TWO);
387         n1 = sqrt(n1);
388         LispObject n2 = arg.subtract(Fixnum.ONE);
389         n2 = n2.divideBy(Fixnum.TWO);
390         n2 = sqrt(n2);
391         LispObject result = n1.add(n2);
392         result = log(result);
393         result = result.multiplyBy(Fixnum.TWO);
394         if (result instanceof Complex) {
395             if (arg instanceof Complex)
396                 return result;
397             LispObject im = ((Complex)result).getImaginaryPart();
398             if (im.zerop())
399                 return ((Complex)result).getRealPart();
400         }
401         return result;
402     }
403
404     // ### atanh
405
private static final Primitive1 ATANH = new Primitive1("atanh", "number")
406     {
407         public LispObject execute(LispObject arg) throws ConditionThrowable
408         {
409             return atanh(arg);
410         }
411     };
412
413     private static LispObject atanh(LispObject arg) throws ConditionThrowable
414     {
415         if (arg instanceof Complex) {
416             LispObject im = ((Complex)arg).getImaginaryPart();
417             if (im.zerop())
418                 return Complex.getInstance(atanh(((Complex)arg).getRealPart()),
419                                            im);
420         }
421         LispObject n1 = log(Fixnum.ONE.add(arg));
422         LispObject n2 = log(Fixnum.ONE.subtract(arg));
423         LispObject result = n1.subtract(n2);
424         result = result.divideBy(Fixnum.TWO);
425         if (result instanceof Complex) {
426             if (arg instanceof Complex)
427                 return result;
428             LispObject im = ((Complex)result).getImaginaryPart();
429             if (im.zerop())
430                 return ((Complex)result).getRealPart();
431         }
432         return result;
433     }
434
435     // ### exp
436
private static final Primitive1 EXP = new Primitive1("exp", "number")
437     {
438         public LispObject execute(LispObject arg) throws ConditionThrowable
439         {
440             return exp(arg);
441         }
442     };
443
444     private static LispObject exp(LispObject arg) throws ConditionThrowable
445     {
446         if (arg instanceof LispFloat)
447             return new LispFloat(Math.exp(((LispFloat)arg).value));
448         if (arg.realp())
449             return new LispFloat(Math.exp(LispFloat.coerceToFloat(arg).value));
450         if (arg instanceof Complex) {
451             Complex argc = (Complex)arg;
452             double re = LispFloat.coerceToFloat(argc.getRealPart()).getValue();
453             double im = LispFloat.coerceToFloat(argc.getImaginaryPart()).getValue();
454             LispFloat resX = new LispFloat(Math.exp(re) * Math.cos(im));
455             LispFloat resY = new LispFloat(Math.exp(re) * Math.sin(im));
456             return Complex.getInstance(resX, resY);
457         }
458         return signal(new TypeError(arg, Symbol.NUMBER));
459     }
460
461     // ### sqrt
462
private static final Primitive1 SQRT = new Primitive1("sqrt", "number")
463     {
464         public LispObject execute(LispObject arg) throws ConditionThrowable
465         {
466             return sqrt(arg);
467         }
468     };
469
470     private static final LispObject sqrt(LispObject obj) throws ConditionThrowable
471     {
472         if (obj.realp() && !obj.minusp()) { // returning real
473
LispFloat f = LispFloat.coerceToFloat(obj);
474             return new LispFloat(Math.sqrt(f.getValue()));
475         } else { // returning Complex
476
if (obj.realp()) {
477                 return Complex.getInstance(new LispFloat(0),
478                                            sqrt(Fixnum.ZERO.subtract(obj)));
479             } else if (obj instanceof Complex) {
480                 return exp(log(obj).divideBy(Fixnum.TWO));
481             }
482         }
483         signal(new TypeError(obj, "number"));
484         return NIL;
485     }
486
487     // ### log
488
private static final Primitive LOG = new Primitive("log", "number &optional base")
489     {
490         public LispObject execute(LispObject arg) throws ConditionThrowable
491         {
492             return log(arg);
493         }
494         public LispObject execute(LispObject number, LispObject base)
495             throws ConditionThrowable
496         {
497             return log(number).divideBy(log(base));
498         }
499     };
500
501     private static final LispObject log(LispObject obj) throws ConditionThrowable
502     {
503         if (obj.realp() && !obj.minusp()) { // real value
504
if (obj instanceof Fixnum)
505                 return new LispFloat(Math.log(((Fixnum)obj).getValue()));
506             if (obj instanceof Bignum)
507                 return new LispFloat(Math.log(((Bignum)obj).floatValue()));
508             if (obj instanceof Ratio)
509                 return new LispFloat(Math.log(((Ratio)obj).floatValue()));
510             if (obj instanceof LispFloat)
511                 return new LispFloat(Math.log(((LispFloat)obj).getValue()));
512         } else { // returning Complex
513
LispFloat re, im, phase, abs;
514             if (obj.realp() && obj.minusp()) {
515                 re = LispFloat.coerceToFloat(obj);
516                 abs = new LispFloat(Math.abs(re.getValue()));
517                 phase = new LispFloat(Math.PI);
518                 return Complex.getInstance(new LispFloat(Math.log(abs.getValue())), phase);
519             } else if (obj instanceof Complex) {
520                 re = LispFloat.coerceToFloat(((Complex)obj).getRealPart());
521                 im = LispFloat.coerceToFloat(((Complex)obj).getImaginaryPart());
522                 phase = new LispFloat(Math.atan2(im.getValue(), re.getValue())); // atan(y/x)
523
abs = (LispFloat)((Complex)obj).ABS();
524                 return Complex.getInstance(new LispFloat(Math.log(abs.getValue())), phase);
525             }
526         }
527         signal(new TypeError(obj, "number"));
528         return NIL;
529     }
530 }
531
Popular Tags