source: branches/0.17.x/abcl/src/org/armedbear/lisp/SingleFloat.java

Last change on this file was 12254, checked in by ehuelsmann, 16 years ago

Remove 'throws ConditionThrowable?' method annotations:

it's an unchecked exception now, so no need to declare it thrown.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 21.0 KB
Line 
1/*
2 * SingleFloat.java
3 *
4 * Copyright (C) 2003-2007 Peter Graves
5 * $Id: SingleFloat.java 12254 2009-11-06 20:07:54Z 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 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 java.math.BigInteger;
37
38public final class SingleFloat extends LispObject
39{
40    public static final SingleFloat ZERO       = new SingleFloat(0);
41    public static final SingleFloat MINUS_ZERO = new SingleFloat(-0.0f);
42    public static final SingleFloat ONE        = new SingleFloat(1);
43    public static final SingleFloat MINUS_ONE  = new SingleFloat(-1);
44
45    public static final SingleFloat SINGLE_FLOAT_POSITIVE_INFINITY =
46        new SingleFloat(Float.POSITIVE_INFINITY);
47
48    public static final SingleFloat SINGLE_FLOAT_NEGATIVE_INFINITY =
49        new SingleFloat(Float.NEGATIVE_INFINITY);
50
51    static {
52        Symbol.SINGLE_FLOAT_POSITIVE_INFINITY.initializeConstant(SINGLE_FLOAT_POSITIVE_INFINITY);
53        Symbol.SINGLE_FLOAT_NEGATIVE_INFINITY.initializeConstant(SINGLE_FLOAT_NEGATIVE_INFINITY);
54    }
55
56    public static SingleFloat getInstance(float f) {
57        if (f == 0)
58            return ZERO;
59        else if (f == -0.0f )
60            return MINUS_ZERO;
61        else if (f == 1)
62            return ONE;
63        else if (f == -1)
64            return MINUS_ONE;
65        else
66            return new SingleFloat(f);
67    }
68
69    public final float value;
70
71    public SingleFloat(float value)
72    {
73        this.value = value;
74    }
75
76    @Override
77    public LispObject typeOf()
78    {
79        return Symbol.SINGLE_FLOAT;
80    }
81
82    @Override
83    public LispObject classOf()
84    {
85        return BuiltInClass.SINGLE_FLOAT;
86    }
87
88    @Override
89    public LispObject typep(LispObject typeSpecifier)
90    {
91        if (typeSpecifier == Symbol.FLOAT)
92            return T;
93        if (typeSpecifier == Symbol.REAL)
94            return T;
95        if (typeSpecifier == Symbol.NUMBER)
96            return T;
97        if (typeSpecifier == Symbol.SINGLE_FLOAT)
98            return T;
99        if (typeSpecifier == Symbol.SHORT_FLOAT)
100            return T;
101        if (typeSpecifier == BuiltInClass.FLOAT)
102            return T;
103        if (typeSpecifier == BuiltInClass.SINGLE_FLOAT)
104            return T;
105        return super.typep(typeSpecifier);
106    }
107
108    @Override
109    public LispObject NUMBERP()
110    {
111        return T;
112    }
113
114    @Override
115    public boolean numberp()
116    {
117        return true;
118    }
119
120    @Override
121    public boolean realp()
122    {
123        return true;
124    }
125
126    @Override
127    public boolean eql(LispObject obj)
128    {
129        if (this == obj)
130            return true;
131        if (obj instanceof SingleFloat) {
132            if (value == 0) {
133                // "If an implementation supports positive and negative zeros
134                // as distinct values, then (EQL 0.0 -0.0) returns false."
135                float f = ((SingleFloat)obj).value;
136                int bits = Float.floatToRawIntBits(f);
137                return bits == Float.floatToRawIntBits(value);
138            }
139            if (value == ((SingleFloat)obj).value)
140                return true;
141        }
142        return false;
143    }
144
145    @Override
146    public boolean equal(LispObject obj)
147    {
148        if (this == obj)
149            return true;
150        if (obj instanceof SingleFloat) {
151            if (value == 0) {
152                // same as EQL
153                float f = ((SingleFloat)obj).value;
154                int bits = Float.floatToRawIntBits(f);
155                return bits == Float.floatToRawIntBits(value);
156            }
157            if (value == ((SingleFloat)obj).value)
158                return true;
159        }
160        return false;
161    }
162
163    @Override
164    public boolean equalp(int n)
165    {
166        // "If two numbers are the same under =."
167        return value == n;
168    }
169
170    @Override
171    public boolean equalp(LispObject obj)
172    {
173        if (obj instanceof SingleFloat)
174            return value == ((SingleFloat)obj).value;
175        if (obj instanceof DoubleFloat)
176            return value == ((DoubleFloat)obj).value;
177        if (obj instanceof Fixnum)
178            return value == ((Fixnum)obj).value;
179        if (obj instanceof Bignum)
180            return value == ((Bignum)obj).floatValue();
181        if (obj instanceof Ratio)
182            return value == ((Ratio)obj).floatValue();
183        return false;
184    }
185
186    @Override
187    public LispObject ABS()
188    {
189        if (value > 0)
190            return this;
191        if (value == 0) // 0.0 or -0.0
192            return ZERO;
193        return new SingleFloat(- value);
194    }
195
196    @Override
197    public boolean plusp()
198    {
199        return value > 0;
200    }
201
202    @Override
203    public boolean minusp()
204    {
205        return value < 0;
206    }
207
208    @Override
209    public boolean zerop()
210    {
211        return value == 0;
212    }
213
214    @Override
215    public LispObject FLOATP()
216    {
217        return T;
218    }
219
220    @Override
221    public boolean floatp()
222    {
223        return true;
224    }
225
226    public static double getValue(LispObject obj)
227    {
228        if (obj instanceof SingleFloat)
229            return ((SingleFloat)obj).value;
230        type_error(obj, Symbol.FLOAT);
231        // not reached
232        return 0.0D;
233    }
234
235    public final float getValue()
236    {
237        return value;
238    }
239
240    @Override
241    public float floatValue() {
242        return value;
243    }
244
245    @Override
246    public double doubleValue() {
247        return value;
248    }
249
250    @Override
251    public Object javaInstance()
252    {
253        return Float.valueOf(value);
254    }
255
256    @Override
257    public Object javaInstance(Class c)
258    {
259        String cn = c.getName();
260        if (cn.equals("java.lang.Float") || cn.equals("float"))
261            return Float.valueOf(value);
262        return javaInstance();
263    }
264
265    @Override
266    public final LispObject incr()
267    {
268        return new SingleFloat(value + 1);
269    }
270
271    @Override
272    public final LispObject decr()
273    {
274        return new SingleFloat(value - 1);
275    }
276
277    @Override
278    public LispObject add(LispObject obj)
279    {
280        if (obj instanceof Fixnum)
281            return new SingleFloat(value + ((Fixnum)obj).value);
282        if (obj instanceof SingleFloat)
283            return new SingleFloat(value + ((SingleFloat)obj).value);
284        if (obj instanceof DoubleFloat)
285            return new DoubleFloat(value + ((DoubleFloat)obj).value);
286        if (obj instanceof Bignum)
287            return new SingleFloat(value + ((Bignum)obj).floatValue());
288        if (obj instanceof Ratio)
289            return new SingleFloat(value + ((Ratio)obj).floatValue());
290        if (obj instanceof Complex) {
291            Complex c = (Complex) obj;
292            return Complex.getInstance(add(c.getRealPart()), c.getImaginaryPart());
293        }
294        return error(new TypeError(obj, Symbol.NUMBER));
295    }
296
297    @Override
298    public LispObject negate()
299    {
300        if (value == 0) {
301            int bits = Float.floatToRawIntBits(value);
302            return (bits < 0) ? ZERO : MINUS_ZERO;
303        }
304        return new SingleFloat(-value);
305    }
306
307    @Override
308    public LispObject subtract(LispObject obj)
309    {
310        if (obj instanceof Fixnum)
311            return new SingleFloat(value - ((Fixnum)obj).value);
312        if (obj instanceof SingleFloat)
313            return new SingleFloat(value - ((SingleFloat)obj).value);
314        if (obj instanceof DoubleFloat)
315            return new DoubleFloat(value - ((DoubleFloat)obj).value);
316        if (obj instanceof Bignum)
317            return new SingleFloat(value - ((Bignum)obj).floatValue());
318        if (obj instanceof Ratio)
319            return new SingleFloat(value - ((Ratio)obj).floatValue());
320        if (obj instanceof Complex) {
321            Complex c = (Complex) obj;
322            return Complex.getInstance(subtract(c.getRealPart()),
323                                       ZERO.subtract(c.getImaginaryPart()));
324        }
325        return error(new TypeError(obj, Symbol.NUMBER));
326    }
327
328    @Override
329    public LispObject multiplyBy(LispObject obj)
330    {
331        if (obj instanceof Fixnum)
332            return new SingleFloat(value * ((Fixnum)obj).value);
333        if (obj instanceof SingleFloat)
334            return new SingleFloat(value * ((SingleFloat)obj).value);
335        if (obj instanceof DoubleFloat)
336            return new DoubleFloat(value * ((DoubleFloat)obj).value);
337        if (obj instanceof Bignum)
338            return new SingleFloat(value * ((Bignum)obj).floatValue());
339        if (obj instanceof Ratio)
340            return new SingleFloat(value * ((Ratio)obj).floatValue());
341        if (obj instanceof Complex) {
342            Complex c = (Complex) obj;
343            return Complex.getInstance(multiplyBy(c.getRealPart()),
344                                       multiplyBy(c.getImaginaryPart()));
345        }
346        return error(new TypeError(obj, Symbol.NUMBER));
347    }
348
349    @Override
350    public LispObject divideBy(LispObject obj)
351    {
352        if (obj instanceof Fixnum)
353            return new SingleFloat(value / ((Fixnum)obj).value);
354        if (obj instanceof SingleFloat)
355            return new SingleFloat(value / ((SingleFloat)obj).value);
356        if (obj instanceof DoubleFloat)
357            return new DoubleFloat(value / ((DoubleFloat)obj).value);
358        if (obj instanceof Bignum)
359            return new SingleFloat(value / ((Bignum)obj).floatValue());
360        if (obj instanceof Ratio)
361            return new SingleFloat(value / ((Ratio)obj).floatValue());
362        if (obj instanceof Complex) {
363            Complex c = (Complex) obj;
364            LispObject re = c.getRealPart();
365            LispObject im = c.getImaginaryPart();
366            LispObject denom = re.multiplyBy(re).add(im.multiplyBy(im));
367            LispObject resX = multiplyBy(re).divideBy(denom);
368            LispObject resY =
369                multiplyBy(Fixnum.MINUS_ONE).multiplyBy(im).divideBy(denom);
370            return Complex.getInstance(resX, resY);
371        }
372        return error(new TypeError(obj, Symbol.NUMBER));
373    }
374
375    @Override
376    public boolean isEqualTo(LispObject obj)
377    {
378        if (obj instanceof Fixnum)
379            return rational().isEqualTo(obj);
380        if (obj instanceof SingleFloat)
381            return value == ((SingleFloat)obj).value;
382        if (obj instanceof DoubleFloat)
383            return value == ((DoubleFloat)obj).value;
384        if (obj instanceof Bignum)
385            return rational().isEqualTo(obj);
386        if (obj instanceof Ratio)
387            return rational().isEqualTo(obj);
388        if (obj instanceof Complex)
389            return obj.isEqualTo(this);
390        error(new TypeError(obj, Symbol.NUMBER));
391        // Not reached.
392        return false;
393    }
394
395    @Override
396    public boolean isNotEqualTo(LispObject obj)
397    {
398        return !isEqualTo(obj);
399    }
400
401    @Override
402    public boolean isLessThan(LispObject obj)
403    {
404        if (obj instanceof Fixnum)
405            return rational().isLessThan(obj);
406        if (obj instanceof SingleFloat)
407            return value < ((SingleFloat)obj).value;
408        if (obj instanceof DoubleFloat)
409            return value < ((DoubleFloat)obj).value;
410        if (obj instanceof Bignum)
411            return rational().isLessThan(obj);
412        if (obj instanceof Ratio)
413            return rational().isLessThan(obj);
414        error(new TypeError(obj, Symbol.REAL));
415        // Not reached.
416        return false;
417    }
418
419    @Override
420    public boolean isGreaterThan(LispObject obj)
421    {
422        if (obj instanceof Fixnum)
423            return rational().isGreaterThan(obj);
424        if (obj instanceof SingleFloat)
425            return value > ((SingleFloat)obj).value;
426        if (obj instanceof DoubleFloat)
427            return value > ((DoubleFloat)obj).value;
428        if (obj instanceof Bignum)
429            return rational().isGreaterThan(obj);
430        if (obj instanceof Ratio)
431            return rational().isGreaterThan(obj);
432        error(new TypeError(obj, Symbol.REAL));
433        // Not reached.
434        return false;
435    }
436
437    @Override
438    public boolean isLessThanOrEqualTo(LispObject obj)
439    {
440        if (obj instanceof Fixnum)
441            return rational().isLessThanOrEqualTo(obj);
442        if (obj instanceof SingleFloat)
443            return value <= ((SingleFloat)obj).value;
444        if (obj instanceof DoubleFloat)
445            return value <= ((DoubleFloat)obj).value;
446        if (obj instanceof Bignum)
447            return rational().isLessThanOrEqualTo(obj);
448        if (obj instanceof Ratio)
449            return rational().isLessThanOrEqualTo(obj);
450        error(new TypeError(obj, Symbol.REAL));
451        // Not reached.
452        return false;
453    }
454
455    @Override
456    public boolean isGreaterThanOrEqualTo(LispObject obj)
457    {
458        if (obj instanceof Fixnum)
459            return rational().isGreaterThanOrEqualTo(obj);
460        if (obj instanceof SingleFloat)
461            return value >= ((SingleFloat)obj).value;
462        if (obj instanceof DoubleFloat)
463            return value >= ((DoubleFloat)obj).value;
464        if (obj instanceof Bignum)
465            return rational().isGreaterThanOrEqualTo(obj);
466        if (obj instanceof Ratio)
467            return rational().isGreaterThanOrEqualTo(obj);
468        error(new TypeError(obj, Symbol.REAL));
469        // Not reached.
470        return false;
471    }
472
473    @Override
474    public LispObject truncate(LispObject obj)
475    {
476        // "When rationals and floats are combined by a numerical function,
477        // the rational is first converted to a float of the same format."
478        // 12.1.4.1
479        if (obj instanceof Fixnum) {
480            return truncate(new SingleFloat(((Fixnum)obj).value));
481        }
482        if (obj instanceof Bignum) {
483            return truncate(new SingleFloat(((Bignum)obj).floatValue()));
484        }
485        if (obj instanceof Ratio) {
486            return truncate(new SingleFloat(((Ratio)obj).floatValue()));
487        }
488        if (obj instanceof SingleFloat) {
489            final LispThread thread = LispThread.currentThread();
490            float divisor = ((SingleFloat)obj).value;
491            float quotient = value / divisor;
492            if (value != 0)
493                MathFunctions.OverUnderFlowCheck(quotient);
494            if (quotient >= Integer.MIN_VALUE && quotient <= Integer.MAX_VALUE) {
495                int q = (int) quotient;
496                return thread.setValues(Fixnum.getInstance(q),
497                                        new SingleFloat(value - q * divisor));
498            }
499            // We need to convert the quotient to a bignum.
500            int bits = Float.floatToRawIntBits(quotient);
501            int s = ((bits >> 31) == 0) ? 1 : -1;
502            int e = (int) ((bits >> 23) & 0xff);
503            long m;
504            if (e == 0)
505                m = (bits & 0x7fffff) << 1;
506            else
507                m = (bits & 0x7fffff) | 0x800000;
508            LispObject significand = number(m);
509            Fixnum exponent = Fixnum.getInstance(e - 150);
510            Fixnum sign = Fixnum.getInstance(s);
511            LispObject result = significand;
512            result =
513                result.multiplyBy(MathFunctions.EXPT.execute(Fixnum.TWO, exponent));
514            result = result.multiplyBy(sign);
515            // Calculate remainder.
516            LispObject product = result.multiplyBy(obj);
517            LispObject remainder = subtract(product);
518            return thread.setValues(result, remainder);
519        }
520        if (obj instanceof DoubleFloat) {
521            final LispThread thread = LispThread.currentThread();
522            double divisor = ((DoubleFloat)obj).value;
523            double quotient = value / divisor;
524            if (value != 0)
525                MathFunctions.OverUnderFlowCheck(quotient);
526            if (quotient >= Integer.MIN_VALUE && quotient <= Integer.MAX_VALUE) {
527                int q = (int) quotient;
528                return thread.setValues(Fixnum.getInstance(q),
529                                        new DoubleFloat(value - q * divisor));
530            }
531            // We need to convert the quotient to a bignum.
532            long bits = Double.doubleToRawLongBits((double)quotient);
533            int s = ((bits >> 63) == 0) ? 1 : -1;
534            int e = (int) ((bits >> 52) & 0x7ffL);
535            long m;
536            if (e == 0)
537                m = (bits & 0xfffffffffffffL) << 1;
538            else
539                m = (bits & 0xfffffffffffffL) | 0x10000000000000L;
540            LispObject significand = number(m);
541            Fixnum exponent = Fixnum.getInstance(e - 1075);
542            Fixnum sign = Fixnum.getInstance(s);
543            LispObject result = significand;
544            result =
545                result.multiplyBy(MathFunctions.EXPT.execute(Fixnum.TWO, exponent));
546            result = result.multiplyBy(sign);
547            // Calculate remainder.
548            LispObject product = result.multiplyBy(obj);
549            LispObject remainder = subtract(product);
550            return thread.setValues(result, remainder);
551        }
552        return error(new TypeError(obj, Symbol.REAL));
553    }
554
555    @Override
556    public int hashCode()
557    {
558        return Float.floatToIntBits(value);
559    }
560
561    @Override
562    public int psxhash()
563    {
564        if ((value % 1) == 0)
565            return (((int)value) & 0x7fffffff);
566        else
567            return (hashCode() & 0x7fffffff);
568    }
569
570    @Override
571    public String writeToString()
572    {
573        if (value == Float.POSITIVE_INFINITY) {
574            StringBuffer sb = new StringBuffer("#.");
575            sb.append(Symbol.SINGLE_FLOAT_POSITIVE_INFINITY.writeToString());
576            return sb.toString();
577        }
578        if (value == Float.NEGATIVE_INFINITY) {
579            StringBuffer sb = new StringBuffer("#.");
580            sb.append(Symbol.SINGLE_FLOAT_NEGATIVE_INFINITY.writeToString());
581            return sb.toString();
582        }
583
584        LispThread thread = LispThread.currentThread();
585        boolean printReadably = Symbol.PRINT_READABLY.symbolValue(thread) != NIL;
586
587        if (value != value) {
588            if (printReadably)
589                return "#.(progn \"Comment: create a NaN.\" (/ 0.0s0 0.0s0))";
590            else
591                return "#<SINGLE-FLOAT NaN>";
592        }
593        String s1 = String.valueOf(value);
594        if (printReadably ||
595            !memq(Symbol.READ_DEFAULT_FLOAT_FORMAT.symbolValue(thread),
596                  list(Symbol.SINGLE_FLOAT, Symbol.SHORT_FLOAT)))
597        {
598            if (s1.indexOf('E') >= 0)
599                return s1.replace('E', 'f');
600            else
601                return s1.concat("f0");
602        } else
603            return s1;
604    }
605
606    public LispObject rational()
607    {
608        final int bits = Float.floatToRawIntBits(value);
609        int sign = ((bits >> 31) == 0) ? 1 : -1;
610        int storedExponent = ((bits >> 23) & 0xff);
611        long mantissa;
612        if (storedExponent == 0)
613            mantissa = (bits & 0x7fffff) << 1;
614        else
615            mantissa = (bits & 0x7fffff) | 0x800000;
616        if (mantissa == 0)
617            return Fixnum.ZERO;
618        if (sign < 0)
619            mantissa = -mantissa;
620        // Subtract bias.
621        final int exponent = storedExponent - 127;
622        BigInteger numerator, denominator;
623        if (exponent < 0) {
624            numerator = BigInteger.valueOf(mantissa);
625            denominator = BigInteger.valueOf(1).shiftLeft(23 - exponent);
626        } else {
627            numerator = BigInteger.valueOf(mantissa).shiftLeft(exponent);
628            denominator = BigInteger.valueOf(0x800000); // (ash 1 23)
629        }
630        return number(numerator, denominator);
631    }
632
633    public static SingleFloat coerceToFloat(LispObject obj)
634    {
635        if (obj instanceof Fixnum)
636            return new SingleFloat(((Fixnum)obj).value);
637        if (obj instanceof SingleFloat)
638            return (SingleFloat) obj;
639        if (obj instanceof DoubleFloat)
640            return new SingleFloat((float)((DoubleFloat)obj).value);
641        if (obj instanceof Bignum)
642            return new SingleFloat(((Bignum)obj).floatValue());
643        if (obj instanceof Ratio)
644            return new SingleFloat(((Ratio)obj).floatValue());
645        error(new TypeError("The value " + obj.writeToString() +
646                             " cannot be converted to type SINGLE-FLOAT."));
647        // Not reached.
648        return null;
649    }
650}
Note: See TracBrowser for help on using the repository browser.