blob: 212ba4270288b0f2af279eede2dda3e78272cbe7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
package org.eclipse.tracecompass.common.core.math;
/**
* Saturated arithmetic. These are mathematical helper functions that are used
* to clamp numbers to maximum and mimumum and avoid overflows.
*
* @author Matthew Khouzam
* @since 2.1
*/
public final class SaturatedArithmetic {
private SaturatedArithmetic() {
// do nothing
}
/**
* Saturated multiplication. It will not overflow but instead clamp the
* result to {@link Integer#MAX_VALUE} and {@link Integer#MIN_VALUE}.
*
* @param left
* The left int to multiply
* @param right
* The right int to multiply
* @return The saturated multiplication result. The mathematical, not Java
* version of Min(Max(MIN_VALUE, left*right), MAX_VALUE).
* @see <a href="http://en.wikipedia.org/wiki/Saturation_arithmetic">
* Saturation arithmetic</a>
*/
public static int multiply(int left, int right) {
int retVal = left * right;
if ((left != 0) && ((retVal / left) != right)) {
return (sameSign(left, right) ? Integer.MAX_VALUE : Integer.MIN_VALUE);
}
return retVal;
}
/**
* Saturated multiplication. It will not overflow but instead clamp the
* result to {@link Long#MAX_VALUE} and {@link Long#MIN_VALUE}.
*
* @param left
* The left long to multiply
* @param right
* The right long to multiply
* @return The saturated multiplication result. The mathematical, not Java
* version of Min(Max(MIN_VALUE, left*right), MAX_VALUE).
* @see <a href="http://en.wikipedia.org/wiki/Saturation_arithmetic">
* Saturation arithmetic</a>
*/
public static long multiply(long left, long right) {
long retVal = left * right;
if ((left != 0) && ((retVal / left) != right)) {
return (sameSign(left, right) ? Long.MAX_VALUE : Long.MIN_VALUE);
}
return retVal;
}
/**
* Saturated addition. It will not overflow but instead clamp the result to
* {@link Integer#MAX_VALUE} and {@link Integer#MIN_VALUE}.
*
* @param left
* The left int to add
* @param right
* The right int to add
* @return The saturated addition result. The mathematical, not Java version
* of Min(Max(MIN_VALUE, left+right), MAX_VALUE).
* @see <a href="http://en.wikipedia.org/wiki/Saturation_arithmetic">
* Saturation arithmetic</a>
*/
public static final int add(final int left, final int right) {
int retVal = left + right;
if (sameSign(left, right) && !sameSign(left, retVal)) {
if (retVal > 0 || left == Integer.MIN_VALUE) {
return Integer.MIN_VALUE;
}
return Integer.MAX_VALUE;
}
return retVal;
}
/**
* Saturated addition. It will not overflow but instead clamp the result to
* {@link Long#MAX_VALUE} and {@link Long#MIN_VALUE}.
*
* @param left
* The left long to add
* @param right
* The right long to add
* @return The saturated addition result. The mathematical, not Java version
* of Min(Max(MIN_VALUE, left+right), MAX_VALUE).
* @see <a href="http://en.wikipedia.org/wiki/Saturation_arithmetic">
* Saturation arithmetic</a>
*/
public static final long add(final long left, final long right) {
long retVal = left + right;
if (sameSign(left, right) && !sameSign(left, retVal)) {
if (retVal > 0 || left == Long.MIN_VALUE) {
return Long.MIN_VALUE;
}
return Long.MAX_VALUE;
}
return retVal;
}
/**
* Test if two numbers are the same sign or not
*
* @param left
* the left long
* @param right
* the right long
* @return true if both left and right are positive or both negative, false
* otherwise
*/
public static boolean sameSign(final long left, final long right) {
return (left ^ right) >= 0;
}
}