001: /*
002: * pow.java
003: *
004: * Copyright (c) 2001-2007 Sun Microsystems, Inc. All Rights Reserved.
005: *
006: * See the file "LICENSE.txt" for information on usage and redistribution
007: * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
008: */
009: package org.pnuts.math;
010:
011: import pnuts.lang.PnutsFunction;
012: import pnuts.lang.Context;
013: import pnuts.lang.Runtime;
014: import java.math.*;
015:
016: public class pow extends PnutsFunction {
017:
018: public pow() {
019: super ("pow");
020: }
021:
022: public boolean defined(int nargs) {
023: return nargs == 2;
024: }
025:
026: protected Object exec(Object[] args, Context context) {
027: if (args.length != 2) {
028: undefined(args, context);
029: return null;
030: }
031: Object arg1 = args[0];
032: Object arg2 = args[1];
033: if ((arg2 instanceof Double)
034: || (arg2 instanceof Float)
035: || (arg2 instanceof BigDecimal)
036: || (arg2 instanceof Number && ((Number) arg2)
037: .intValue() < 0)) {
038: return new Double(Math.pow(((Number) arg1).doubleValue(),
039: ((Number) arg2).doubleValue()));
040: } else if ((arg2 instanceof Integer) || (arg2 instanceof Short)
041: || (arg2 instanceof Byte)) {
042: if (arg1 instanceof Double) {
043: return new Double(ipow_d(((Double) arg1).doubleValue(),
044: ((Number) arg2).intValue()));
045: } else if (arg1 instanceof Float) {
046: return new Float(ipow_f(((Float) arg1).floatValue(),
047: ((Number) arg2).intValue()));
048: } else {
049: return ipow(arg1, ((Number) arg2).intValue());
050: }
051: } else {
052: return npow(arg1, arg2);
053: }
054: }
055:
056: static final Integer zero = new Integer(0);
057: static final Integer one = new Integer(1);
058: static final Integer two = new Integer(2);
059:
060: static Object npow(Object n, Object m) {
061: if (Runtime.eq(m, zero)) {
062: return one;
063: } else {
064: Object m2 = Runtime.divide(m, two);
065: Object mod = Runtime.mod(m, two);
066: Object t = npow(n, m2);
067: Object r = Runtime.multiply(t, t);
068: if (Runtime.gt(mod, zero)) {
069: return Runtime.multiply(r, n);
070: } else {
071: return r;
072: }
073: }
074: }
075:
076: static Object ipow(Object n, int m) {
077: if (m == 0) {
078: return one;
079: } else {
080: int m2 = m / 2;
081: int mod = m % 2;
082: Object t = ipow(n, m2);
083: Object r = Runtime.multiply(t, t);
084: if (mod > 0) {
085: return Runtime.multiply(r, n);
086: } else {
087: return r;
088: }
089: }
090: }
091:
092: static double ipow_d(double d, int m) {
093: if (m == 0) {
094: return 1;
095: } else {
096: int m2 = m / 2;
097: int mod = m % 2;
098: double t = ipow_d(d, m2);
099: double r = t * t;
100: if (mod > 0) {
101: return r * d;
102: } else {
103: return r;
104: }
105: }
106: }
107:
108: static float ipow_f(float d, int m) {
109: if (m == 0) {
110: return 1;
111: } else {
112: int m2 = m / 2;
113: int mod = m % 2;
114: float t = ipow_f(d, m2);
115: float r = t * t;
116: if (mod > 0) {
117: return r * d;
118: } else {
119: return r;
120: }
121: }
122: }
123:
124: public String toString() {
125: return "function pow(x, y)";
126: }
127: }
|