0001: /*
0002: * BinaryOperator.java
0003: *
0004: * Copyright (c) 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
0005: *
0006: * See the file "LICENSE.txt" for information on usage and redistribution
0007: * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
0008: */
0009: package pnuts.lang;
0010:
0011: import java.io.Serializable;
0012: import java.lang.reflect.Array;
0013: import java.math.BigDecimal;
0014: import java.math.BigInteger;
0015: import java.util.*;
0016: import org.pnuts.lang.*;
0017:
0018: /**
0019: * Abstract base class of binary operations
0020: *
0021: * @see pnuts.lang.BooleanOperator
0022: */
0023: public abstract class BinaryOperator implements Serializable {
0024:
0025: static BigInteger maxLong = BigInteger.valueOf(Long.MAX_VALUE);
0026: static BigInteger minLong = BigInteger.valueOf(Long.MIN_VALUE);
0027: final static int SmallIntSize = 256;
0028: final static Integer smallInt[] = new Integer[SmallIntSize];
0029: static {
0030: for (int i = 0; i < SmallIntSize; i++) {
0031: smallInt[i] = new Integer(i);
0032: }
0033: }
0034:
0035: /**
0036: * Operation on ints
0037: */
0038: protected Object op_int(int i1, int i2) {
0039: throw new IllegalArgumentException(i1 + ", " + i2);
0040: }
0041:
0042: /**
0043: * Operation on longs
0044: */
0045: protected Object op_long(long l1, long l2) {
0046: throw new IllegalArgumentException(l1 + ", " + l2);
0047: }
0048:
0049: /**
0050: * Operation on floats
0051: */
0052: protected Object op_float(float f1, float f2) {
0053: throw new IllegalArgumentException(f1 + ", " + f2);
0054: }
0055:
0056: /**
0057: * Operation on doubles
0058: */
0059: protected Object op_double(double d1, double d2) {
0060: throw new IllegalArgumentException(d1 + ", " + d2);
0061: }
0062:
0063: /**
0064: * Operation on BigDecimal's
0065: */
0066: protected Object op_bdec(BigDecimal d1, BigDecimal d2) {
0067: throw new IllegalArgumentException(d1 + ", " + d2);
0068: }
0069:
0070: /**
0071: * Operation on BigInteger's
0072: */
0073: protected Object op_bint(BigInteger b1, BigInteger b2) {
0074: throw new IllegalArgumentException(b1 + ", " + b2);
0075: }
0076:
0077: /**
0078: * Operation on a Numeric and an Object
0079: */
0080: protected Object op_numeric(Numeric n1, Object n2) {
0081: throw new IllegalArgumentException(n1 + ", " + n2);
0082: }
0083:
0084: /**
0085: * Operation on an Object and a Numeric
0086: */
0087: protected Object op_numeric(Object n1, Numeric n2) {
0088: throw new IllegalArgumentException(n1 + ", " + n2);
0089: }
0090:
0091: /**
0092: * Operation on Object's
0093: */
0094: protected Object op_object(Object o1, Object o2) {
0095: throw new IllegalArgumentException(o1 + ", " + o2);
0096: }
0097:
0098: /**
0099: * Operation on a String and an Object
0100: */
0101: protected Object op_string(String n1, Object n2) {
0102: throw new IllegalArgumentException(n1 + ", " + n2);
0103: }
0104:
0105: /**
0106: * Operation on an Object and a String
0107: */
0108: protected Object op_string(Object n1, String n2) {
0109: throw new IllegalArgumentException(n1 + ", " + n2);
0110: }
0111:
0112: /**
0113: * Operation on booleans
0114: */
0115: protected Object op_boolean(boolean b1, boolean b2) {
0116: throw new IllegalArgumentException(b1 + ", " + b2);
0117: }
0118:
0119: /**
0120: * Dispatches a binary expression to a particular operation
0121: */
0122: public Object operateOn(Object n1, Object n2) {
0123: int t1;
0124: int t2;
0125: if (n1 instanceof Integer) {
0126: t1 = 1;
0127: } else if (n1 instanceof Character) {
0128: t1 = 2;
0129: } else if (n1 instanceof Byte) {
0130: t1 = 4;
0131: } else if (n1 instanceof Short) {
0132: t1 = 8;
0133: } else if (n1 instanceof Long) {
0134: t1 = 16;
0135: } else if (n1 instanceof Float) {
0136: t1 = 32;
0137: } else if (n1 instanceof Double) {
0138: t1 = 64;
0139: } else if (n1 instanceof String) {
0140: t1 = 128;
0141: } else if (n1 instanceof BigDecimal) {
0142: t1 = 256;
0143: } else if (n1 instanceof BigInteger) {
0144: t1 = 512;
0145: } else if (n1 instanceof Boolean) {
0146: t1 = 1024;
0147: } else if (n1 instanceof Numeric) {
0148: t1 = 2048;
0149: } else {
0150: t1 = 0;
0151: }
0152: if (n2 instanceof Integer) {
0153: t2 = 1;
0154: } else if (n2 instanceof Character) {
0155: t2 = 2;
0156: } else if (n2 instanceof Byte) {
0157: t2 = 4;
0158: } else if (n2 instanceof Short) {
0159: t2 = 8;
0160: } else if (n2 instanceof Long) {
0161: t2 = 16;
0162: } else if (n2 instanceof Float) {
0163: t2 = 32;
0164: } else if (n2 instanceof Double) {
0165: t2 = 64;
0166: } else if (n2 instanceof String) {
0167: t2 = 128;
0168: } else if (n2 instanceof BigDecimal) {
0169: t2 = 256;
0170: } else if (n2 instanceof BigInteger) {
0171: t2 = 512;
0172: } else if (n2 instanceof Boolean) {
0173: t2 = 1024;
0174: } else if (n2 instanceof Numeric) {
0175: t2 = 2048;
0176: } else {
0177: t2 = 0;
0178: }
0179:
0180: switch ((t1 << 16) | t2) {
0181:
0182: case (1 << 16) + 4: // int, byte
0183: case (1 << 16) + 8: // int, short
0184: case (4 << 16) + 1: // byte, int
0185: case (4 << 16) + 4: // byte, byte
0186: case (4 << 16) + 8: // byte, short
0187: case (8 << 16) + 1: // short, int
0188: case (8 << 16) + 4: // short, byte
0189: case (8 << 16) + 8: // short, short
0190: return op_int(((Number) n1).intValue(), ((Number) n2)
0191: .intValue());
0192:
0193: case (1 << 16) + 1: // int, int
0194: return op_int(((Integer) n1).intValue(), ((Integer) n2)
0195: .intValue());
0196:
0197: case (4 << 16) + 2: // byte, char
0198: case (8 << 16) + 2: // short, char
0199: return op_int(((Number) n1).intValue(),
0200: (int) ((Character) n2).charValue());
0201:
0202: case (1 << 16) + 2: // int, char
0203: return op_int(((Integer) n1).intValue(),
0204: (int) ((Character) n2).charValue());
0205:
0206: case (1 << 16) + 16: // int, long
0207: case (16 << 16) + 1: // long, int
0208: case (16 << 16) + 16: // long, long
0209: return op_long(((Number) n1).longValue(), ((Number) n2)
0210: .longValue());
0211:
0212: case (2 << 16) + 4: // char, byte
0213: case (2 << 16) + 8: // char, short
0214: return op_int((int) ((Character) n1).charValue(),
0215: ((Number) n2).intValue());
0216:
0217: case (2 << 16) + 1: // char, int
0218: return op_int((int) ((Character) n1).charValue(),
0219: ((Integer) n2).intValue());
0220:
0221: case (2 << 16) + 2: // char, char
0222: return op_int((int) ((Character) n1).charValue(),
0223: (int) ((Character) n2).charValue());
0224:
0225: case (2 << 16) + 16: // char, long
0226: return op_long((long) ((Character) n1).charValue(),
0227: ((Long) n2).longValue());
0228:
0229: case (16 << 16) + 2: // long, char
0230: return op_long(((Long) n1).longValue(),
0231: (long) ((Character) n2).charValue());
0232:
0233: case (1 << 16) + 32: // int,float
0234: case (16 << 16) + 32: // long,float
0235: case (32 << 16) + 1: // float, int
0236: case (32 << 16) + 16: // float, long
0237: case (32 << 16) + 32: // float, float
0238: return op_float(((Number) n1).floatValue(), ((Number) n2)
0239: .floatValue());
0240:
0241: case (1 << 16) + 64: // int, double
0242: case (16 << 16) + 64: // long, double
0243: case (32 << 16) + 64: // float, double
0244: case (64 << 16) + 1: // double , int
0245: case (64 << 16) + 16: // double, long
0246: case (64 << 16) + 32: // double, float
0247: case (64 << 16) + 64: // double, double
0248: return op_double(((Number) n1).doubleValue(), ((Number) n2)
0249: .doubleValue());
0250:
0251: case (2 << 16) + 32: // char, float
0252: return op_float((float) ((Character) n1).charValue(),
0253: ((Float) n2).floatValue());
0254:
0255: case (32 << 16) + 2: // float, char
0256: return op_float(((Float) n1).floatValue(),
0257: (float) ((Character) n2).charValue());
0258:
0259: case (2 << 16) + 64: // char, double
0260: return op_double((double) ((Character) n1).charValue(),
0261: ((Double) n2).doubleValue());
0262:
0263: case (64 << 16) + 2: // double, char
0264: return op_double(((Double) n1).doubleValue(),
0265: (double) ((Character) n2).charValue());
0266:
0267: case (1 << 16) + 512: // int, bigint
0268: case (4 << 16) + 512: // byte, bigint
0269: case (8 << 16) + 512: // short, bigint
0270: case (16 << 16) + 512: // long, bigint
0271: return op_bint(BigInteger
0272: .valueOf(((Number) n1).longValue()),
0273: (BigInteger) n2);
0274:
0275: case (2 << 16) + 512: // char, bigint
0276: return op_bint(BigInteger.valueOf((long) ((Character) n1)
0277: .charValue()), (BigInteger) n2);
0278:
0279: case (512 << 16) + 1: // bigint, int
0280: case (512 << 16) + 4: // bigint, byte
0281: case (512 << 16) + 8: // bigint, short
0282: case (512 << 16) + 16: // bigint, long
0283: return op_bint((BigInteger) n1, BigInteger
0284: .valueOf(((Number) n2).longValue()));
0285:
0286: case (512 << 16) + 2: // bigint, char
0287: return op_bint((BigInteger) n1, BigInteger
0288: .valueOf((long) ((Character) n2).charValue()));
0289:
0290: case (512 << 16) + 512: // bigint, bigint
0291: return op_bint((BigInteger) n1, (BigInteger) n2);
0292:
0293: case (512 << 16) + 32: // bigint, float
0294: {
0295: float ff = ((Float) n2).floatValue();
0296: if (Float.isInfinite(ff) || Float.isNaN(ff)) {
0297: return n2;
0298: }
0299: return op_bdec(new BigDecimal((BigInteger) n1),
0300: doubleToDecimal(ff));
0301: }
0302: case (512 << 16) + 64: // bigint, double
0303: {
0304: double dd = ((Double) n2).doubleValue();
0305: if (Double.isInfinite(dd) || Double.isNaN(dd)) {
0306: return n2;
0307: }
0308: return op_bdec(new BigDecimal((BigInteger) n1),
0309: doubleToDecimal(dd));
0310: }
0311: case (32 << 16) + 512: // float, bigint
0312: {
0313: float ff = ((Float) n1).floatValue();
0314: if (Float.isInfinite(ff) || Float.isNaN(ff)) {
0315: return n1;
0316: }
0317: return op_bdec(doubleToDecimal(ff), new BigDecimal(
0318: (BigInteger) n2));
0319: }
0320: case (64 << 16) + 512: // double, bigint
0321: {
0322: double dd = ((Double) n1).doubleValue();
0323: if (Double.isInfinite(dd) || Double.isNaN(dd)) {
0324: return n1;
0325: }
0326: return op_bdec(doubleToDecimal(dd), new BigDecimal(
0327: (BigInteger) n2));
0328: }
0329: case (1 << 16) + 256: // int, decimal
0330: case (4 << 16) + 256: // byte, decimal
0331: case (8 << 16) + 256: // short, decimal
0332: case (16 << 16) + 256: // long, decimal
0333: BigDecimal b1 = Configuration.normalConfiguration
0334: .longToBigDecimal(((Number) n1).longValue());
0335: return op_bdec(b1, (BigDecimal) n2);
0336:
0337: case (2 << 16) + 256: // char, decimal
0338: BigDecimal d1 = Configuration.normalConfiguration
0339: .longToBigDecimal((long) ((Character) n1)
0340: .charValue());
0341: return op_bdec(d1, (BigDecimal) n2);
0342:
0343: case (32 << 16) + 256: // float, decimal
0344: {
0345: float ff = ((Float) n1).floatValue();
0346: if (Float.isInfinite(ff) || Float.isNaN(ff)) {
0347: return n1;
0348: }
0349: return op_bdec(doubleToDecimal(ff), (BigDecimal) n2);
0350: }
0351: case (64 << 16) + 256: // double, decimal
0352: {
0353: double dd = ((Double) n1).doubleValue();
0354: if (Double.isInfinite(dd) || Double.isNaN(dd)) {
0355: return n1;
0356: }
0357: return op_bdec(doubleToDecimal(dd), (BigDecimal) n2);
0358: }
0359: case (256 << 16) + 1: // decimal, int
0360: case (256 << 16) + 4: // decimal, byte
0361: case (256 << 16) + 8: // decimal, short
0362: case (256 << 16) + 16: // decimal, long
0363: BigDecimal b2 = Configuration.normalConfiguration
0364: .longToBigDecimal(((Number) n2).longValue());
0365: return op_bdec((BigDecimal) n1, b2);
0366:
0367: case (256 << 16) + 2: // decimal, char
0368: BigDecimal d2 = Configuration.normalConfiguration
0369: .longToBigDecimal((long) ((Character) n2)
0370: .charValue());
0371: return op_bdec((BigDecimal) n1, d2);
0372:
0373: case (256 << 16) + 32: // decimal, float
0374: float ff = ((Float) n2).floatValue();
0375: if (Float.isInfinite(ff) || Float.isNaN(ff)) {
0376: return n2;
0377: }
0378: return op_bdec((BigDecimal) n1, doubleToDecimal(ff));
0379: case (256 << 16) + 64: // decimal, double
0380: double dd = ((Double) n2).doubleValue();
0381: if (Double.isInfinite(dd) || Double.isNaN(dd)) {
0382: return n2;
0383: }
0384: return op_bdec((BigDecimal) n1, doubleToDecimal(dd));
0385:
0386: case (256 << 16) + 256: // decimal, decimal
0387: return op_bdec((BigDecimal) n1, (BigDecimal) n2);
0388:
0389: case (1024 << 16) + 1024: // boolean, boolean
0390: return op_boolean(((Boolean) n1).booleanValue(),
0391: ((Boolean) n2).booleanValue());
0392:
0393: case (128 << 16) + 1: // String, int
0394: case (128 << 16) + 2: // String, char
0395: case (128 << 16) + 4: // String, byte
0396: case (128 << 16) + 8: // String, shorc
0397: case (128 << 16) + 16: // String, long
0398: case (128 << 16) + 32: // String, float
0399: case (128 << 16) + 64: // String, double
0400: case (128 << 16) + 128: // String, String
0401: case (128 << 16) + 256: // String, BigDecimal
0402: case (128 << 16) + 512: // String, BigInteger
0403: case (128 << 16) + 1024: // String, booolean
0404: case (128 << 16) + 2048: // String, Numeric
0405: case (128 << 16) + 0: // String, Object
0406: return op_string((String) n1, n2);
0407:
0408: case (1 << 16) + 128: // int, String
0409: case (2 << 16) + 128: // char, String
0410: case (4 << 16) + 128: // byte, String
0411: case (8 << 16) + 128: // short, String
0412: case (16 << 16) + 128: // long, String
0413: case (32 << 16) + 128: // float, String
0414: case (64 << 16) + 128: // double, String
0415: case (256 << 16) + 128: // BigDecimal, String
0416: case (512 << 16) + 128: // BigInteger, String
0417: case (1024 << 16) + 128: // boolean, String
0418: case (2048 << 16) + 128: // Numeric, String
0419: case (0 << 16) + 128: // Object, String
0420: return op_string(n1, (String) n2);
0421:
0422: case (2048 << 16) + 1: // Numeric, int
0423: case (2048 << 16) + 2: // Numeric, char
0424: case (2048 << 16) + 4: // Numeric, byte
0425: case (2048 << 16) + 8: // Numeric, short
0426: case (2048 << 16) + 16: // Numeric, long
0427: case (2048 << 16) + 32: // Numeric, float
0428: case (2048 << 16) + 64: // Numeric, double
0429: case (2048 << 16) + 256: // Numeric, BigDecimal
0430: case (2048 << 16) + 512: // Numeric, BigInteger
0431: case (2048 << 16) + 2048: // Numeric, Numeric
0432: return op_numeric((Numeric) n1, n2);
0433:
0434: case (1 << 16) + 2048: // int, Numeric
0435: case (2 << 16) + 2048: // char, Numeric
0436: case (4 << 16) + 2048: // byte, Numeric
0437: case (8 << 16) + 2048: // short, Numeric
0438: case (16 << 16) + 2048: // long, Numeric
0439: case (32 << 16) + 2048: // float, Numeric
0440: case (64 << 16) + 2048: // double, Numeric
0441: case (256 << 16) + 2048: // BigDecimal, Numeric
0442: case (512 << 16) + 2048: // BigInteger, Numeric
0443: return op_numeric(n1, (Numeric) n2);
0444:
0445: default:
0446: return op_object(n1, n2);
0447: }
0448: }
0449:
0450: static BigDecimal doubleToDecimal(double d) {
0451: return (BigDecimal) Runtime.decimalNumber("" + d, 10);
0452: }
0453:
0454: protected static Number compressNumber(Number n) {
0455: return Runtime.compress(n);
0456: }
0457:
0458: /**
0459: * The default implementation of + operator
0460: */
0461: public static class Add extends BinaryOperator {
0462:
0463: static Add instance = new Add();
0464:
0465: public Object op_int(int i1, int i2) {
0466: long l = (long) i1 + i2;
0467: if (l >= 0 && l < SmallIntSize) {
0468: return smallInt[(int) l];
0469: } else if (l <= Integer.MAX_VALUE && l >= Integer.MIN_VALUE) {
0470: return new Integer((int) l);
0471: } else {
0472: return new Long(l);
0473: }
0474: }
0475:
0476: public Object op_long(long d1, long d2) {
0477: long d3 = d1 + d2;
0478: if (d3 > d1 && d2 < 0 || d3 < d1 && d2 > 0) {
0479: return Runtime.compress(BigInteger.valueOf(d1).add(
0480: BigInteger.valueOf(d2)));
0481: }
0482: if (d3 >= 0 && d3 < SmallIntSize) {
0483: return smallInt[(int) d3];
0484: } else if (d3 <= Integer.MAX_VALUE
0485: && d3 >= Integer.MIN_VALUE) {
0486: return new Integer((int) d3);
0487: } else {
0488: return new Long(d3);
0489: }
0490: }
0491:
0492: public Object op_float(float f1, float f2) {
0493: return new Float(f1 + f2);
0494: }
0495:
0496: public Object op_double(double d1, double d2) {
0497: return new Double(d1 + d2);
0498: }
0499:
0500: public Object op_bdec(BigDecimal d1, BigDecimal d2) {
0501: return d1.add(d2);
0502: }
0503:
0504: public Object op_bint(BigInteger b1, BigInteger b2) {
0505: return Runtime.compress(b1.add(b2));
0506: }
0507:
0508: public Object op_numeric(Numeric n1, Object n2) {
0509: return n1.add(n2);
0510: }
0511:
0512: public Object op_numeric(Object n1, Numeric n2) {
0513: return n2.add(n1);
0514: }
0515:
0516: public Object op_string(String n1, Object n2) {
0517: StringBuffer sbuf = new StringBuffer(n1);
0518: concat(n2, sbuf);
0519: return sbuf.toString();
0520: }
0521:
0522: public Object op_string(Object n1, String n2) {
0523: StringBuffer sbuf = new StringBuffer();
0524: concat(n1, sbuf);
0525: sbuf.append(n2);
0526: return sbuf.toString();
0527: }
0528:
0529: public Object op_object(Object o1, Object o2) {
0530: boolean array1 = Runtime.isArray(o1);
0531: boolean array2 = Runtime.isArray(o2);
0532: if (array1) {
0533: return appendArray(o1, o2);
0534: } else if (o1 instanceof Collection) {
0535: if (array2) {
0536: Class cls = o1.getClass();
0537: try {
0538: Collection c = (Collection) cls.newInstance();
0539: c.addAll((Collection) o1);
0540: int len = Array.getLength(o2);
0541: for (int i = 0; i < len; i++) {
0542: c.add(Array.get(o2, i));
0543: }
0544: return c;
0545: } catch (IllegalAccessException e0) {
0546: throw new IllegalArgumentException(o1 + ", "
0547: + o2);
0548: } catch (InstantiationException e) {
0549: throw new IllegalArgumentException(o1 + ", "
0550: + o2);
0551: }
0552: } else if (o2 instanceof Collection) {
0553: try {
0554: Class cls = o1.getClass();
0555: Collection c = (Collection) cls.newInstance();
0556: c.addAll((Collection) o1);
0557: c.addAll((Collection) o2);
0558: return c;
0559: } catch (IllegalAccessException e0) {
0560: throw new IllegalArgumentException(o1 + ", "
0561: + o2);
0562: } catch (InstantiationException e) {
0563: throw new IllegalArgumentException(o1 + ", "
0564: + o2);
0565: }
0566: }
0567: }
0568: if (o1 instanceof Map && o2 instanceof Map) {
0569: Class cls = o1.getClass();
0570: try {
0571: Map m = (Map) cls.newInstance();
0572: m.putAll((Map) o1);
0573: m.putAll((Map) o2);
0574: return m;
0575: } catch (IllegalAccessException e0) {
0576: throw new IllegalArgumentException(o1 + ", " + o2);
0577: } catch (InstantiationException e) {
0578: throw new IllegalArgumentException(o1 + ", " + o2);
0579: }
0580: }
0581: if (o1 instanceof Generator && o2 instanceof Generator) {
0582: return appendGenerator((Generator) o1, (Generator) o2);
0583: }
0584: return super .op_object(o1, o2);
0585: }
0586: }
0587:
0588: static void concat(Object o, StringBuffer sbuf) {
0589: String s;
0590: if (Runtime.isArray(o)) {
0591: s = Pnuts.format(o);
0592: } else {
0593: s = String.valueOf(o);
0594: }
0595: sbuf.append(s);
0596: }
0597:
0598: static Object appendGenerator(Generator g1, Generator g2) {
0599: return new CompositeGenerator(g1, g2);
0600: }
0601:
0602: static Object appendArray(Object p1, Object p2) {
0603: int l1 = Runtime.getArrayLength(p1);
0604: int l2;
0605:
0606: boolean notList = false;
0607: if (p2 instanceof Collection) {
0608: l2 = ((Collection) p2).size();
0609: if (!(p2 instanceof List)) {
0610: notList = true;
0611: }
0612: } else {
0613: l2 = Runtime.getArrayLength(p2);
0614: }
0615: Class componentType = p1.getClass().getComponentType();
0616: Object p3 = Array.newInstance(componentType, l1 + l2);
0617: System.arraycopy(p1, 0, p3, 0, l1);
0618: if (notList) {
0619: int i = 0;
0620: for (Iterator it = ((Collection) p2).iterator(); it
0621: .hasNext();) {
0622: Object o2 = it.next();
0623: if (!componentType.isInstance(o2)) {
0624: o2 = Runtime.transform(componentType, o2);
0625: }
0626: Array.set(p3, i++ + l1, o2);
0627: }
0628: } else {
0629: for (int i = 0; i < l2; i++) {
0630: Object o2;
0631: if (p2 instanceof List) {
0632: o2 = ((List) p2).get(i);
0633: } else {
0634: o2 = Array.get(p2, i);
0635: }
0636: if (!componentType.isInstance(o2)) {
0637: o2 = Runtime.transform(componentType, o2);
0638: }
0639: Array.set(p3, i + l1, o2);
0640: }
0641: }
0642: return p3;
0643: }
0644:
0645: /**
0646: * The default implementation of - operator
0647: */
0648: public static class Subtract extends BinaryOperator {
0649:
0650: static Subtract instance = new Subtract();
0651:
0652: public Object op_int(int i1, int i2) {
0653: long l = (long) i1 - i2;
0654: if (l >= 0 && l < SmallIntSize) {
0655: return smallInt[(int) l];
0656: } else if (l <= Integer.MAX_VALUE && l >= Integer.MIN_VALUE) {
0657: return new Integer((int) l);
0658: } else {
0659: return new Long(l);
0660: }
0661: }
0662:
0663: public Object op_long(long d1, long d2) {
0664: long d3 = d1 - d2;
0665: if (d3 > d1 && d2 > 0 || d3 < d1 && d2 < 0) {
0666: return op_bint(BigInteger.valueOf(d1), BigInteger
0667: .valueOf(d2));
0668: }
0669: if (d3 <= Integer.MAX_VALUE && d3 >= Integer.MIN_VALUE) {
0670: return new Integer((int) d3);
0671: } else {
0672: return new Long(d3);
0673: }
0674: }
0675:
0676: public Object op_float(float f1, float f2) {
0677: return new Float(f1 - f2);
0678: }
0679:
0680: public Object op_double(double d1, double d2) {
0681: return new Double(d1 - d2);
0682: }
0683:
0684: public Object op_bdec(BigDecimal d1, BigDecimal d2) {
0685: return d1.subtract(d2);
0686: }
0687:
0688: public Object op_bint(BigInteger b1, BigInteger b2) {
0689: return Runtime.compress(b1.subtract(b2));
0690: }
0691:
0692: public Object op_numeric(Numeric n1, Object n2) {
0693: return n1.subtract(n2);
0694: }
0695:
0696: public Object op_numeric(Object n1, Numeric n2) {
0697: return Add.instance.operateOn(n2.negate(), n1);
0698: }
0699:
0700: public Object op_object(Object o1, Object o2) {
0701: boolean array1 = false;
0702: boolean array2 = false;
0703: Collection c1 = null;
0704: Collection c2 = null;
0705: if (o1 instanceof Collection) {
0706: c1 = (Collection) o1;
0707: } else if (Runtime.isArray(o1)) {
0708: array1 = true;
0709: } else {
0710: return super .op_object(o1, o2);
0711: }
0712: if (o2 instanceof Collection) {
0713: c2 = (Collection) o2;
0714: } else if (Runtime.isArray(o2)) {
0715: array2 = true;
0716: } else {
0717: return super .op_object(o1, o2);
0718: }
0719:
0720: if (array1) {
0721: c1 = new ArrayList();
0722: for (int i = 0; i < Runtime.getArrayLength(o1); i++) {
0723: c1.add(Array.get(o1, i));
0724: }
0725: }
0726: if (array2) {
0727: c2 = new ArrayList();
0728: for (int i = 0; i < Runtime.getArrayLength(o2); i++) {
0729: c2.add(Array.get(o2, i));
0730: }
0731: }
0732:
0733: if (c1 != null && c2 != null) {
0734: Class cls = c1.getClass();
0735: try {
0736: Collection c = (Collection) cls.newInstance();
0737: c.addAll(c1);
0738: c.removeAll(c2);
0739: if (array1) {
0740: Object array = Array.newInstance(o1.getClass()
0741: .getComponentType(), c.size());
0742: int i = 0;
0743: for (Iterator it = c.iterator(); it.hasNext();) {
0744: Array.set(array, i++, it.next());
0745: }
0746: return array;
0747: } else {
0748: return c;
0749: }
0750: } catch (Exception e) {
0751: throw new IllegalArgumentException(e.getMessage());
0752: }
0753: }
0754: return super .op_object(o1, o2);
0755: }
0756: }
0757:
0758: /**
0759: * The default implementation of * operator
0760: */
0761: public static class Multiply extends BinaryOperator {
0762:
0763: static Multiply instance = new Multiply();
0764:
0765: public Object op_int(int i1, int i2) {
0766: long l = (long) i1 * i2;
0767: if (l <= Integer.MAX_VALUE && l >= Integer.MIN_VALUE) {
0768: return new Integer((int) l);
0769: } else {
0770: return new Long(l);
0771: }
0772: }
0773:
0774: public Object op_long(long d1, long d2) {
0775: long d3 = d1 * d2;
0776: if (d2 == 0) {
0777: return new Long(0L);
0778: }
0779: if (d3 / d2 == d1) {
0780: if (d3 <= Integer.MAX_VALUE && d3 >= Integer.MIN_VALUE) {
0781: return new Integer((int) d3);
0782: } else {
0783: return new Long(d3);
0784: }
0785: } else {
0786: return op_bint(BigInteger.valueOf(d1), BigInteger
0787: .valueOf(d2));
0788: }
0789: }
0790:
0791: public Object op_float(float f1, float f2) {
0792: return new Float(f1 * f2);
0793: }
0794:
0795: public Object op_double(double d1, double d2) {
0796: return new Double(d1 * d2);
0797: }
0798:
0799: public Object op_bdec(BigDecimal d1, BigDecimal d2) {
0800: return d1.multiply(d2);
0801: }
0802:
0803: public Object op_bint(BigInteger b1, BigInteger b2) {
0804: return Runtime.compress(b1.multiply(b2));
0805: }
0806:
0807: public Object op_numeric(Numeric n1, Object n2) {
0808: return n1.multiply(n2);
0809: }
0810:
0811: public Object op_numeric(Object n1, Numeric n2) {
0812: return n2.multiply(n1);
0813: }
0814:
0815: public Object op_object(Object o1, Object o2) {
0816: if (o1 instanceof Set && o2 instanceof Set) {
0817: Set c1 = (Set) o1;
0818: Set c2 = (Set) o2;
0819: Class cls = c1.getClass();
0820: try {
0821: Collection c = (Collection) cls.newInstance();
0822: c.addAll(c1);
0823: c.retainAll(c2);
0824: return c;
0825: } catch (Exception e) {
0826: throw new IllegalArgumentException(e.getMessage());
0827: }
0828: } else {
0829: return super .op_object(o1, o2);
0830: }
0831: }
0832: }
0833:
0834: /**
0835: * The default implementation of / operator
0836: */
0837: public static class Divide extends BinaryOperator {
0838:
0839: static Divide instance = new Divide();
0840:
0841: public Object op_int(int i1, int i2) {
0842: int l = i1 / i2;
0843: if (l >= 0 && l < SmallIntSize) {
0844: return smallInt[(int) l];
0845: }
0846: return new Integer(l);
0847: }
0848:
0849: public Object op_long(long d1, long d2) {
0850: long d3 = d1 / d2;
0851: if (d3 <= Integer.MAX_VALUE && d3 >= Integer.MIN_VALUE) {
0852: return new Integer((int) d3);
0853: } else {
0854: return new Long(d3);
0855: }
0856: }
0857:
0858: public Object op_float(float f1, float f2) {
0859: return new Float(f1 / f2);
0860: }
0861:
0862: public Object op_double(double d1, double d2) {
0863: return new Double(d1 / d2);
0864: }
0865:
0866: public Object op_bdec(BigDecimal d1, BigDecimal d2) {
0867: return d1.divide(d2, BigDecimal.ROUND_HALF_DOWN);
0868: }
0869:
0870: public Object op_bint(BigInteger b1, BigInteger b2) {
0871: return Runtime.compress(b1.divide(b2));
0872: }
0873:
0874: public Object op_numeric(Numeric n1, Object n2) {
0875: return n1.divide(n2);
0876: }
0877:
0878: public Object op_numeric(Object n1, Numeric n2) {
0879: return Multiply.instance.operateOn(n2.inverse(), n1);
0880: }
0881: }
0882:
0883: /**
0884: * The default implementation of % operator
0885: */
0886: public static class Mod extends BinaryOperator {
0887:
0888: static Mod instance = new Mod();
0889:
0890: public Object op_int(int i1, int i2) {
0891: int l = i1 % i2;
0892: if (l >= 0 && l < SmallIntSize) {
0893: return smallInt[(int) l];
0894: }
0895: return new Integer(l);
0896: }
0897:
0898: public Object op_long(long d1, long d2) {
0899: long d3 = d1 % d2;
0900: if (d3 <= Integer.MAX_VALUE && d3 >= Integer.MIN_VALUE) {
0901: return new Integer((int) d3);
0902: } else {
0903: return new Long(d3);
0904: }
0905: }
0906:
0907: public Object op_float(float f1, float f2) {
0908: throw new IllegalArgumentException();
0909: }
0910:
0911: public Object op_double(double d1, double d2) {
0912: throw new IllegalArgumentException();
0913: }
0914:
0915: public Object op_bdec(BigDecimal d1, BigDecimal d2) {
0916: throw new IllegalArgumentException();
0917: }
0918:
0919: public Object op_bint(BigInteger b1, BigInteger b2) {
0920: return Runtime.compress(b1.mod(b2));
0921: }
0922: }
0923:
0924: /**
0925: * The default implementation of >>> operator
0926: */
0927: public static class ShiftArithmetic extends BinaryOperator {
0928:
0929: static ShiftArithmetic instance = new ShiftArithmetic();
0930:
0931: public Object op_int(int d1, int d2) {
0932: int l = d1 >>> d2;
0933: if (l >= 0 && l < SmallIntSize) {
0934: return smallInt[(int) l];
0935: }
0936: return new Integer(l);
0937: }
0938:
0939: public Object op_long(long d1, long d2) {
0940: long l = d1 >>> d2;
0941: if (l >= 0 && l < SmallIntSize) {
0942: return smallInt[(int) l];
0943: } else if (l <= Integer.MAX_VALUE && l >= Integer.MIN_VALUE) {
0944: return new Integer((int) l);
0945: } else {
0946: return new Long(l);
0947: }
0948: }
0949: }
0950:
0951: /**
0952: * The default implementation of < operator
0953: */
0954: public static class ShiftLeft extends BinaryOperator {
0955:
0956: static ShiftLeft instance = new ShiftLeft();
0957:
0958: public Object op_int(int d1, int d2) {
0959: int m = 0;
0960: long dd = (long) d1;
0961: while (dd > 0) {
0962: dd >>= 1;
0963: m++;
0964: }
0965: if (d2 + m > 63) {
0966: return Runtime.compress(BigInteger.valueOf(d1)
0967: .shiftLeft((int) d2));
0968: } else {
0969: long l = (long) d1 << d2;
0970: if (l >= 0 && l < SmallIntSize) {
0971: return smallInt[(int) l];
0972: } else if (l <= Integer.MAX_VALUE
0973: && l >= Integer.MIN_VALUE) {
0974: return new Integer((int) l);
0975: } else {
0976: return new Long(l);
0977: }
0978: }
0979: }
0980:
0981: public Object op_long(long d1, long d2) {
0982: int m = 0;
0983: long dd = d1;
0984: while (dd > 0) {
0985: dd >>= 1;
0986: m++;
0987: }
0988: if (d2 + m > 63) {
0989: return Runtime.compress(BigInteger.valueOf(d1)
0990: .shiftLeft((int) d2));
0991: } else {
0992: long l = d1 << d2;
0993: if (l >= 0 && l < SmallIntSize) {
0994: return smallInt[(int) l];
0995: } else if (l <= Integer.MAX_VALUE
0996: && l >= Integer.MIN_VALUE) {
0997: return new Integer((int) l);
0998: } else {
0999: return new Long(l);
1000: }
1001: }
1002: }
1003:
1004: public Object op_bint(BigInteger b1, BigInteger b2) {
1005: return Runtime.compress(b1.shiftLeft(b2.intValue()));
1006: }
1007: }
1008:
1009: /**
1010: * The default implementation of > operator
1011: */
1012: public static class ShiftRight extends BinaryOperator {
1013:
1014: static ShiftRight instance = new ShiftRight();
1015:
1016: public Object op_int(int d1, int d2) {
1017: int l = d1 >> d2;
1018: if (l >= 0 && l < SmallIntSize) {
1019: return smallInt[(int) l];
1020: }
1021: return new Integer(l);
1022: }
1023:
1024: public Object op_long(long d1, long d2) {
1025: long l = d1 >> d2;
1026: if (l >= 0 && l < SmallIntSize) {
1027: return smallInt[(int) l];
1028: } else if (l <= Integer.MAX_VALUE && l >= Integer.MIN_VALUE) {
1029: return new Integer((int) l);
1030: } else {
1031: return new Long(l);
1032: }
1033: }
1034:
1035: public Object op_bint(BigInteger b1, BigInteger b2) {
1036: return Runtime.compress(b1.shiftRight(b2.intValue()));
1037: }
1038: }
1039:
1040: /**
1041: * The default implementation of & operator
1042: */
1043: public static class And extends BinaryOperator {
1044:
1045: static And instance = new And();
1046:
1047: public Object op_int(int i1, int i2) {
1048: int l = i1 & i2;
1049: if (l >= 0 && l < SmallIntSize) {
1050: return smallInt[(int) l];
1051: }
1052: return new Integer(l);
1053: }
1054:
1055: public Object op_long(long d1, long d2) {
1056: return new Long(d1 & d2);
1057: }
1058:
1059: public Object op_bint(BigInteger b1, BigInteger b2) {
1060: return Runtime.compress(b1.and(b2));
1061: }
1062:
1063: public Object op_boolean(boolean b1, boolean b2) {
1064: return (b1 & b2) ? Boolean.TRUE : Boolean.FALSE;
1065: }
1066: }
1067:
1068: /**
1069: * The default implementation of | operator (bitwise OR)
1070: */
1071: public static class Or extends BinaryOperator {
1072:
1073: static Or instance = new Or();
1074:
1075: public Object op_int(int i1, int i2) {
1076: int l = i1 | i2;
1077: if (l >= 0 && l < SmallIntSize) {
1078: return smallInt[(int) l];
1079: }
1080: return new Integer(l);
1081: }
1082:
1083: public Object op_long(long d1, long d2) {
1084: return new Long(d1 | d2);
1085: }
1086:
1087: public Object op_bint(BigInteger b1, BigInteger b2) {
1088: return Runtime.compress(b1.or(b2));
1089: }
1090:
1091: public Object op_boolean(boolean b1, boolean b2) {
1092: return (b1 | b2) ? Boolean.TRUE : Boolean.FALSE;
1093: }
1094: }
1095:
1096: /**
1097: * The default implementation of ^ operator
1098: */
1099: public static class Xor extends BinaryOperator {
1100:
1101: static Xor instance = new Xor();
1102:
1103: public Object op_int(int i1, int i2) {
1104: int l = i1 ^ i2;
1105: if (l >= 0 && l < SmallIntSize) {
1106: return smallInt[(int) l];
1107: }
1108: return new Integer(l);
1109: }
1110:
1111: public Object op_long(long d1, long d2) {
1112: return new Long(d1 ^ d2);
1113: }
1114:
1115: public Object op_bint(BigInteger b1, BigInteger b2) {
1116: return Runtime.compress(b1.xor(b2));
1117: }
1118:
1119: public Object op_boolean(boolean b1, boolean b2) {
1120: return (b1 ^ b2) ? Boolean.TRUE : Boolean.FALSE;
1121: }
1122: }
1123: }
|