Index: src/test/groovy/operator/IntegerOperatorsTest.groovy
===================================================================
--- src/test/groovy/operator/IntegerOperatorsTest.groovy	(revision 16004)
+++ src/test/groovy/operator/IntegerOperatorsTest.groovy	(working copy)
@@ -158,16 +158,21 @@
         x = -16 >>> 4
         assert x == 0xFFFFFFF
 
-        //Ensure that the type of the right operand (shift distance) is ignored when calculating the
-        //result.  This is how java works, and for these operators, it makes sense to keep that behavior.
-        x = Integer.MAX_VALUE << 1L
-        assert x == -2
-        assert x instanceof Integer
-
-        x = new Long(Integer.MAX_VALUE).longValue() << 1
+        x = Long.valueOf(Integer.MAX_VALUE) << 1
         assert x == 0xfffffffe
         assert x instanceof Long
 
+        x = BigInteger.valueOf(Long.MAX_VALUE) << 1
+        assert x == 0xfffffffffffffffe
+        assert x instanceof BigInteger
+
+        //BigInteger doesn't support unsigned right shift operator
+        try {
+            x = 0xfffffffffffffffe >>> 1
+            fail("Should catch UnsupportedOperationException");
+        } catch (UnsupportedOperationException uoe) {
+        }
+
         //The left operand (shift value) must be an integral type
         try {
             x = 8.0F >> 2
@@ -182,4 +187,126 @@
         } catch (UnsupportedOperationException uoe) {
         }
     }
+
+    void testAddTypePromotion() {
+        x = Integer.MAX_VALUE + 1
+        assert x == Long.valueOf(Integer.MAX_VALUE) + 1
+        assert x instanceof Long
+
+        x = Integer.MIN_VALUE + -1
+        assert x == Long.valueOf(Integer.MIN_VALUE) + -1
+        assert x instanceof Long
+
+        x = Long.MAX_VALUE + 1
+        assert x == BigInteger.valueOf(Long.MAX_VALUE) + 1
+        assert x instanceof BigInteger
+
+        x = Long.MIN_VALUE + -1
+        assert x == BigInteger.valueOf(Long.MIN_VALUE) + -1
+        assert x instanceof BigInteger
+    }
+
+    void testSubtractTypePromotion() {
+        x = Integer.MAX_VALUE - -1
+        assert x == Long.valueOf(Integer.MAX_VALUE) - -1
+        assert x instanceof Long
+
+        x = Integer.MIN_VALUE - 1
+        assert x == Long.valueOf(Integer.MIN_VALUE) - 1
+        assert x instanceof Long
+
+        x = Long.MAX_VALUE - -1
+        assert x == BigInteger.valueOf(Long.MAX_VALUE) - -1
+        assert x instanceof BigInteger
+
+        x = Long.MIN_VALUE - 1
+        assert x == BigInteger.valueOf(Long.MIN_VALUE) - 1
+        assert x instanceof BigInteger
+    }
+
+    void testMultiplyTypePromotion() {
+        x = Integer.MAX_VALUE * 2
+        assert x == Long.valueOf(Integer.MAX_VALUE) * 2
+        assert x instanceof Long
+
+        x = Integer.MAX_VALUE * -2
+        assert x == Long.valueOf(Integer.MAX_VALUE) * -2
+        assert x instanceof Long
+
+        x = Long.MAX_VALUE * 2
+        assert x == BigInteger.valueOf(Long.MAX_VALUE) * 2
+        assert x instanceof BigInteger
+
+        x = Long.MAX_VALUE * -2
+        assert x == BigInteger.valueOf(Long.MAX_VALUE) * -2
+        assert x instanceof BigInteger
+    }
+
+    void testAbsTypePromotion() {
+        x = Integer.MIN_VALUE.abs()
+        assert x == Long.valueOf(Integer.MIN_VALUE).abs()
+        assert x instanceof Long
+
+        x = Long.MIN_VALUE.abs()
+        assert x == BigInteger.valueOf(Long.MIN_VALUE).abs()
+        assert x instanceof BigInteger
+    }
+
+    void testUnaryMinusTypePromotion() {
+        x = -Integer.MIN_VALUE
+        assert x == -(Long.valueOf(Integer.MIN_VALUE))
+        assert x instanceof Long
+
+        x = -Long.MIN_VALUE
+        assert x == -(BigInteger.valueOf(Long.MIN_VALUE))
+        assert x instanceof BigInteger
+    }
+
+    void testLeftShiftTypePromotion() {
+        x = Integer.MAX_VALUE << 1
+        assert x == Long.valueOf(Integer.MAX_VALUE) << 1
+        assert x instanceof Long
+
+        x = Integer.MIN_VALUE << 1
+        assert x == Long.valueOf(Integer.MIN_VALUE) << 1
+        assert x instanceof Long
+
+        x = Integer.MAX_VALUE << 33
+        assert x == BigInteger.valueOf(Integer.MAX_VALUE) << 33
+        assert x instanceof BigInteger
+
+        x = Integer.MIN_VALUE << 33
+        assert x == BigInteger.valueOf(Integer.MIN_VALUE) << 33
+        assert x instanceof BigInteger
+
+        x = 1 << 33
+        assert x == 1L << 33
+        assert x instanceof Long
+
+        x = -1 << 33
+        assert x == -1L << 33
+        assert x instanceof Long
+
+        x = Long.MAX_VALUE << 1
+        assert x == BigInteger.valueOf(Long.MAX_VALUE) << 1
+        assert x instanceof BigInteger
+
+        x = Long.MIN_VALUE << 1
+        assert x == BigInteger.valueOf(Long.MIN_VALUE) << 1
+        assert x instanceof BigInteger
+    }
+
+    void testMultiplyByZero() {
+        x = 0 * 100
+        assert x == 0
+
+        x = 100 * 0
+        assert x == 0
+
+        x = 0 * 100L
+        assert x == 0
+
+        x = 100L * 0
+        assert x == 0
+    }
 }
Index: src/main/org/codehaus/groovy/runtime/typehandling/NumberMath.java
===================================================================
--- src/main/org/codehaus/groovy/runtime/typehandling/NumberMath.java	(revision 16004)
+++ src/main/org/codehaus/groovy/runtime/typehandling/NumberMath.java	(working copy)
@@ -15,6 +15,8 @@
  */
 package org.codehaus.groovy.runtime.typehandling;
 
+import org.codehaus.groovy.runtime.DefaultGroovyMethods;
+
 import java.math.BigDecimal;
 import java.math.BigInteger;
 
@@ -90,42 +92,39 @@
     }
 
     /**
-     * For this operation, consider the operands independently.  Throw an exception if the right operand
-     * (shift distance) is not an integral type.  For the left operand (shift value) also require an integral
-     * type, but do NOT promote from Integer to Long.  This is consistent with Java, and makes sense for the
-     * shift operators.
+     * Throw an exception if the right operand (shift distance) is not
+     * an integral type.  For the left operand (shift value) also
+     * require an integral type.
      */
     public static Number leftShift(Number left, Number right) {
 		if (isFloatingPoint(right) || isBigDecimal(right)) {
 	        throw new UnsupportedOperationException("Shift distance must be an integral type, but " +  right + " (" + right.getClass().getName() + ") was supplied");
 		}
-    	return getMath(left).leftShiftImpl(left,right);
+    	return getMath(left,right).leftShiftImpl(left,right);
     }
     
     /**
-     * For this operation, consider the operands independently.  Throw an exception if the right operand
-     * (shift distance) is not an integral type.  For the left operand (shift value) also require an integral
-     * type, but do NOT promote from Integer to Long.  This is consistent with Java, and makes sense for the
-     * shift operators.
+     * Throw an exception if the right operand (shift distance) is not
+     * an integral type.  For the left operand (shift value) also
+     * require an integral type.
      */
     public static Number rightShift(Number left, Number right) {
 		if (isFloatingPoint(right) || isBigDecimal(right)) {
 	        throw new UnsupportedOperationException("Shift distance must be an integral type, but " +  right + " (" + right.getClass().getName() + ") was supplied");
 		}
-    	return getMath(left).rightShiftImpl(left,right);
+    	return getMath(left,right).rightShiftImpl(left,right);
     }
     
     /**
-     * For this operation, consider the operands independently.  Throw an exception if the right operand
-     * (shift distance) is not an integral type.  For the left operand (shift value) also require an integral
-     * type, but do NOT promote from Integer to Long.  This is consistent with Java, and makes sense for the
-     * shift operators.
+     * Throw an exception if the right operand (shift distance) is not
+     * an integral type.  For the left operand (shift value) also
+     * require an integral type.
      */
     public static Number rightShiftUnsigned(Number left, Number right) {
 		if (isFloatingPoint(right) || isBigDecimal(right)) {
 	        throw new UnsupportedOperationException("Shift distance must be an integral type, but " +  right + " (" + right.getClass().getName() + ") was supplied");
 		}
-    	return getMath(left).rightShiftUnsignedImpl(left,right);
+    	return getMath(left,right).rightShiftUnsignedImpl(left,right);
     }
     
     public static Number unaryMinus(Number left) {
@@ -153,28 +152,59 @@
 	}
 
 	public static BigDecimal toBigDecimal(Number n) {
-		return (n instanceof BigDecimal ? (BigDecimal) n : new BigDecimal(n.toString()));
+        return DefaultGroovyMethods.toBigDecimal(n);
 	}
 				
 	public static BigInteger toBigInteger(Number n) {
-		return (n instanceof BigInteger ? (BigInteger) n : new BigInteger(n.toString()));
+        return DefaultGroovyMethods.toBigInteger(n);
 	}
 					
 	/**
-	 * Determine which NumberMath instance to use, given the supplied operands.  This method implements
-	 * the type promotion rules discussed in the documentation.  Note that by the time this method is
-	 * called, any Byte, Character or Short operands will have been promoted to Integer.  For reference,
-	 * here is the promotion matrix:
-	 *    bD bI  D  F  L  I
-	 * bD bD bD  D  D bD bD
-	 * bI bD bI  D  D bI bI
-	 *  D  D  D  D  D  D  D
-	 *  F  D  D  D  D  D  D
-	 *  L bD bI  D  D  L  L
-	 *  I bD bI  D  D  L  I
+	 * Determine which NumberMath instance to use, given the supplied
+	 * operands.  This method implements the type promotion rules
+	 * discussed in the documentation.  Note that by the time this
+	 * method is called, any Byte, Character or Short operands will
+	 * have been promoted to Integer.
+     * 
+     * For reference, here is the binary operator type promotion
+	 * matrix:
+     * 
+	 *     bD bI  D  F  L  I
+     *     -----------------
+	 * bD |bD bD  D  D bD bD
+	 * bI |bD bI  D  D bI bI
+	 *  D | D  D  D  D  D  D
+	 *  F | D  D  D  D  D  D
+	 *  L |bD bI  D  D  L+ L+
+	 *  I |bD bI  D  D  L+ I+
 	 * 
-	 * Note that for division, if either operand isFloatingPoint, the result will be floating.  Otherwise,
-	 * the result is BigDecimal
+     * When both operands are of type Integer or Long (in any
+     * combination) the result type is dynamically promoted to a
+     * larger type if needed to avoid overflow.  This is represented
+     * by the bottom-right 2x2 square in the promotion matrix above.
+     * I+ represents Integer, Long or BigInteger.  L+ represents Long
+     * or BigInteger.
+     * 
+     * Unary operators with an Integer or Long operand will also
+     * dynamically promote their result types:
+     *
+	 *     bD bI  D  F  L  I
+     *     -----------------
+	 *     bD bI  D  D  L+ I+
+     * 
+     * The division operator returns Double if either operand is Float
+	 * or Double, returns BigDecimal otherwise.  Here is the division
+	 * operator type promotion matrix:
+     *
+	 *     bD bI  D  F  L  I
+     *     -----------------
+	 * bD |bD bD  D  D bD bD
+	 * bI |bD bD  D  D bD bD
+	 *  D | D  D  D  D  D  D
+	 *  F | D  D  D  D  D  D
+	 *  L |bD bD  D  D bD bD
+	 *  I |bD bD  D  D bD bD
+	 * 
 	 */
 	public static NumberMath getMath(Number left, Number right) {
 		if (isFloatingPoint(left) || isFloatingPoint(right)) {
Index: src/main/org/codehaus/groovy/runtime/typehandling/IntegerMath.java
===================================================================
--- src/main/org/codehaus/groovy/runtime/typehandling/IntegerMath.java	(revision 16004)
+++ src/main/org/codehaus/groovy/runtime/typehandling/IntegerMath.java	(working copy)
@@ -15,6 +15,8 @@
  */
 package org.codehaus.groovy.runtime.typehandling;
 
+import java.math.BigInteger;
+
 /**
  * Integer NumberMath operations
  * 
@@ -27,19 +29,35 @@
 	private IntegerMath() {}
 					
 	protected Number absImpl(Number number) {
-		return Integer.valueOf(Math.abs(number.intValue()));
+        int n = number.intValue();
+        if (n > Integer.MIN_VALUE) {
+            return Integer.valueOf(Math.abs(n));
+        }
+        return Long.valueOf(Math.abs((long)n));
 	}
 	
 	public Number addImpl(Number left, Number right) {
-		return Integer.valueOf(left.intValue() + right.intValue());
+		long v = left.longValue() + right.longValue();
+		if (v <= Integer.MAX_VALUE && v >= Integer.MIN_VALUE) {
+            return Integer.valueOf((int)v);
+        }
+		return Long.valueOf(v);
 	}
 
 	public Number subtractImpl(Number left, Number right) {
-		return Integer.valueOf(left.intValue() - right.intValue());
+		long v = left.longValue() - right.longValue();
+		if (v <= Integer.MAX_VALUE && v >= Integer.MIN_VALUE) {
+            return Integer.valueOf((int)v);
+        }
+		return Long.valueOf(v);
 	}
 
 	public Number multiplyImpl(Number left, Number right) {
-		return Integer.valueOf(left.intValue() * right.intValue());
+		long v = left.longValue() * right.longValue();
+		if (v <= Integer.MAX_VALUE && v >= Integer.MIN_VALUE) {
+            return Integer.valueOf((int)v);
+        }
+		return Long.valueOf(v);
 	}
 
 	public Number divideImpl(Number left, Number right) {
@@ -72,8 +90,12 @@
         return Integer.valueOf(left.intValue() % right.intValue());
     }
 
-    protected Number unaryMinusImpl(Number left) {
-        return Integer.valueOf(-left.intValue());
+    protected Number unaryMinusImpl(Number number) {
+        int n = number.intValue();
+        if (n > Integer.MIN_VALUE) {
+            return Integer.valueOf(-n);
+        }
+        return Long.valueOf(-((long)n));
     }
 
     protected Number bitwiseNegateImpl(Number left) {
@@ -81,14 +103,44 @@
     }
 
     protected Number leftShiftImpl(Number left, Number right) {
-        return Integer.valueOf(left.intValue() << right.intValue());
+        long l = left.longValue();
+        int r = right.intValue();
+        if (r < 0) {
+            throw new IllegalArgumentException("Shift distance must be non-negative, but " +  r + " was supplied");
+        }
+        if (r < 64 || l == 0 || r == 0) {
+            long v = l << r;
+            if (v >> r == l) {
+                if (v <= Integer.MAX_VALUE && v >= Integer.MIN_VALUE) {
+                    return Integer.valueOf((int)v);
+                }
+                return Long.valueOf(v);
+            }
+        }
+        return BigIntegerMath.INSTANCE.leftShiftImpl(left, right);
     }
 
     protected Number rightShiftImpl(Number left, Number right) {
-        return Integer.valueOf(left.intValue() >> right.intValue());
+        int l = left.intValue();
+        int r = right.intValue();
+        if (r < 0) {
+            throw new IllegalArgumentException("Shift distance must be non-negative, but " +  r + " was supplied");
+        }
+        if (r >= 32) {
+            return Integer.valueOf((l < 0) ? -1 : 0);
+        }
+        return Integer.valueOf(l >> r);
     }
 
     protected Number rightShiftUnsignedImpl(Number left, Number right) {
-        return Integer.valueOf(left.intValue() >>> right.intValue());
+        int l = left.intValue();
+        int r = right.intValue();
+        if (r < 0) {
+            throw new IllegalArgumentException("Shift distance must be non-negative, but " +  r + " was supplied");
+        }
+        if (r >= 32) {
+            return Integer.valueOf(0);
+        }
+        return Integer.valueOf(l >>> r);
     }
 }
Index: src/main/org/codehaus/groovy/runtime/typehandling/BigIntegerMath.java
===================================================================
--- src/main/org/codehaus/groovy/runtime/typehandling/BigIntegerMath.java	(revision 16004)
+++ src/main/org/codehaus/groovy/runtime/typehandling/BigIntegerMath.java	(working copy)
@@ -16,6 +16,8 @@
 
 package org.codehaus.groovy.runtime.typehandling;
 
+import java.math.BigInteger;
+
 /**
  * BigInteger NumberMath operations
  * 
@@ -77,4 +79,28 @@
     protected Number xorImpl(Number left, Number right) {
         return toBigInteger(left).xor(toBigInteger(right));
     }
+
+    protected Number leftShiftImpl(Number left, Number right) {
+        BigInteger bi_r = toBigInteger(right);
+        if (bi_r.compareTo(BigInteger.ZERO) < 0) {
+            throw new IllegalArgumentException("Shift distance must be non-negative, but " +  bi_r + " was supplied");
+        }
+        int i_r = bi_r.intValue();
+        if (bi_r.compareTo(toBigInteger(i_r)) != 0) {
+            throw new IllegalArgumentException("Shift distance must fit within Integer range, but " +  bi_r + " was supplied");
+        }
+        return toBigInteger(left).shiftLeft(i_r);
+    }
+
+    protected Number rightShiftImpl(Number left, Number right) {
+        BigInteger bi_r = toBigInteger(right);
+        if (bi_r.compareTo(BigInteger.ZERO) < 0) {
+            throw new IllegalArgumentException("Shift distance must be non-negative, but " +  bi_r + " was supplied");
+        }
+        int i_r = bi_r.intValue();
+        if (bi_r.compareTo(toBigInteger(i_r)) != 0) {
+            throw new IllegalArgumentException("Shift distance must fit within Integer range, but " +  bi_r + " was supplied");
+        }
+        return toBigInteger(left).shiftRight(i_r);
+    }
 }
Index: src/main/org/codehaus/groovy/runtime/typehandling/LongMath.java
===================================================================
--- src/main/org/codehaus/groovy/runtime/typehandling/LongMath.java	(revision 16004)
+++ src/main/org/codehaus/groovy/runtime/typehandling/LongMath.java	(working copy)
@@ -27,19 +27,41 @@
 	private LongMath() {}
 					
 	protected Number absImpl(Number number) {
-		return new Long(Math.abs(number.longValue()));
+        long n = number.longValue();
+        if (n > Long.MIN_VALUE) {
+            return Long.valueOf(Math.abs(n));
+        }
+        return BigIntegerMath.INSTANCE.absImpl(number);
 	}
 	
 	public Number addImpl(Number left, Number right) {
-		return new Long(left.longValue() + right.longValue());
+        long l = left.longValue();
+        long r = right.longValue();
+        long v = l + r;
+        if ((v^l) >= 0 || (v^r) >= 0) {
+            return Long.valueOf(v);
+        }
+        return BigIntegerMath.INSTANCE.addImpl(left, right);
 	}
 
 	public Number subtractImpl(Number left, Number right) {
-		return new Long(left.longValue() - right.longValue());
+        long l = left.longValue();
+        long r = right.longValue();
+        long v = l - r;
+        if ((v^l) >= 0 || (v^~r) >= 0) {
+            return Long.valueOf(v);
+        }
+        return BigIntegerMath.INSTANCE.subtractImpl(left, right);
 	}
 
 	public Number multiplyImpl(Number left, Number right) {
-		return new Long(left.longValue() * right.longValue());
+        long l = left.longValue();
+        long r = right.longValue();
+        long v = l * r;
+        if (l == 0 || v/l == r) {
+            return Long.valueOf(v);
+        }
+        return BigIntegerMath.INSTANCE.multiplyImpl(left, right);
 	}
 
 	public Number divideImpl(Number left, Number right) {
@@ -53,46 +75,77 @@
 	}
 
 	protected Number intdivImpl(Number left, Number right) {
-        return new Long(left.longValue() / right.longValue());
+        return Long.valueOf(left.longValue() / right.longValue());
 	}
 	
     protected Number modImpl(Number left, Number right) {
-        return new Long(left.longValue() % right.longValue());
+        return Long.valueOf(left.longValue() % right.longValue());
     }
     
-    protected Number unaryMinusImpl(Number left) {
-        return new Long(-left.longValue());
+    protected Number unaryMinusImpl(Number number) {
+        long n = number.longValue();
+        if (n > Long.MIN_VALUE) {
+            return Long.valueOf(-n);
+        }
+        return BigIntegerMath.INSTANCE.unaryMinusImpl(number);
     }
     
     protected Number bitwiseNegateImpl(Number left) {
-        return new Long(~left.longValue());
+        return Long.valueOf(~left.longValue());
     }
     
     protected Number orImpl(Number left, Number right) {
-        return new Long(left.longValue() | right.longValue());
+        return Long.valueOf(left.longValue() | right.longValue());
     }
 
     protected Number andImpl(Number left, Number right) {
-        return new Long(left.longValue() & right.longValue());
+        return Long.valueOf(left.longValue() & right.longValue());
     }
     
     protected Number xorImpl(Number left, Number right) {
-        return new Long(left.longValue() ^ right.longValue());
+        return Long.valueOf(left.longValue() ^ right.longValue());
     }
     
     protected Number leftShiftImpl(Number left, Number right) {
-        return new Long(left.longValue() << right.longValue());
+        long l = left.longValue();
+        long r = right.longValue();
+        if (r < 0) {
+            throw new IllegalArgumentException("Shift distance must be non-negative, but " +  r + " was supplied");
+        }
+        if (r < 64 || l == 0 || r == 0) {
+            long v = l << r;
+            if (v >> r == l) {
+                return Long.valueOf(v);
+            }
+        }
+        return BigIntegerMath.INSTANCE.leftShiftImpl(left, right);
     }
 
     protected Number rightShiftImpl(Number left, Number right) {
-        return new Long(left.longValue() >> right.longValue());
+        long l = left.longValue();
+        long r = right.longValue();
+        if (r < 0) {
+            throw new IllegalArgumentException("Shift distance must be non-negative, but " +  r + " was supplied");
+        }
+        if (r >= 64) {
+            return Long.valueOf((l < 0) ? -1 : 0);
+        }
+        return Long.valueOf(l >> r);
     }
 
     protected Number rightShiftUnsignedImpl(Number left, Number right) {
-        return new Long(left.longValue() >>> right.longValue());
+        long l = left.longValue();
+        long r = right.longValue();
+        if (r < 0) {
+            throw new IllegalArgumentException("Shift distance must be non-negative, but " +  r + " was supplied");
+        }
+        if (r >= 64) {
+            return Long.valueOf(0);
+        }
+        return Long.valueOf(l >>> r);
     }
 
     protected Number bitAndImpl(Number left, Number right) {
-        return new Long(left.longValue() & right.longValue());
+        return Long.valueOf(left.longValue() & right.longValue());
     }
 }
Index: src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
===================================================================
--- src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java	(revision 16004)
+++ src/main/org/codehaus/groovy/runtime/DefaultGroovyMethods.java	(working copy)
@@ -8004,24 +8004,13 @@
      */
     //Note:  This method is NOT called if number is a BigInteger or BigDecimal because
     //those classes implement a method with a better exact match.
-    public static int abs(Number number) {
-        return Math.abs(number.intValue());
+    public static Number abs(Number number) {
+        return NumberMath.abs(number);
     }
 
     /**
      * Get the absolute value
      *
-     * @param number a Long
-     * @return the absolute value of that Long
-     * @since 1.0
-     */
-    public static long abs(Long number) {
-        return Math.abs(number.longValue());
-    }
-
-    /**
-     * Get the absolute value
-     *
      * @param number a Float
      * @return the absolute value of that Float
      * @since 1.0
@@ -8042,10 +8031,10 @@
     }
 
     /**
-     * Get the absolute value
+     * Round the value
      *
      * @param number a Float
-     * @return the absolute value of that Float
+     * @return the rounded value of that Float
      * @since 1.0
      */
     public static int round(Float number) {
@@ -8056,7 +8045,7 @@
      * Round the value
      *
      * @param number a Double
-     * @return the absolute value of that Double
+     * @return the rounded value of that Double
      * @since 1.0
      */
     public static long round(Double number) {
@@ -8483,7 +8472,7 @@
         } else if (self instanceof Float) {
             return new BigDecimal((Float)self).toBigInteger();
         } else {
-            return new BigInteger(Long.toString(self.longValue()));
+            return BigInteger.valueOf(self.longValue());
         }
     }
 
Index: src/main/org/codehaus/groovy/runtime/InvokerHelper.java
===================================================================
--- src/main/org/codehaus/groovy/runtime/InvokerHelper.java	(revision 16004)
+++ src/main/org/codehaus/groovy/runtime/InvokerHelper.java	(working copy)
@@ -224,12 +224,18 @@
 
     public static Object unaryMinus(Object value) {
         if (value instanceof Integer) {
-            Integer number = (Integer) value;
-            return Integer.valueOf(-number.intValue());
+            int n = ((Integer) value).intValue();
+            if (n > Integer.MIN_VALUE) {
+                return Integer.valueOf(-n);
+            }
+            return Long.valueOf(-((long)n));
         }
         if (value instanceof Long) {
-            Long number = (Long) value;
-            return new Long(-number.longValue());
+            long n = ((Long) value).longValue();
+            if (n > Long.MIN_VALUE) {
+                return Long.valueOf(-n);
+            }
+            return BigInteger.valueOf(n).negate();
         }
         if (value instanceof BigInteger) {
             return ((BigInteger) value).negate();
@@ -239,11 +245,11 @@
         }
         if (value instanceof Double) {
             Double number = (Double) value;
-            return new Double(-number.doubleValue());
+            return Double.valueOf(-number.doubleValue());
         }
         if (value instanceof Float) {
             Float number = (Float) value;
-            return new Float(-number.floatValue());
+            return Float.valueOf(-number.floatValue());
         }
         if (value instanceof ArrayList) {
             // value is an list.
@@ -660,7 +666,7 @@
         }
         if (value instanceof Long) {
             Long number = (Long) value;
-            return new Long(~number.longValue());
+            return Long.valueOf(~number.longValue());
         }
         if (value instanceof BigInteger) {
             return ((BigInteger) value).not();
