Skip to content

Commit cd338fa

Browse files
java-team-github-botGoogle Java Core Libraries
authored and
Google Java Core Libraries
committedApr 22, 2022
Adds rotate() for arrays of ints.
RELNOTES=Adds rotate() for arrays of ints. PiperOrigin-RevId: 443706002
1 parent ac878a5 commit cd338fa

File tree

4 files changed

+286
-0
lines changed

4 files changed

+286
-0
lines changed
 

‎android/guava-tests/test/com/google/common/primitives/IntsTest.java

+97
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,103 @@ public void testReverseIndexed() {
342342
testReverse(new int[] {-1, 1, -2, 2}, 1, 3, new int[] {-1, -2, 1, 2});
343343
}
344344

345+
private static void testRotate(int[] input, int distance, int[] expectedOutput) {
346+
input = Arrays.copyOf(input, input.length);
347+
Ints.rotate(input, distance);
348+
assertThat(input).isEqualTo(expectedOutput);
349+
}
350+
351+
private static void testRotate(
352+
int[] input, int distance, int fromIndex, int toIndex, int[] expectedOutput) {
353+
input = Arrays.copyOf(input, input.length);
354+
Ints.rotate(input, distance, fromIndex, toIndex);
355+
assertThat(input).isEqualTo(expectedOutput);
356+
}
357+
358+
public void testRotate() {
359+
testRotate(new int[] {}, -1, new int[] {});
360+
testRotate(new int[] {}, 0, new int[] {});
361+
testRotate(new int[] {}, 1, new int[] {});
362+
363+
testRotate(new int[] {1}, -2, new int[] {1});
364+
testRotate(new int[] {1}, -1, new int[] {1});
365+
testRotate(new int[] {1}, 0, new int[] {1});
366+
testRotate(new int[] {1}, 1, new int[] {1});
367+
testRotate(new int[] {1}, 2, new int[] {1});
368+
369+
testRotate(new int[] {1, 2}, -3, new int[] {2, 1});
370+
testRotate(new int[] {1, 2}, -1, new int[] {2, 1});
371+
testRotate(new int[] {1, 2}, -2, new int[] {1, 2});
372+
testRotate(new int[] {1, 2}, 0, new int[] {1, 2});
373+
testRotate(new int[] {1, 2}, 1, new int[] {2, 1});
374+
testRotate(new int[] {1, 2}, 2, new int[] {1, 2});
375+
testRotate(new int[] {1, 2}, 3, new int[] {2, 1});
376+
377+
testRotate(new int[] {1, 2, 3}, -5, new int[] {3, 1, 2});
378+
testRotate(new int[] {1, 2, 3}, -4, new int[] {2, 3, 1});
379+
testRotate(new int[] {1, 2, 3}, -3, new int[] {1, 2, 3});
380+
testRotate(new int[] {1, 2, 3}, -2, new int[] {3, 1, 2});
381+
testRotate(new int[] {1, 2, 3}, -1, new int[] {2, 3, 1});
382+
testRotate(new int[] {1, 2, 3}, 0, new int[] {1, 2, 3});
383+
testRotate(new int[] {1, 2, 3}, 1, new int[] {3, 1, 2});
384+
testRotate(new int[] {1, 2, 3}, 2, new int[] {2, 3, 1});
385+
testRotate(new int[] {1, 2, 3}, 3, new int[] {1, 2, 3});
386+
testRotate(new int[] {1, 2, 3}, 4, new int[] {3, 1, 2});
387+
testRotate(new int[] {1, 2, 3}, 5, new int[] {2, 3, 1});
388+
389+
testRotate(new int[] {1, 2, 3, 4}, -9, new int[] {2, 3, 4, 1});
390+
testRotate(new int[] {1, 2, 3, 4}, -5, new int[] {2, 3, 4, 1});
391+
testRotate(new int[] {1, 2, 3, 4}, -1, new int[] {2, 3, 4, 1});
392+
testRotate(new int[] {1, 2, 3, 4}, 0, new int[] {1, 2, 3, 4});
393+
testRotate(new int[] {1, 2, 3, 4}, 1, new int[] {4, 1, 2, 3});
394+
testRotate(new int[] {1, 2, 3, 4}, 5, new int[] {4, 1, 2, 3});
395+
testRotate(new int[] {1, 2, 3, 4}, 9, new int[] {4, 1, 2, 3});
396+
397+
testRotate(new int[] {1, 2, 3, 4, 5}, -6, new int[] {2, 3, 4, 5, 1});
398+
testRotate(new int[] {1, 2, 3, 4, 5}, -4, new int[] {5, 1, 2, 3, 4});
399+
testRotate(new int[] {1, 2, 3, 4, 5}, -3, new int[] {4, 5, 1, 2, 3});
400+
testRotate(new int[] {1, 2, 3, 4, 5}, -1, new int[] {2, 3, 4, 5, 1});
401+
testRotate(new int[] {1, 2, 3, 4, 5}, 0, new int[] {1, 2, 3, 4, 5});
402+
testRotate(new int[] {1, 2, 3, 4, 5}, 1, new int[] {5, 1, 2, 3, 4});
403+
testRotate(new int[] {1, 2, 3, 4, 5}, 3, new int[] {3, 4, 5, 1, 2});
404+
testRotate(new int[] {1, 2, 3, 4, 5}, 4, new int[] {2, 3, 4, 5, 1});
405+
testRotate(new int[] {1, 2, 3, 4, 5}, 6, new int[] {5, 1, 2, 3, 4});
406+
}
407+
408+
public void testRotateIndexed() {
409+
testRotate(new int[] {}, 0, 0, 0, new int[] {});
410+
411+
testRotate(new int[] {1}, 0, 0, 1, new int[] {1});
412+
testRotate(new int[] {1}, 1, 0, 1, new int[] {1});
413+
testRotate(new int[] {1}, 1, 1, 1, new int[] {1});
414+
415+
// Rotate the central 5 elements, leaving the ends as-is
416+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, -6, 1, 6, new int[] {0, 2, 3, 4, 5, 1, 6});
417+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, -1, 1, 6, new int[] {0, 2, 3, 4, 5, 1, 6});
418+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, 0, 1, 6, new int[] {0, 1, 2, 3, 4, 5, 6});
419+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, 5, 1, 6, new int[] {0, 1, 2, 3, 4, 5, 6});
420+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, 14, 1, 6, new int[] {0, 2, 3, 4, 5, 1, 6});
421+
422+
// Rotate the first three elements
423+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, -2, 0, 3, new int[] {2, 0, 1, 3, 4, 5, 6});
424+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, -1, 0, 3, new int[] {1, 2, 0, 3, 4, 5, 6});
425+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, 0, 0, 3, new int[] {0, 1, 2, 3, 4, 5, 6});
426+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, 1, 0, 3, new int[] {2, 0, 1, 3, 4, 5, 6});
427+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, 2, 0, 3, new int[] {1, 2, 0, 3, 4, 5, 6});
428+
429+
// Rotate the last four elements
430+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, -6, 3, 7, new int[] {0, 1, 2, 5, 6, 3, 4});
431+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, -5, 3, 7, new int[] {0, 1, 2, 4, 5, 6, 3});
432+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, -4, 3, 7, new int[] {0, 1, 2, 3, 4, 5, 6});
433+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, -3, 3, 7, new int[] {0, 1, 2, 6, 3, 4, 5});
434+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, -2, 3, 7, new int[] {0, 1, 2, 5, 6, 3, 4});
435+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, -1, 3, 7, new int[] {0, 1, 2, 4, 5, 6, 3});
436+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, 0, 3, 7, new int[] {0, 1, 2, 3, 4, 5, 6});
437+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, 1, 3, 7, new int[] {0, 1, 2, 6, 3, 4, 5});
438+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, 2, 3, 7, new int[] {0, 1, 2, 5, 6, 3, 4});
439+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, 3, 3, 7, new int[] {0, 1, 2, 4, 5, 6, 3});
440+
}
441+
345442
public void testSortDescending() {
346443
testSortDescending(new int[] {}, new int[] {});
347444
testSortDescending(new int[] {1}, new int[] {1});

‎android/guava/src/com/google/common/primitives/Ints.java

+46
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,52 @@ public static void reverse(int[] array, int fromIndex, int toIndex) {
510510
}
511511
}
512512

513+
/**
514+
* Performs a right rotation of {@code array} of "distance" places, so that the first element is
515+
* moved to index "distance", and the element at index {@code i} ends up at index {@code (distance
516+
* + i) mod array.length}. This is equivalent to {@code Collections.rotate(Ints.asList(array),
517+
* distance)}, but is considerably faster and avoids allocation and garbage collection.
518+
*
519+
* <p>The provided "distance" may be negative, which will rotate left.
520+
*/
521+
public static void rotate(int[] array, int distance) {
522+
rotate(array, distance, 0, array.length);
523+
}
524+
525+
/**
526+
* Performs a right rotation of {@code array} between {@code fromIndex} inclusive and {@code
527+
* toIndex} exclusive. This is equivalent to {@code
528+
* Collections.rotate(Ints.asList(array).subList(fromIndex, toIndex), distance)}, but is
529+
* considerably faster and avoids allocations and garbage collection.
530+
*
531+
* <p>The provided "distance" may be negative, which will rotate left.
532+
*
533+
* @throws IndexOutOfBoundsException if {@code fromIndex < 0}, {@code toIndex > array.length}, or
534+
* {@code toIndex > fromIndex}
535+
*/
536+
public static void rotate(int[] array, int distance, int fromIndex, int toIndex) {
537+
checkNotNull(array);
538+
checkPositionIndexes(fromIndex, toIndex, array.length);
539+
if (array.length <= 1) {
540+
return;
541+
}
542+
543+
int length = toIndex - fromIndex;
544+
// Obtain m = (-distance mod length), a non-negative value less than "length". This is how many
545+
// places left to rotate.
546+
int m = -distance % length;
547+
m = (m < 0) ? m + length : m;
548+
// The current index of what will become the first element of the rotated section.
549+
int newFirstIndex = m + fromIndex;
550+
if (newFirstIndex == fromIndex) {
551+
return;
552+
}
553+
554+
reverse(array, fromIndex, newFirstIndex);
555+
reverse(array, newFirstIndex, toIndex);
556+
reverse(array, fromIndex, toIndex);
557+
}
558+
513559
/**
514560
* Returns an array containing each value of {@code collection}, converted to a {@code int} value
515561
* in the manner of {@link Number#intValue}.

‎guava-tests/test/com/google/common/primitives/IntsTest.java

+97
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,103 @@ public void testReverseIndexed() {
342342
testReverse(new int[] {-1, 1, -2, 2}, 1, 3, new int[] {-1, -2, 1, 2});
343343
}
344344

345+
private static void testRotate(int[] input, int distance, int[] expectedOutput) {
346+
input = Arrays.copyOf(input, input.length);
347+
Ints.rotate(input, distance);
348+
assertThat(input).isEqualTo(expectedOutput);
349+
}
350+
351+
private static void testRotate(
352+
int[] input, int distance, int fromIndex, int toIndex, int[] expectedOutput) {
353+
input = Arrays.copyOf(input, input.length);
354+
Ints.rotate(input, distance, fromIndex, toIndex);
355+
assertThat(input).isEqualTo(expectedOutput);
356+
}
357+
358+
public void testRotate() {
359+
testRotate(new int[] {}, -1, new int[] {});
360+
testRotate(new int[] {}, 0, new int[] {});
361+
testRotate(new int[] {}, 1, new int[] {});
362+
363+
testRotate(new int[] {1}, -2, new int[] {1});
364+
testRotate(new int[] {1}, -1, new int[] {1});
365+
testRotate(new int[] {1}, 0, new int[] {1});
366+
testRotate(new int[] {1}, 1, new int[] {1});
367+
testRotate(new int[] {1}, 2, new int[] {1});
368+
369+
testRotate(new int[] {1, 2}, -3, new int[] {2, 1});
370+
testRotate(new int[] {1, 2}, -1, new int[] {2, 1});
371+
testRotate(new int[] {1, 2}, -2, new int[] {1, 2});
372+
testRotate(new int[] {1, 2}, 0, new int[] {1, 2});
373+
testRotate(new int[] {1, 2}, 1, new int[] {2, 1});
374+
testRotate(new int[] {1, 2}, 2, new int[] {1, 2});
375+
testRotate(new int[] {1, 2}, 3, new int[] {2, 1});
376+
377+
testRotate(new int[] {1, 2, 3}, -5, new int[] {3, 1, 2});
378+
testRotate(new int[] {1, 2, 3}, -4, new int[] {2, 3, 1});
379+
testRotate(new int[] {1, 2, 3}, -3, new int[] {1, 2, 3});
380+
testRotate(new int[] {1, 2, 3}, -2, new int[] {3, 1, 2});
381+
testRotate(new int[] {1, 2, 3}, -1, new int[] {2, 3, 1});
382+
testRotate(new int[] {1, 2, 3}, 0, new int[] {1, 2, 3});
383+
testRotate(new int[] {1, 2, 3}, 1, new int[] {3, 1, 2});
384+
testRotate(new int[] {1, 2, 3}, 2, new int[] {2, 3, 1});
385+
testRotate(new int[] {1, 2, 3}, 3, new int[] {1, 2, 3});
386+
testRotate(new int[] {1, 2, 3}, 4, new int[] {3, 1, 2});
387+
testRotate(new int[] {1, 2, 3}, 5, new int[] {2, 3, 1});
388+
389+
testRotate(new int[] {1, 2, 3, 4}, -9, new int[] {2, 3, 4, 1});
390+
testRotate(new int[] {1, 2, 3, 4}, -5, new int[] {2, 3, 4, 1});
391+
testRotate(new int[] {1, 2, 3, 4}, -1, new int[] {2, 3, 4, 1});
392+
testRotate(new int[] {1, 2, 3, 4}, 0, new int[] {1, 2, 3, 4});
393+
testRotate(new int[] {1, 2, 3, 4}, 1, new int[] {4, 1, 2, 3});
394+
testRotate(new int[] {1, 2, 3, 4}, 5, new int[] {4, 1, 2, 3});
395+
testRotate(new int[] {1, 2, 3, 4}, 9, new int[] {4, 1, 2, 3});
396+
397+
testRotate(new int[] {1, 2, 3, 4, 5}, -6, new int[] {2, 3, 4, 5, 1});
398+
testRotate(new int[] {1, 2, 3, 4, 5}, -4, new int[] {5, 1, 2, 3, 4});
399+
testRotate(new int[] {1, 2, 3, 4, 5}, -3, new int[] {4, 5, 1, 2, 3});
400+
testRotate(new int[] {1, 2, 3, 4, 5}, -1, new int[] {2, 3, 4, 5, 1});
401+
testRotate(new int[] {1, 2, 3, 4, 5}, 0, new int[] {1, 2, 3, 4, 5});
402+
testRotate(new int[] {1, 2, 3, 4, 5}, 1, new int[] {5, 1, 2, 3, 4});
403+
testRotate(new int[] {1, 2, 3, 4, 5}, 3, new int[] {3, 4, 5, 1, 2});
404+
testRotate(new int[] {1, 2, 3, 4, 5}, 4, new int[] {2, 3, 4, 5, 1});
405+
testRotate(new int[] {1, 2, 3, 4, 5}, 6, new int[] {5, 1, 2, 3, 4});
406+
}
407+
408+
public void testRotateIndexed() {
409+
testRotate(new int[] {}, 0, 0, 0, new int[] {});
410+
411+
testRotate(new int[] {1}, 0, 0, 1, new int[] {1});
412+
testRotate(new int[] {1}, 1, 0, 1, new int[] {1});
413+
testRotate(new int[] {1}, 1, 1, 1, new int[] {1});
414+
415+
// Rotate the central 5 elements, leaving the ends as-is
416+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, -6, 1, 6, new int[] {0, 2, 3, 4, 5, 1, 6});
417+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, -1, 1, 6, new int[] {0, 2, 3, 4, 5, 1, 6});
418+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, 0, 1, 6, new int[] {0, 1, 2, 3, 4, 5, 6});
419+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, 5, 1, 6, new int[] {0, 1, 2, 3, 4, 5, 6});
420+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, 14, 1, 6, new int[] {0, 2, 3, 4, 5, 1, 6});
421+
422+
// Rotate the first three elements
423+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, -2, 0, 3, new int[] {2, 0, 1, 3, 4, 5, 6});
424+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, -1, 0, 3, new int[] {1, 2, 0, 3, 4, 5, 6});
425+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, 0, 0, 3, new int[] {0, 1, 2, 3, 4, 5, 6});
426+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, 1, 0, 3, new int[] {2, 0, 1, 3, 4, 5, 6});
427+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, 2, 0, 3, new int[] {1, 2, 0, 3, 4, 5, 6});
428+
429+
// Rotate the last four elements
430+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, -6, 3, 7, new int[] {0, 1, 2, 5, 6, 3, 4});
431+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, -5, 3, 7, new int[] {0, 1, 2, 4, 5, 6, 3});
432+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, -4, 3, 7, new int[] {0, 1, 2, 3, 4, 5, 6});
433+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, -3, 3, 7, new int[] {0, 1, 2, 6, 3, 4, 5});
434+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, -2, 3, 7, new int[] {0, 1, 2, 5, 6, 3, 4});
435+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, -1, 3, 7, new int[] {0, 1, 2, 4, 5, 6, 3});
436+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, 0, 3, 7, new int[] {0, 1, 2, 3, 4, 5, 6});
437+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, 1, 3, 7, new int[] {0, 1, 2, 6, 3, 4, 5});
438+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, 2, 3, 7, new int[] {0, 1, 2, 5, 6, 3, 4});
439+
testRotate(new int[] {0, 1, 2, 3, 4, 5, 6}, 3, 3, 7, new int[] {0, 1, 2, 4, 5, 6, 3});
440+
}
441+
345442
public void testSortDescending() {
346443
testSortDescending(new int[] {}, new int[] {});
347444
testSortDescending(new int[] {1}, new int[] {1});

‎guava/src/com/google/common/primitives/Ints.java

+46
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,52 @@ public static void reverse(int[] array, int fromIndex, int toIndex) {
512512
}
513513
}
514514

515+
/**
516+
* Performs a right rotation of {@code array} of "distance" places, so that the first element is
517+
* moved to index "distance", and the element at index {@code i} ends up at index {@code (distance
518+
* + i) mod array.length}. This is equivalent to {@code Collections.rotate(Ints.asList(array),
519+
* distance)}, but is considerably faster and avoids allocation and garbage collection.
520+
*
521+
* <p>The provided "distance" may be negative, which will rotate left.
522+
*/
523+
public static void rotate(int[] array, int distance) {
524+
rotate(array, distance, 0, array.length);
525+
}
526+
527+
/**
528+
* Performs a right rotation of {@code array} between {@code fromIndex} inclusive and {@code
529+
* toIndex} exclusive. This is equivalent to {@code
530+
* Collections.rotate(Ints.asList(array).subList(fromIndex, toIndex), distance)}, but is
531+
* considerably faster and avoids allocations and garbage collection.
532+
*
533+
* <p>The provided "distance" may be negative, which will rotate left.
534+
*
535+
* @throws IndexOutOfBoundsException if {@code fromIndex < 0}, {@code toIndex > array.length}, or
536+
* {@code toIndex > fromIndex}
537+
*/
538+
public static void rotate(int[] array, int distance, int fromIndex, int toIndex) {
539+
checkNotNull(array);
540+
checkPositionIndexes(fromIndex, toIndex, array.length);
541+
if (array.length <= 1) {
542+
return;
543+
}
544+
545+
int length = toIndex - fromIndex;
546+
// Obtain m = (-distance mod length), a non-negative value less than "length". This is how many
547+
// places left to rotate.
548+
int m = -distance % length;
549+
m = (m < 0) ? m + length : m;
550+
// The current index of what will become the first element of the rotated section.
551+
int newFirstIndex = m + fromIndex;
552+
if (newFirstIndex == fromIndex) {
553+
return;
554+
}
555+
556+
reverse(array, fromIndex, newFirstIndex);
557+
reverse(array, newFirstIndex, toIndex);
558+
reverse(array, fromIndex, toIndex);
559+
}
560+
515561
/**
516562
* Returns an array containing each value of {@code collection}, converted to a {@code int} value
517563
* in the manner of {@link Number#intValue}.

0 commit comments

Comments
 (0)
Please sign in to comment.