/**********************************************************************
Copyright (c) 2009-2010 Alexander Kerner. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
 ***********************************************************************/

package net.sf.kerner.utils.math;

import java.math.BigInteger;

/**
 * 
 * Perform arithmetic operations with number over- and underflow check. 
 * 
 * <p>
 * <b>Example:</b><br>
 *
 * </p>
 * <p>
 * <pre>
 * TODO example
 * </pre>
 * </p>
 *
 * @author <a href="mailto:alex.kerner.24@googlemail.com">Alexander Kerner</a>
 * @version 2010-11-22
 *
 */
public class ArithmeticSavety {

	public static final BigInteger BIG_MAX_INT = BigInteger
			.valueOf(Integer.MAX_VALUE);
	public static final BigInteger BIG_MIN_INT = BigInteger
			.valueOf(Integer.MIN_VALUE);

	public static final BigInteger BIG_MAX_LONG = BigInteger
			.valueOf(Long.MAX_VALUE);
	public static final BigInteger BIG_MIN_LONG = BigInteger
			.valueOf(Long.MIN_VALUE);

	/**
	 * 
	 * 
	 * Check if {@code {@link Integer#MIN_VALUE} <= {@code b} <=
	 * {@link Integer#MAX_VALUE}}.
	 * 
	 * @param b
	 *            {@code BigInteger} to check if in range
	 * @see BigInteger
	 */
	public static void rangeCheckInteger(BigInteger b) {
		if (b.compareTo(BIG_MAX_INT) == 1 || b.compareTo(BIG_MIN_INT) == -1)
			throw new ArithmeticException("Integer overflow");
	}

	/**
	 * 
	 * 
	 * Check if {@code {@link Long#MIN_VALUE} <= {@code b} <= {@link Long#MAX_VALUE}}.
	 * 
	 * @param b
	 *            {@code BigInteger} to check if in range
	 * @see BigInteger
	 */
	public static void rangeCheckLong(BigInteger b) {
		if (b.compareTo(BIG_MAX_LONG) == 1 || b.compareTo(BIG_MIN_LONG) == -1)
			throw new ArithmeticException("Long overflow");
	}

	/**
	 * 
	 * Perform addition of two {@code int} values with arithmetic safety. if
	 * resulting {@code int} would over- or underflow an exception will be
	 * thrown.
	 * 
	 * @param a
	 *            first value
	 * @param b
	 *            second value
	 * @return {@code a + b}
	 */
	public static int addInt(int a, int b) {
		final BigInteger bb = BigInteger.valueOf(a).add(BigInteger.valueOf(b));
		rangeCheckInteger(bb);
		return bb.intValue();
	}

	/**
	 * 
	 * Perform addition of two {@code long} values with arithmetic safety. if
	 * resulting {@code long} would over- or underflow an exception will be
	 * thrown.
	 * 
	 * @param a
	 *            first value
	 * @param b
	 *            second value
	 * @return {@code a + b}
	 */
	public static long addLong(long a, long b) {
		final BigInteger bb = BigInteger.valueOf(a).add(BigInteger.valueOf(b));
		rangeCheckLong(bb);
		return bb.longValue();
	}

	/**
	 * 
	 * Perform multiplication of two {@code long} values with arithmetic safety.
	 * if resulting {@code long} would over- or underflow an exception will be
	 * thrown.
	 * 
	 * @param a
	 *            first value
	 * @param b
	 *            second value
	 * @return {@code a * b}
	 */
	public static int multiply(int a, int b) {
		final BigInteger bb = BigInteger.valueOf(a).multiply(
				BigInteger.valueOf(b));
		rangeCheckInteger(bb);
		return bb.intValue();
	}

	/**
	 * 
	 * Perform multiplication of two {@code long} values with arithmetic safety.
	 * if resulting {@code long} would over- or underflow an exception will be
	 * thrown.
	 * 
	 * @param a
	 *            first value
	 * @param b
	 *            second value
	 * @return {@code a * b}
	 */
	public static long multiply(long a, long b) {
		final BigInteger bb = BigInteger.valueOf(a).multiply(
				BigInteger.valueOf(b));
		rangeCheckLong(bb);
		return bb.longValue();
	}

	/**
	 * 
	 * Increment a {@code BigInteger} with arithmetic safety.
	 * 
	 * @param integer
	 *            {@code BigInteger} to increment
	 * @return incremented {@code BigInteger}
	 */
	public static Integer increment(Integer integer) {
		return Integer.valueOf(addInt(integer.intValue(), 1));
	}

	/**
	 * 
	 * Add one {@link Integer} to another {@link Integer} with arithmetic
	 * safety.
	 * 
	 * @param integer1
	 *            first value
	 * @param integer2
	 *            second value
	 * @return {@code a + b}
	 */
	public static Integer add(Integer integer1, Integer integer2) {
		return Integer
				.valueOf(addInt(integer1.intValue(), integer2.intValue()));
	}

}

@@ -762,16 +762,45 @@
 .math;%0A%0A
+import java.math.BigDecimal;%0A
 import j
@@ -820,16 +820,16 @@
 nteger;%0A
-
 %0A/**%0A * 
@@ -1494,16 +1494,194 @@
 _VALUE);
+%0A%09%0A%09public static final BigDecimal BIG_MAX_DECIMAL = BigDecimal.valueOf(Double.MAX_VALUE);%0A%09public static final BigDecimal BIG_MIN_DECIMAL = BigDecimal.valueOf(Double.MIN_VALUE);
 %0A%0A%09/**%0A%09
@@ -2419,20 +2419,211 @@
 eption(%22
-Long
+Double overflow%22);%0A%09%7D%0A%09%0A%09public static void rangeCheckDouble(BigDecimal b)%7B%0A%09%09if (b.compareTo(BIG_MAX_DECIMAL) == 1 %7C%7C b.compareTo(BIG_MIN_DECIMAL) == -1)%0A%09%09%09throw new ArithmeticException(%22Double
  overflo
@@ -4455,32 +4455,32 @@
 eCheckLong(bb);%0A
-
 %09%09return bb.long
@@ -4482,32 +4482,225 @@
 .longValue();%0A%09%7D
+%0A%09%0A%09public static double multiply(double a, double b) %7B%0A%09%09final BigDecimal bb = BigDecimal.valueOf(a).multiply(%0A%09%09%09%09BigDecimal.valueOf(b));%0A%09%09rangeCheckDouble(bb);%0A%09%09return bb.doubleValue();%0A%09%7D
 %0A%0A%09/**%0A%09 * %0A%09 * 

Introduce ArithmeticSavety#multiply(double,double), #rangeChechDouble(BigDecimal).