You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by md...@apache.org on 2017/05/08 10:31:30 UTC

svn commit: r1794319 - in /jackrabbit/oak/trunk/oak-commons/src: main/java/org/apache/jackrabbit/oak/commons/IOUtils.java test/java/org/apache/jackrabbit/oak/commons/IOUtilsTest.java

Author: mduerig
Date: Mon May  8 10:31:30 2017
New Revision: 1794319

URL: http://svn.apache.org/viewvc?rev=1794319&view=rev
Log:
OAK-6164: IOUtils.nextPowerOf2() returns lower power of 2 for very high int values
Return long instead of in from nextPowerOf2 so we can cover the whole integer range uniformly.
Credits to Matt Ryan for the patch.

Modified:
    jackrabbit/oak/trunk/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/IOUtils.java
    jackrabbit/oak/trunk/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/IOUtilsTest.java

Modified: jackrabbit/oak/trunk/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/IOUtils.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/IOUtils.java?rev=1794319&r1=1794318&r2=1794319&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/IOUtils.java (original)
+++ jackrabbit/oak/trunk/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/IOUtils.java Mon May  8 10:31:30 2017
@@ -274,17 +274,20 @@ public final class IOUtils {
 
     /**
      * Get the value that is equal or higher than this value, and that is a
-     * power of two.
+     * power of two.  The returned value will be in the range [0, 2^31].
+     * If the input is less than zero, the result of 1 is returned (powers of
+     * negative numbers are not integer values).
      *
-     * @param x the original value
-     * @return the next power of two value
+     * @param x the original value.
+     * @return the next power of two value.  Results are always in the
+     * range [0, 2^31].
      */
-    public static int nextPowerOf2(int x) {
+    public static long nextPowerOf2(int x) {
         long i = 1;
-        while (i < x && i < (Integer.MAX_VALUE / 2)) {
+        while (i < x) {
             i += i;
         }
-        return (int) i;
+        return i;
     }
 
     /**

Modified: jackrabbit/oak/trunk/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/IOUtilsTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/IOUtilsTest.java?rev=1794319&r1=1794318&r2=1794319&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/IOUtilsTest.java (original)
+++ jackrabbit/oak/trunk/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/IOUtilsTest.java Mon May  8 10:31:30 2017
@@ -250,6 +250,30 @@ public class IOUtilsTest extends TestCas
         }
     }
 
+    public void testNextPowerOf2() {
+        assertEquals(1L, IOUtils.nextPowerOf2(0));
+        assertEquals(1L, IOUtils.nextPowerOf2(1));
+        assertEquals(2L, IOUtils.nextPowerOf2(2));
+        assertEquals(4L, IOUtils.nextPowerOf2(3));
+        assertEquals(4L, IOUtils.nextPowerOf2(4));
+        assertEquals(8L, IOUtils.nextPowerOf2(5));
+        assertEquals(8L, IOUtils.nextPowerOf2(7));
+        assertEquals(8L, IOUtils.nextPowerOf2(8));
+        assertEquals(16L, IOUtils.nextPowerOf2(12)); // it is powers of 2, not evens
+        assertEquals(32L, IOUtils.nextPowerOf2(21)); // random mid-range number
+
+        // Test values around the upper limit of powers of 2 in the signed int range
+        assertEquals(0x01L << (Integer.SIZE-2), IOUtils.nextPowerOf2(Integer.MAX_VALUE >> 1));
+        assertEquals(0x01L << (Integer.SIZE-2), IOUtils.nextPowerOf2((Integer.MAX_VALUE >> 1) + 1));
+        assertEquals( 0x01L << ((long)Integer.SIZE - 1L), IOUtils.nextPowerOf2((Integer.MAX_VALUE >> 1) + 2));
+        assertEquals(0x01L << ((long)Integer.SIZE - 1L), IOUtils.nextPowerOf2(Integer.MAX_VALUE));
+
+        // Negative values
+        assertEquals(1L, IOUtils.nextPowerOf2(-1));
+        assertEquals(1L, IOUtils.nextPowerOf2(-2));
+        assertEquals(1L, IOUtils.nextPowerOf2(Integer.MIN_VALUE));
+    }
+
     private static void testVarInt(int x, int expectedLen) throws IOException {
         ByteArrayOutputStream out = new ByteArrayOutputStream();
         IOUtils.writeVarInt(out, x);