Skip to content

Commit

Permalink
Merge pull request #500 from apache/common_util_cleanup
Browse files Browse the repository at this point in the history
Consolidate / remove some duplicate code in datasketches/common/Util.
  • Loading branch information
leerho authored Jan 31, 2024
2 parents ff07407 + 2043519 commit 10f1048
Show file tree
Hide file tree
Showing 34 changed files with 135 additions and 185 deletions.
78 changes: 28 additions & 50 deletions src/main/java/org/apache/datasketches/common/Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -290,88 +290,66 @@ public static boolean isMultipleOf8AndGT0(final long v) {
//Powers of 2 or powers of base related

/**
* Returns true if given int argument is exactly a positive power of 2 and greater than zero.
* Returns true if given long argument is exactly a positive power of 2.
*
* @param powerOf2 The input argument.
* @return true if argument is exactly a positive power of 2 and greater than zero.
*/
public static boolean isIntPowerOf2(final int powerOf2) {
return powerOf2 > 0 && (powerOf2 & powerOf2 - 1) == 0; //or (v > 0) && ((v & -v) == v)
}

/**
* Returns true if given long argument is exactly a positive power of 2 and greater than zero.
*
* @param powerOf2 The input argument.
* @return true if argument is exactly a positive power of 2 and greater than zero.
*/
public static boolean isLongPowerOf2(final long powerOf2) {
return powerOf2 > 0 && (powerOf2 & powerOf2 - 1L) == 0; //or (v > 0) && ((v & -v) == v)
}

/**
* Checks the given int argument to make sure it is a positive power of 2 and greater than zero.
* If not it throws an exception with the user supplied local argument name.
* @param powerOf2 The input int argument must be a power of 2 and greater than zero.
* @param argName Used in the thrown exception.
* @throws SketchesArgumentException if not a power of 2 nor greater than zero.
* @param n The input argument.
* @return true if argument is exactly a positive power of 2.
*/
public static void checkIfIntPowerOf2(final int powerOf2, final String argName) {
if (isIntPowerOf2(powerOf2)) { return; }
throw new SketchesArgumentException("The value of the int argument \"" + argName + "\""
+ " must be a positive integer-power of 2" + " and greater than 0: " + powerOf2);
public static boolean isPowerOf2(final long n) {
return (n > 0) && ((n & (n - 1L)) == 0); //or (n > 0) && ((n & -n) == n)
}

/**
* Checks the given long argument to make sure it is a positive power of 2 and greater than zero.
* If not, it throws an exception with the user supplied local argument name.
* @param powerOf2 The input long argument must be a power of 2 and greater than zero.
* @param argName Used in the thrown exception.
* @throws SketchesArgumentException if not a power of 2 nor greater than zero.
* Checks the given long argument if it is a positive integer power of 2.
* If not, it throws an exception with the user supplied local argument name, if not null.
* @param n The input long argument must be a positive integer power of 2.
* @param argName Used in the thrown exception. It may be null.
* @throws SketchesArgumentException if not a positive integer power of 2.
*/
public static void checkIfLongPowerOf2(final long powerOf2, final String argName) {
if (isLongPowerOf2(powerOf2)) { return; }
throw new SketchesArgumentException("The value of the int argument \"" + argName + "\""
+ " must be a positive integer-power of 2" + " and greater than 0: " + powerOf2);
public static void checkIfPowerOf2(final long n, String argName) {
if (isPowerOf2(n)) { return; }
argName = (argName == null) ? "" : argName;
throw new SketchesArgumentException("The value of the argument \"" + argName + "\""
+ " must be a positive integer power of 2: " + n);
}

/**
* Computes the int ceiling power of 2 within the range [1, 2^30]. This is the smallest positive power
* of 2 that is equal to or greater than the given n and a mathematical integer.
* of 2 that is equal to or greater than the given n and a positive integer.
*
* <p>For:
* <ul>
* <li>n &le; 1: returns 1</li>
* <li>2^30 &le; n &le; 2^31 -1 : returns 2^30</li>
* <li>n == an exact power of 2 : returns n</li>
* <li>otherwise returns the smallest power of 2 &ge; n and equal to a mathematical integer</li>
* <li>otherwise returns the smallest power of 2 &ge; n and equal to a positive integer</li>
* </ul>
*
* @param n The input int argument.
* @return the ceiling power of 2.
*/
public static int ceilingIntPowerOf2(final int n) {
public static int ceilingPowerOf2(final int n) {
if (n <= 1) { return 1; }
final int topIntPwrOf2 = 1 << 30;
return n >= topIntPwrOf2 ? topIntPwrOf2 : Integer.highestOneBit(n - 1 << 1);
}

/**
* Computes the long ceiling power of 2 within the range [1, 2^62]. This is the smallest positive power
* of 2 that is equal to or greater than the given n and a mathematical long.
* of 2 that is equal to or greater than the given n and a positive long.
*
* <p>For:
* <ul>
* <li>n &le; 1: returns 1</li>
* <li>2^62 &le; n &le; 2^63 -1 : returns 2^62</li>
* <li>n == an exact power of 2 : returns n</li>
* <li>otherwise returns the smallest power of 2 &ge; n and equal to a mathematical integer</li>
* <li>otherwise returns the smallest power of 2 &ge; n and equal to a positive long</li>
* </ul>
*
* @param n The input long argument.
* @return the ceiling power of 2.
*/
public static long ceilingLongPowerOf2(final long n) {
public static long ceilingPowerOf2(final long n) {
if (n <= 1L) { return 1L; }
final long topIntPwrOf2 = 1L << 62;
return n >= topIntPwrOf2 ? topIntPwrOf2 : Long.highestOneBit(n - 1L << 1);
Expand All @@ -380,7 +358,7 @@ public static long ceilingLongPowerOf2(final long n) {
/**
* Computes the floor power of 2 given <i>n</i> is in the range [1, 2^31-1].
* This is the largest positive power of 2 that equal to or less than the given n and equal
* to a mathematical integer.
* to a positive integer.
*
* <p>For:
* <ul>
Expand All @@ -402,7 +380,7 @@ public static int floorPowerOf2(final int n) {
/**
* Computes the floor power of 2 given <i>n</i> is in the range [1, 2^63-1].
* This is the largest positive power of 2 that is equal to or less than the given <i>n</i> and
* equal to a mathematical integer.
* equal to a positive integer.
*
* <p>For:
* <ul>
Expand Down Expand Up @@ -534,7 +512,7 @@ public static double powerSeriesNextDouble(final int ppb, final double curPoint,
* Returns the ceiling of a given <i>n</i> given a <i>base</i>, where the ceiling is an integral power of the base.
* This is the smallest positive power of <i>base</i> that is equal to or greater than the given <i>n</i>
* and equal to a mathematical integer.
* The result of this function is consistent with {@link #ceilingIntPowerOf2(int)} for values
* The result of this function is consistent with {@link #ceilingPowerOf2(int)} for values
* less than one. I.e., if <i>n &lt; 1,</i> the result is 1.
*
* <p>The formula is: <i>base<sup>ceiling(log<sub>base</sub>(x))</sup></i></p>
Expand Down Expand Up @@ -622,7 +600,7 @@ public static int numberOfLeadingOnes(final long v) {
* @throws SketchesArgumentException if not a power of 2 nor greater than zero.
*/
public static int exactLog2OfInt(final int powerOf2, final String argName) {
checkIfIntPowerOf2(powerOf2, argName);
checkIfPowerOf2(powerOf2, argName);
return Integer.numberOfTrailingZeros(powerOf2);
}

Expand All @@ -635,7 +613,7 @@ public static int exactLog2OfInt(final int powerOf2, final String argName) {
* @throws SketchesArgumentException if not a power of 2 nor greater than zero.
*/
public static int exactLog2OfLong(final long powerOf2, final String argName) {
checkIfLongPowerOf2(powerOf2, argName);
checkIfPowerOf2(powerOf2, argName);
return Long.numberOfTrailingZeros(powerOf2);
}

Expand All @@ -646,7 +624,7 @@ public static int exactLog2OfLong(final long powerOf2, final String argName) {
* @return the log2 of the given int value if it is an exact power of 2 and greater than zero.
*/
public static int exactLog2OfInt(final int powerOf2) {
if (!isIntPowerOf2(powerOf2)) {
if (!isPowerOf2(powerOf2)) {
throw new SketchesArgumentException("Argument 'powerOf2' must be a positive power of 2.");
}
return Long.numberOfTrailingZeros(powerOf2);
Expand All @@ -659,7 +637,7 @@ public static int exactLog2OfInt(final int powerOf2) {
* @return the log2 of the given long value if it is an exact power of 2 and greater than zero.
*/
public static int exactLog2OfLong(final long powerOf2) {
if (!isLongPowerOf2(powerOf2)) {
if (!isPowerOf2(powerOf2)) {
throw new SketchesArgumentException("Argument 'powerOf2' must be a positive power of 2.");
}
return Long.numberOfTrailingZeros(powerOf2);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
package org.apache.datasketches.cpc;

import static org.apache.datasketches.common.Util.INVERSE_GOLDEN_U64;
import static org.apache.datasketches.common.Util.ceilingIntPowerOf2;
import static org.apache.datasketches.common.Util.ceilingPowerOf2;
import static org.apache.datasketches.common.Util.log2;
import static org.apache.datasketches.common.Util.powerSeriesNextDouble;
import static org.apache.datasketches.cpc.CompressedState.importFromMemory;
Expand Down Expand Up @@ -109,7 +109,7 @@ private void doRangeOfNAtLgK(final int lgK) {

while (n <= maxN) {
final double lgT = (slope * log2(n)) + lgMaxT;
final int totTrials = Math.max(ceilingIntPowerOf2((int) Math.pow(2.0, lgT)), (1 << lgMinT));
final int totTrials = Math.max(ceilingPowerOf2((int) Math.pow(2.0, lgT)), (1 << lgMinT));
doTrialsAtLgKAtN(lgK, n, totTrials);
n = Math.round(powerSeriesNextDouble(uPPO, n, true, 2.0));
}
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/apache/datasketches/fdt/PostProcessor.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

package org.apache.datasketches.fdt;

import static org.apache.datasketches.common.Util.ceilingIntPowerOf2;
import static org.apache.datasketches.common.Util.ceilingPowerOf2;
import static org.apache.datasketches.thetacommon.HashOperations.hashSearchOrInsert;
import static org.apache.datasketches.tuple.Util.stringHash;

Expand Down Expand Up @@ -64,7 +64,7 @@ public PostProcessor(final FdtSketch sketch, final Group group, final char sep)
this.sketch = sketch.copy();
this.sep = sep;
final int numEntries = sketch.getRetainedEntries();
mapArrSize = ceilingIntPowerOf2((int)(numEntries / 0.75));
mapArrSize = ceilingPowerOf2((int)(numEntries / 0.75));
hashArr = new long[mapArrSize];
priKeyArr = new String[mapArrSize];
counterArr = new int[mapArrSize];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import static org.apache.datasketches.common.Util.LS;
import static org.apache.datasketches.common.Util.checkBounds;
import static org.apache.datasketches.common.Util.exactLog2OfInt;
import static org.apache.datasketches.common.Util.isIntPowerOf2;
import static org.apache.datasketches.common.Util.isPowerOf2;
import static org.apache.datasketches.frequencies.PreambleUtil.EMPTY_FLAG_MASK;
import static org.apache.datasketches.frequencies.PreambleUtil.SER_VER;
import static org.apache.datasketches.frequencies.PreambleUtil.extractActiveItems;
Expand Down Expand Up @@ -321,7 +321,7 @@ public int getCurrentMapCapacity() {
* @return epsilon used to compute <i>a priori</i> error.
*/
public static double getEpsilon(final int maxMapSize) {
if (!isIntPowerOf2(maxMapSize)) {
if (!isPowerOf2(maxMapSize)) {
throw new SketchesArgumentException("maxMapSize is not a power of 2.");
}
return 3.5 / maxMapSize;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import static org.apache.datasketches.common.Util.LS;
import static org.apache.datasketches.common.Util.checkBounds;
import static org.apache.datasketches.common.Util.exactLog2OfInt;
import static org.apache.datasketches.common.Util.isIntPowerOf2;
import static org.apache.datasketches.common.Util.isPowerOf2;
import static org.apache.datasketches.frequencies.PreambleUtil.EMPTY_FLAG_MASK;
import static org.apache.datasketches.frequencies.PreambleUtil.SER_VER;
import static org.apache.datasketches.frequencies.PreambleUtil.extractActiveItems;
Expand Down Expand Up @@ -363,7 +363,7 @@ public int getCurrentMapCapacity() {
* @return epsilon used to compute <i>a priori</i> error.
*/
public static double getEpsilon(final int maxMapSize) {
if (!isIntPowerOf2(maxMapSize)) {
if (!isPowerOf2(maxMapSize)) {
throw new SketchesArgumentException("maxMapSize is not a power of 2.");
}
return 3.5 / maxMapSize;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
package org.apache.datasketches.hash;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.apache.datasketches.common.Util.ceilingIntPowerOf2;
import static org.apache.datasketches.common.Util.ceilingPowerOf2;
import static org.apache.datasketches.hash.MurmurHash3.hash;

import java.nio.ByteBuffer;
Expand Down Expand Up @@ -368,7 +368,7 @@ private static int asInteger(final long[] data, final int n) {
throw new SketchesStateException(
"Internal Error: Failed to find integer &lt; n within 10000 iterations.");
}
final long mask = ceilingIntPowerOf2(n) - 1;
final long mask = ceilingPowerOf2(n) - 1;
while (++cnt < 10000) {
final long[] h = MurmurHash3.hash(data, seed);
t = (int) (h[0] & mask);
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/apache/datasketches/hll/PreambleUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

package org.apache.datasketches.hll;

import static org.apache.datasketches.common.Util.ceilingIntPowerOf2;
import static org.apache.datasketches.common.Util.ceilingPowerOf2;
import static org.apache.datasketches.common.Util.exactLog2OfLong;
import static org.apache.datasketches.common.Util.zeroPad;
import static org.apache.datasketches.hll.HllUtil.LG_AUX_ARR_INTS;
Expand Down Expand Up @@ -460,7 +460,7 @@ static int computeLgArr(final Memory mem, final int count, final int lgConfigK)
//value is missing, recompute
final CurMode curMode = extractCurMode(mem);
if (curMode == CurMode.LIST) { return HllUtil.LG_INIT_LIST_SIZE; }
int ceilPwr2 = ceilingIntPowerOf2(count);
int ceilPwr2 = ceilingPowerOf2(count);
if ((RESIZE_DENOM * count) > (RESIZE_NUMER * ceilPwr2)) { ceilPwr2 <<= 1; }
if (curMode == CurMode.SET) {
return Math.max(LG_INIT_SET_SIZE, exactLog2OfLong(ceilPwr2));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

package org.apache.datasketches.hllmap;

import static org.apache.datasketches.common.Util.checkIfIntPowerOf2;
import static org.apache.datasketches.common.Util.checkIfPowerOf2;
import static org.apache.datasketches.common.Util.invPow2;

import java.util.Arrays;
Expand Down Expand Up @@ -266,7 +266,7 @@ int getCapacityCouponsPerEntry() {
}

private static final void checkMaxCouponsPerKey(final int maxCouponsPerKey) {
checkIfIntPowerOf2(maxCouponsPerKey, "maxCouponsPerKey");
checkIfPowerOf2(maxCouponsPerKey, "maxCouponsPerKey");
final int cpk = maxCouponsPerKey;
if ((cpk < 16) || (cpk > 256)) {
throw new SketchesArgumentException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
import static java.lang.Math.min;
import static java.lang.Math.pow;
import static java.lang.Math.round;
import static org.apache.datasketches.common.Util.ceilingIntPowerOf2;
import static org.apache.datasketches.common.Util.isIntPowerOf2;
import static org.apache.datasketches.common.Util.ceilingPowerOf2;
import static org.apache.datasketches.common.Util.isPowerOf2;
import static org.apache.datasketches.quantiles.PreambleUtil.COMPACT_FLAG_MASK;
import static org.apache.datasketches.quantiles.PreambleUtil.EMPTY_FLAG_MASK;
import static org.apache.datasketches.quantiles.PreambleUtil.ORDERED_FLAG_MASK;
Expand Down Expand Up @@ -104,7 +104,7 @@ public static int getKFromEpsilon(final double epsilon, final boolean pmf) {
* @param k must be greater than 1 and less than 65536 and a power of 2.
*/
static void checkK(final int k) {
if ((k < MIN_K) || (k > MAX_K) || !isIntPowerOf2(k)) {
if ((k < MIN_K) || (k > MAX_K) || !isPowerOf2(k)) {
throw new SketchesArgumentException(
"K must be >= " + MIN_K + " and <= " + MAX_K + " and a power of 2: " + k);
}
Expand Down Expand Up @@ -210,7 +210,7 @@ static int computeCombinedBufferItemCapacity(final int k, final long n) {
final int totLevels = computeNumLevelsNeeded(k, n);
if (totLevels == 0) {
final int bbItems = computeBaseBufferItems(k, n);
return Math.max(2 * MIN_K, ceilingIntPowerOf2(bbItems));
return Math.max(2 * MIN_K, ceilingPowerOf2(bbItems));
}
return (2 + totLevels) * k;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

package org.apache.datasketches.quantiles;

import static org.apache.datasketches.common.Util.checkIfIntPowerOf2;
import static org.apache.datasketches.common.Util.checkIfPowerOf2;
import static org.apache.datasketches.quantiles.PreambleUtil.EMPTY_FLAG_MASK;
import static org.apache.datasketches.quantiles.PreambleUtil.FLAGS_BYTE;

Expand Down Expand Up @@ -151,7 +151,7 @@ static void downSamplingMergeInto(final DoublesSketch src, final UpdateDoublesSk
}

final int downFactor = sourceK / targetK;
checkIfIntPowerOf2(downFactor, "source.getK()/target.getK() ratio");
checkIfPowerOf2(downFactor, "source.getK()/target.getK() ratio");
final int lgDownFactor = Integer.numberOfTrailingZeros(downFactor);

if (src.isEmpty()) { return; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

import static java.lang.Math.max;
import static java.lang.Math.min;
import static org.apache.datasketches.common.Util.ceilingIntPowerOf2;
import static org.apache.datasketches.common.Util.ceilingPowerOf2;
import static org.apache.datasketches.quantiles.ClassicUtil.MAX_PRELONGS;
import static org.apache.datasketches.quantiles.ClassicUtil.MIN_K;
import static org.apache.datasketches.quantiles.ClassicUtil.checkIsCompactMemory;
Expand Down Expand Up @@ -456,7 +456,7 @@ public static int getUpdatableStorageBytes(final int k, final long n) {
final int metaPre = MAX_PRELONGS + 2; //plus min, max
final int totLevels = computeNumLevelsNeeded(k, n);
if (n <= k) {
final int ceil = Math.max(ceilingIntPowerOf2((int)n), MIN_K * 2);
final int ceil = Math.max(ceilingPowerOf2((int)n), MIN_K * 2);
return metaPre + ceil << 3;
}
return metaPre + (2 + totLevels) * k << 3;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
package org.apache.datasketches.quantiles;

import static java.lang.System.arraycopy;
import static org.apache.datasketches.common.Util.checkIfIntPowerOf2;
import static org.apache.datasketches.common.Util.checkIfPowerOf2;

import java.util.Arrays;
import java.util.Comparator;
Expand Down Expand Up @@ -144,7 +144,7 @@ static <T> void downSamplingMergeInto(final ItemsSketch<T> src, final ItemsSketc
}

final int downFactor = sourceK / targetK;
checkIfIntPowerOf2(downFactor, "source.getK()/target.getK() ratio");
checkIfPowerOf2(downFactor, "source.getK()/target.getK() ratio");
final int lgDownFactor = Integer.numberOfTrailingZeros(downFactor);

final Object[] sourceLevels = src.getCombinedBuffer(); // aliasing is a bit dangerous
Expand Down
Loading

0 comments on commit 10f1048

Please sign in to comment.