Changeset 11729
- Timestamp:
- 04/04/09 21:57:58 (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/abcl/src/org/armedbear/lisp/MathFunctions.java
r11728 r11729 748 748 if (base.zerop()) 749 749 return base; 750 if (power instanceof Fixnum) { 751 if (base.rationalp()) 752 return intexp(base, power); 753 LispObject result; 754 if (base instanceof SingleFloat) 755 result = SingleFloat.ONE; 756 else if (base instanceof DoubleFloat) 757 result = DoubleFloat.ONE; 758 else 759 // base is complex 760 result = Fixnum.ONE; 761 int pow = ((Fixnum)power).value; 762 if (pow > 0) { 763 LispObject term = base; 764 while (pow != 0) { 765 if ((pow & 1) == 1) 766 result = result.multiplyBy(term); 767 768 term = term.multiplyBy(term); 769 pow = pow >> 1; 770 } 771 } else if (pow < 0) { 772 LispObject term = base; 773 pow = -pow; 774 while (pow != 0) { 775 if ((pow & 1) == 1) 776 result = result.divideBy(term); 777 778 term = term.multiplyBy(term); 779 pow = pow >> 1; 780 } 781 } 782 if (TRAP_OVERFLOW) { 783 if (result instanceof SingleFloat) 784 if (Float.isInfinite(((SingleFloat)result).value)) 785 return error(new FloatingPointOverflow(NIL)); 786 if (result instanceof DoubleFloat) 787 if (Double.isInfinite(((DoubleFloat)result).value)) 788 return error(new FloatingPointOverflow(NIL)); 789 } 790 if (TRAP_UNDERFLOW) { 791 if (result.zerop()) 792 return error(new FloatingPointUnderflow(NIL)); 793 } 794 return result; 795 } 796 if (base instanceof Fixnum && power instanceof Bignum) 797 return ((Fixnum)base).pow(power); 750 if (base.isEqualTo(1)) 751 return base; 752 753 if ((power instanceof Fixnum 754 || power instanceof Bignum) 755 && (base.rationalp() 756 || (base instanceof Complex 757 && ((Complex)base).realpart.rationalp()))) { 758 // exact math version 759 return intexp(base, power); 760 } 761 // for anything not a rational or complex rational, use 762 // float approximation. 798 763 if (base instanceof Complex || power instanceof Complex) 799 764 return exp(power.multiplyBy(log(base))); … … 802 767 if (base instanceof Fixnum) 803 768 x = ((Fixnum)base).value; 769 else if (base instanceof Bignum) 770 x = ((Bignum)base).doubleValue(); 804 771 else if (base instanceof Ratio) 805 772 x = ((Ratio)base).doubleValue(); … … 811 778 return error(new LispError("EXPT: unsupported case: base is of type " + 812 779 base.typeOf().writeToString())); 813 if (power instanceof Ratio) 780 781 if (power instanceof Fixnum) 782 y = ((Fixnum)power).value; 783 else if (power instanceof Bignum) 784 y = ((Bignum)power).doubleValue(); 785 else if (power instanceof Ratio) 814 786 y = ((Ratio)power).doubleValue(); 815 787 else if (power instanceof SingleFloat) … … 827 799 double imagPart = r * Math.sin(y * Math.PI); 828 800 if (base instanceof DoubleFloat || power instanceof DoubleFloat) 829 return Complex.getInstance(new DoubleFloat(realPart), 830 new DoubleFloat(imagPart)); 801 return Complex 802 .getInstance(OverUnderFlowCheck(new DoubleFloat(realPart)), 803 OverUnderFlowCheck(new DoubleFloat(imagPart))); 831 804 else 832 return Complex.getInstance(new SingleFloat((float)realPart), 833 new SingleFloat((float)imagPart)); 805 return Complex 806 .getInstance(OverUnderFlowCheck(new SingleFloat((float)realPart)), 807 OverUnderFlowCheck(new SingleFloat((float)imagPart))); 834 808 } 835 809 } 836 810 if (base instanceof DoubleFloat || power instanceof DoubleFloat) 837 return new DoubleFloat(r);811 return OverUnderFlowCheck(new DoubleFloat(r)); 838 812 else 839 return new SingleFloat((float)r); 840 } 841 }; 813 return OverUnderFlowCheck(new SingleFloat((float)r)); 814 } 815 }; 816 817 /** Checks number for over- or underflow values. 818 * 819 * @param number 820 * @return number or signals an appropriate error 821 * @throws org.armedbear.lisp.ConditionThrowable 822 */ 823 private final static LispObject OverUnderFlowCheck(LispObject number) 824 throws ConditionThrowable 825 { 826 if (number instanceof Complex) { 827 OverUnderFlowCheck(((Complex)number).realpart); 828 OverUnderFlowCheck(((Complex)number).imagpart); 829 return number; 830 } 831 832 if (TRAP_OVERFLOW) { 833 if (number instanceof SingleFloat) 834 if (Float.isInfinite(((SingleFloat)number).value)) 835 return error(new FloatingPointOverflow(NIL)); 836 if (number instanceof DoubleFloat) 837 if (Double.isInfinite(((DoubleFloat)number).value)) 838 return error(new FloatingPointOverflow(NIL)); 839 } 840 if (TRAP_UNDERFLOW) { 841 if (number.zerop()) 842 return error(new FloatingPointUnderflow(NIL)); 843 } 844 return number; 845 } 842 846 843 847 // Adapted from SBCL. 848 /** Return the exponent of base taken to the integer exponent power 849 * 850 * @param base A value of any type 851 * @param power An integer (fixnum or bignum) value 852 * @throws org.armedbear.lisp.ConditionThrowable 853 */ 844 854 private static final LispObject intexp(LispObject base, LispObject power) 845 855 throws ConditionThrowable 846 856 { 857 if (power.isEqualTo(0)) 858 return Fixnum.ONE; 859 if (base.isEqualTo(1)) 860 return base; 861 if (base.isEqualTo(0)) 862 return base; 863 847 864 if (power.minusp()) { 848 865 power = Fixnum.ZERO.subtract(power); … … 851 868 if (base.eql(Fixnum.TWO)) 852 869 return Fixnum.ONE.ash(power); 870 853 871 LispObject nextn = power.ash(Fixnum.MINUS_ONE); 854 872 LispObject total; … … 861 879 return total; 862 880 base = base.multiplyBy(base); 863 power = nextn; 864 nextn = power.ash(Fixnum.MINUS_ONE); 865 if (power.oddp()) 881 882 if (nextn.oddp()) 866 883 total = base.multiplyBy(total); 884 nextn = nextn.ash(Fixnum.MINUS_ONE); 867 885 } 868 886 }
Note: See TracChangeset
for help on using the changeset viewer.