How can one add two long
values in Java so that if the result overflows then it is clamped to the range Long.MIN_VALUE
..Long.MAX_VALUE
?
For adding ints one can perform the arithmetic in long
precision and cast the result back to an int
, e.g.:
int saturatedAdd(int x, int y) {
long sum = (long) x + (long) y;
long clampedSum = Math.max((long) Integer.MIN_VALUE,
Math.min(sum, (long) Integer.MAX_VALUE));
return (int) clampedSum;
}
or
import com.google.common.primitives.Ints;
int saturatedAdd(int x, int y) {
long sum = (long) x + (long) y;
return Ints.saturatedCast(sum);
}
but in the case of long
there is no larger primitive type that can hold the intermediate (unclamped) sum.
Since this is Java, I cannot use inline assembly (in particular SSE's saturated add instructions.)
It can be implemented using BigInteger
, e.g.
static final BigInteger bigMin = BigInteger.valueOf(Long.MIN_VALUE);
static final BigInteger bigMax = BigInteger.valueOf(Long.MAX_VALUE);
long saturatedAdd(long x, long y) {
BigInteger sum = BigInteger.valueOf(x).add(BigInteger.valueOf(y));
return bigMin.max(sum).min(bigMax).longValue();
}
however performance is important so this method is not ideal (though useful for testing.)
I don't know whether avoiding branching can significantly affect performance in Java. I assume it can, but I would like to benchmark methods both with and without branching.
Related: http://stackoverflow.com/questions/121240/saturating-addition-in-c