LongRangeSet (LongRangeSet multiplier, LongRangeType lrType) { if (multiplier.isEmpty()) return multiplier; if (myValue == 0) return this; if (myValue == 1) return multiplier; if (myValue == -1) return multiplier.negate(lrType); if (multiplier instanceof Point) { long val = ((Point)multiplier).myValue; long res = myValue * val; return point(lrType.cast(res)); } boolean overflow = false; long min = multiplier.min(); long max = multiplier.max(); if (lrType == LongRangeType.INT64) { try { min = Math.multiplyExact(min, myValue); max = Math.multiplyExact(max, myValue); } catch (ArithmeticException e) { overflow = true; } } else { assert lrType.bytes() <= 4; min *= myValue; max *= myValue; if (min != lrType.cast(min) || max != lrType.cast(max)) { overflow = true; } } LongRangeSet result; if (overflow) { result = lrType.fullRange(); } else { result = min > max ? range(max, min) : range(min, max); } long abs = Math.abs(myValue); if (overflow) { abs = Long.lowestOneBit(abs); } if (abs < 0 || (abs > Long.SIZE && Long.bitCount(abs) == 1)) { abs = Long.SIZE; } if (multiplier instanceof ModRange && ((ModRange)multiplier).myBits == 1 && abs < Long.SIZE) { int mod = ((ModRange)multiplier).myMod; abs *= overflow ? Long.lowestOneBit(mod) : mod; if (abs < 0 || (abs > Long.SIZE && Long.bitCount(abs) == 1)) { abs = Long.SIZE; } } return modRange(result.min(), result.max(), abs, 1L); }