Skip to content

Commit 0d85f00

Browse files
committed
[CALCITE-7639] Normalize shift amounts with a JDK 8 compatible positiveModulo helper
An earlier commit made the shift amount a long and normalized it with Math.floorMod(y, <int width>). Math.floorMod(long, int) was only added in JDK 9, so on JDK 8 the call resolves to Math.floorMod(long, long) (returning long) and does not compile when assigned to an int ('incompatible types: possible lossy conversion from long to int'). Introduce a private positiveModulo(long, int) helper that widens to Math.floorMod(long, long) and narrows the result (always in [0, m)) back to int, and route all shift-amount normalizations through it. This keeps the JDK 8 build working and factors the modulo into a single named helper.
1 parent 4add3af commit 0d85f00

1 file changed

Lines changed: 29 additions & 14 deletions

File tree

core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3772,6 +3772,21 @@ private static ByteString binaryOperator(
37723772
return new ByteString(result);
37733773
}
37743774

3775+
/**
3776+
* Returns {@code x} modulo {@code m}, normalized to the range {@code [0, m)}
3777+
* (unlike {@code %}, the result is never negative). Used to normalize a shift
3778+
* amount to the bit width of the value being shifted.
3779+
*
3780+
* @param x the value (typically a shift amount, which may be negative)
3781+
* @param m the modulus, which must be positive (typically a bit width)
3782+
* @return {@code x} modulo {@code m}, in the range {@code [0, m)}
3783+
*/
3784+
private static int positiveModulo(long x, int m) {
3785+
// Math.floorMod(long, int) is only available since JDK 9, so widen to
3786+
// Math.floorMod(long, long) and narrow the result (always in [0, m)) to int.
3787+
return (int) Math.floorMod(x, (long) m);
3788+
}
3789+
37753790
/**
37763791
* Performs PostgresSQL-style bitwise shift on a 32-bit integer.
37773792
*
@@ -3780,7 +3795,7 @@ private static ByteString binaryOperator(
37803795
* @return the shifted integer
37813796
*/
37823797
public static int leftShift(int x, long y) {
3783-
int shift = Math.floorMod(y, 32); // normalize to 0~31
3798+
int shift = positiveModulo(y, 32); // normalize to 0~31
37843799
return y >= 0 ? x << shift : x >> shift; // arithmetic right shift
37853800
}
37863801

@@ -3794,7 +3809,7 @@ public static int leftShift(int x, long y) {
37943809
* @return the shifted long value
37953810
*/
37963811
public static long leftShift(long x, long y) {
3797-
int shift = Math.floorMod(y, 64); // normalize to 0~63
3812+
int shift = positiveModulo(y, 64); // normalize to 0~63
37983813
return y >= 0 ? x << shift : x >> shift;
37993814
}
38003815

@@ -3816,7 +3831,7 @@ public static byte[] leftShift(byte[] bytes, long y) {
38163831

38173832
// PostgreSQL behavior: always treat as left shift with modulo arithmetic
38183833
// Negative y becomes equivalent positive shift
3819-
int shift = Math.floorMod(y, bitLen);
3834+
int shift = positiveModulo(y, bitLen);
38203835

38213836
if (shift == 0) {
38223837
return bytes.clone();
@@ -3863,7 +3878,7 @@ public static ByteString leftShift(ByteString bytes, long y) {
38633878
* Overflow bits are masked to 8 bits.
38643879
*/
38653880
public static UByte leftShift(UByte x, long y) {
3866-
int shift = Math.floorMod(y, 8);
3881+
int shift = positiveModulo(y, 8);
38673882
int val = x.byteValue() & 0xFF;
38683883
val = (y >= 0) ? (val << shift) & 0xFF : (val >> shift) & 0xFF;
38693884
return UByte.valueOf((byte) val);
@@ -3874,7 +3889,7 @@ public static UByte leftShift(UByte x, long y) {
38743889
* Overflow bits are masked to 16 bits.
38753890
*/
38763891
public static UShort leftShift(UShort x, long y) {
3877-
int shift = Math.floorMod(y, 16);
3892+
int shift = positiveModulo(y, 16);
38783893
int val = x.shortValue() & 0xFFFF;
38793894
val = (y >= 0) ? (val << shift) & 0xFFFF : (val >> shift) & 0xFFFF;
38803895
return UShort.valueOf((short) val);
@@ -3885,7 +3900,7 @@ public static UShort leftShift(UShort x, long y) {
38853900
* Overflow bits are masked to 32 bits.
38863901
*/
38873902
public static UInteger leftShift(UInteger x, long y) {
3888-
int shift = Math.floorMod(y, 32);
3903+
int shift = positiveModulo(y, 32);
38893904
long val = x.longValue() & 0xFFFFFFFFL;
38903905
val = (y >= 0) ? (val << shift) & 0xFFFFFFFFL : (val >> shift) & 0xFFFFFFFFL;
38913906
return UInteger.valueOf(val);
@@ -3896,7 +3911,7 @@ public static UInteger leftShift(UInteger x, long y) {
38963911
* Overflow bits are masked to 64 bits (long shifts naturally truncate).
38973912
*/
38983913
public static ULong leftShift(ULong x, long y) {
3899-
int shift = Math.floorMod(y, 64);
3914+
int shift = positiveModulo(y, 64);
39003915
long val = x.longValue();
39013916
val = (y >= 0) ? val << shift : val >> shift;
39023917
return ULong.valueOf(val);
@@ -3910,7 +3925,7 @@ public static ULong leftShift(ULong x, long y) {
39103925
* @return the shifted integer
39113926
*/
39123927
public static int rightShift(int x, long y) {
3913-
int shift = Math.floorMod(y, 32); // normalize to 0~31
3928+
int shift = positiveModulo(y, 32); // normalize to 0~31
39143929
return y >= 0 ? x >> shift : x << shift; // arithmetic right shift
39153930
}
39163931

@@ -3924,7 +3939,7 @@ public static int rightShift(int x, long y) {
39243939
* @return the shifted long value
39253940
*/
39263941
public static long rightShift(long x, long y) {
3927-
int shift = Math.floorMod(y, 64); // normalize to 0~63
3942+
int shift = positiveModulo(y, 64); // normalize to 0~63
39283943
return y >= 0 ? x >> shift : x << shift;
39293944
}
39303945

@@ -3946,7 +3961,7 @@ public static byte[] rightShift(byte[] bytes, long y) {
39463961

39473962
// PostgreSQL behavior: always treat as right shift with modulo arithmetic
39483963
// Negative y becomes equivalent positive shift
3949-
int shift = Math.floorMod(y, bitLen);
3964+
int shift = positiveModulo(y, bitLen);
39503965

39513966
if (shift == 0) {
39523967
return bytes.clone();
@@ -3993,7 +4008,7 @@ public static ByteString rightShift(ByteString bytes, long y) {
39934008
* Overflow bits are masked to 8 bits.
39944009
*/
39954010
public static UByte rightShift(UByte x, long y) {
3996-
int shift = Math.floorMod(y, 8);
4011+
int shift = positiveModulo(y, 8);
39974012
int val = x.byteValue() & 0xFF;
39984013
val = (y >= 0) ? (val >> shift) & 0xFF : (val << shift) & 0xFF;
39994014
return UByte.valueOf((byte) val);
@@ -4004,7 +4019,7 @@ public static UByte rightShift(UByte x, long y) {
40044019
* Overflow bits are masked to 16 bits.
40054020
*/
40064021
public static UShort rightShift(UShort x, long y) {
4007-
int shift = Math.floorMod(y, 16);
4022+
int shift = positiveModulo(y, 16);
40084023
int val = x.shortValue() & 0xFFFF;
40094024
val = (y >= 0) ? (val >> shift) & 0xFFFF : (val << shift) & 0xFFFF;
40104025
return UShort.valueOf((short) val);
@@ -4015,7 +4030,7 @@ public static UShort rightShift(UShort x, long y) {
40154030
* Overflow bits are masked to 32 bits.
40164031
*/
40174032
public static UInteger rightShift(UInteger x, long y) {
4018-
int shift = Math.floorMod(y, 32);
4033+
int shift = positiveModulo(y, 32);
40194034
long val = x.longValue() & 0xFFFFFFFFL;
40204035
val = (y >= 0) ? (val >> shift) & 0xFFFFFFFFL : (val << shift) & 0xFFFFFFFFL;
40214036
return UInteger.valueOf(val);
@@ -4026,7 +4041,7 @@ public static UInteger rightShift(UInteger x, long y) {
40264041
* Overflow bits are masked to 64 bits (long shifts naturally truncate).
40274042
*/
40284043
public static ULong rightShift(ULong x, long y) {
4029-
int shift = Math.floorMod(y, 64);
4044+
int shift = positiveModulo(y, 64);
40304045
long val = x.longValue();
40314046
val = (y >= 0) ? val >> shift : val << shift;
40324047
return ULong.valueOf(val);

0 commit comments

Comments
 (0)