source: trunk/abcl/src/org/armedbear/lisp/SingleFloat.java @ 11490

Last change on this file since 11490 was 11488, checked in by ehuelsmann, 16 years ago

Add @Override annotations.

Patch by: Douglas Miles

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