Skip to content

Commit d67edbb

Browse files
zbynekcogman
andauthored
Faster implementation of long and int rotation (#10187)
I picked up the implementation by @cogman from gerrit and added a few testcases. Fixes #9563 Co-authored-by: Thomas May <[email protected]>
1 parent 5935a97 commit d67edbb

File tree

4 files changed

+24
-30
lines changed

4 files changed

+24
-30
lines changed

user/super/com/google/gwt/emul/java/lang/Integer.java

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -184,24 +184,15 @@ public static int reverseBytes(int i) {
184184
}
185185

186186
public static int rotateLeft(int i, int distance) {
187-
while (distance-- > 0) {
188-
i = i << 1 | ((i < 0) ? 1 : 0);
189-
}
190-
return i;
187+
int lowerBits = i >>> (SIZE - distance);
188+
int upperBits = i << distance;
189+
return upperBits | lowerBits;
191190
}
192191

193192
public static int rotateRight(int i, int distance) {
194-
int ui = i & MAX_VALUE; // avoid sign extension
195-
int carry = (i < 0) ? 0x40000000 : 0; // MIN_VALUE rightshifted 1
196-
while (distance-- > 0) {
197-
int nextcarry = ui & 1;
198-
ui = carry | (ui >> 1);
199-
carry = (nextcarry == 0) ? 0 : 0x40000000;
200-
}
201-
if (carry != 0) {
202-
ui = ui | MIN_VALUE;
203-
}
204-
return ui;
193+
int upperBits = i << (SIZE - distance);
194+
int lowerBits = i >>> distance;
195+
return upperBits | lowerBits;
205196
}
206197

207198
public static int signum(int i) {

user/super/com/google/gwt/emul/java/lang/Long.java

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -128,24 +128,15 @@ public static long reverseBytes(long l) {
128128
}
129129

130130
public static long rotateLeft(long i, int distance) {
131-
while (distance-- > 0) {
132-
i = i << 1 | ((i < 0) ? 1 : 0);
133-
}
134-
return i;
131+
long lowerBits = i >>> (SIZE - distance);
132+
long upperBits = i << distance;
133+
return upperBits | lowerBits;
135134
}
136135

137136
public static long rotateRight(long i, int distance) {
138-
long ui = i & MAX_VALUE; // avoid sign extension
139-
long carry = (i < 0) ? 0x4000000000000000L : 0; // MIN_VALUE rightshifted 1
140-
while (distance-- > 0) {
141-
long nextcarry = ui & 1;
142-
ui = carry | (ui >> 1);
143-
carry = (nextcarry == 0) ? 0 : 0x4000000000000000L;
144-
}
145-
if (carry != 0) {
146-
ui = ui | MIN_VALUE;
147-
}
148-
return ui;
137+
long upperBits = i << (SIZE - distance);
138+
long lowerBits = i >>> distance;
139+
return upperBits | lowerBits;
149140
}
150141

151142
public static int signum(long i) {

user/test/com/google/gwt/emultest/java/lang/IntegerTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,13 +234,19 @@ public void testRotateLeft() {
234234
assertEquals(-1, Integer.rotateLeft(-1, 4));
235235
assertEquals(Integer.MIN_VALUE, Integer.rotateLeft(0x40000000, 1));
236236
assertEquals(1, Integer.rotateLeft(Integer.MIN_VALUE, 1));
237+
assertEquals(Integer.MIN_VALUE, Integer.rotateLeft(Integer.MIN_VALUE, 0));
238+
assertEquals(Integer.MIN_VALUE, Integer.rotateLeft(1, -1));
239+
assertEquals(-1, Integer.rotateLeft(-1, 1000));
237240
}
238241

239242
public void testRotateRight() {
240243
assertEquals(0, Integer.rotateRight(0, 4));
241244
assertEquals(Integer.MIN_VALUE, Integer.rotateRight(1, 1));
242245
assertEquals(0x10000000, Integer.rotateRight(1, 4));
243246
assertEquals(-1, Integer.rotateRight(-1, 4));
247+
assertEquals(Integer.MIN_VALUE, Integer.rotateLeft(Integer.MIN_VALUE, 0));
248+
assertEquals(1, Integer.rotateRight(Integer.MIN_VALUE, -1));
249+
assertEquals(-1, Integer.rotateRight(-1, 1000));
244250
}
245251

246252
public void testSignum() {

user/test/com/google/gwt/emultest/java/lang/LongTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,13 +224,19 @@ public void testRotateLeft() {
224224
assertEquals(-1, Long.rotateLeft(-1, 4));
225225
assertEquals(Long.MIN_VALUE, Long.rotateLeft(0x4000000000000000L, 1));
226226
assertEquals(1, Long.rotateLeft(Long.MIN_VALUE, 1));
227+
assertEquals(Long.MIN_VALUE, Long.rotateLeft(Long.MIN_VALUE, 0));
228+
assertEquals(Long.MIN_VALUE, Long.rotateLeft(1, -1));
229+
assertEquals(-1, Long.rotateLeft(-1, 1000));
227230
}
228231

229232
public void testRotateRight() {
230233
assertEquals(0, Long.rotateRight(0, 4));
231234
assertEquals(Long.MIN_VALUE, Long.rotateRight(1, 1));
232235
assertEquals(0x1000000000000000L, Long.rotateRight(1, 4));
233236
assertEquals(-1, Long.rotateRight(-1, 4));
237+
assertEquals(Long.MIN_VALUE, Long.rotateRight(Long.MIN_VALUE, 0));
238+
assertEquals(1, Long.rotateRight(Long.MIN_VALUE, -1));
239+
assertEquals(-1, Long.rotateRight(-1, 1000));
234240
}
235241

236242
public void testSignum() {

0 commit comments

Comments
 (0)