This is an automated email from the ASF dual-hosted git repository. desruisseaux pushed a commit to branch geoapi-4.0 in repository https://gitbox.apache.org/repos/asf/sis.git
commit 40715a5f7c3913470593a36950cabad95ff9ed30 Author: Martin Desruisseaux <[email protected]> AuthorDate: Thu Jan 3 10:35:57 2019 +0100 Bug fix: wrong mask value if the number of dimensions is 64. --- .../src/main/java/org/apache/sis/io/wkt/Formatter.java | 2 +- .../java/org/apache/sis/metadata/sql/Dispatcher.java | 3 ++- .../java/org/apache/sis/geometry/CoordinateFormat.java | 3 ++- .../operation/transform/PassThroughTransform.java | 3 ++- .../java/org/apache/sis/internal/util/Numerics.java | 17 +++++++++++++++++ .../java/org/apache/sis/internal/netcdf/Variable.java | 3 ++- .../sis/internal/storage/io/ChannelDataOutput.java | 3 ++- 7 files changed, 28 insertions(+), 6 deletions(-) diff --git a/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Formatter.java b/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Formatter.java index 2089d58..033c40d 100644 --- a/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Formatter.java +++ b/core/sis-metadata/src/main/java/org/apache/sis/io/wkt/Formatter.java @@ -1613,7 +1613,7 @@ public class Formatter implements Localized { */ public boolean hasContextualUnit(final int depth) { ArgumentChecks.ensurePositive("depth", depth); - return (depth < Long.SIZE) && (hasContextualUnit & (1L << depth)) != 0; + return (hasContextualUnit & Numerics.bitmask(depth)) != 0; } /** diff --git a/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/Dispatcher.java b/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/Dispatcher.java index 6cc95e5..fa2a268 100644 --- a/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/Dispatcher.java +++ b/core/sis-metadata/src/main/java/org/apache/sis/metadata/sql/Dispatcher.java @@ -31,6 +31,7 @@ import org.apache.sis.metadata.KeyNamePolicy; import org.apache.sis.metadata.ValueExistencePolicy; import org.apache.sis.internal.system.Semaphores; import org.apache.sis.internal.metadata.Dependencies; +import org.apache.sis.internal.util.Numerics; /** @@ -206,7 +207,7 @@ final class Dispatcher implements InvocationHandler { throws ReflectiveOperationException, SQLException, MetadataStoreException { Object value = null; - final long nullBit = 1L << info.asIndexMap(source.standard).get(method.getName()); // Okay even if overflow. + final long nullBit = Numerics.bitmask(info.asIndexMap(source.standard).get(method.getName())); // Okay even if overflow. /* * The NULL_COLLECTION semaphore prevents creation of new empty collections by getter methods * (a consequence of lazy instantiation). The intent is to avoid creation of unnecessary objects diff --git a/core/sis-referencing/src/main/java/org/apache/sis/geometry/CoordinateFormat.java b/core/sis-referencing/src/main/java/org/apache/sis/geometry/CoordinateFormat.java index a535e81..7844846 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/geometry/CoordinateFormat.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/geometry/CoordinateFormat.java @@ -41,6 +41,7 @@ import org.opengis.referencing.cs.CoordinateSystemAxis; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.crs.TemporalCRS; import org.apache.sis.internal.util.LocalizedParseException; +import org.apache.sis.internal.util.Numerics; import org.apache.sis.util.resources.Errors; import org.apache.sis.util.ArgumentChecks; import org.apache.sis.util.CharSequences; @@ -365,7 +366,7 @@ public class CoordinateFormat extends CompoundFormat<DirectPosition> { * Returns {@code true} if the value at the given dimension needs to have its sign reversed. */ private boolean isNegative(final int dimension) { - return (dimension < Long.SIZE) && (negate & (1L << dimension)) != 0; + return (negate & Numerics.bitmask(dimension)) != 0; } /** diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/PassThroughTransform.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/PassThroughTransform.java index 6f98355..9fe1d1b 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/PassThroughTransform.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/PassThroughTransform.java @@ -30,6 +30,7 @@ import org.apache.sis.referencing.operation.matrix.Matrices; import org.apache.sis.referencing.operation.matrix.MatrixSIS; import org.apache.sis.internal.referencing.DirectPositionView; import org.apache.sis.internal.metadata.WKTKeywords; +import org.apache.sis.internal.util.Numerics; import org.apache.sis.geometry.GeneralDirectPosition; import org.apache.sis.io.wkt.Formatter; import org.apache.sis.util.ComparisonMode; @@ -796,7 +797,7 @@ public class PassThroughTransform extends AbstractMathTransform implements Seria * used operation in {@link #tryConcatenate(boolean, MathTransform, MathTransformFactory)}. */ private static long maskLowBits(final int n) { - return (1L << n) - 1; + return Numerics.bitmask(n) - 1; } /** diff --git a/core/sis-utility/src/main/java/org/apache/sis/internal/util/Numerics.java b/core/sis-utility/src/main/java/org/apache/sis/internal/util/Numerics.java index 60977d6..3e4e0bd 100644 --- a/core/sis-utility/src/main/java/org/apache/sis/internal/util/Numerics.java +++ b/core/sis-utility/src/main/java/org/apache/sis/internal/util/Numerics.java @@ -147,6 +147,23 @@ public final class Numerics extends Static { } /** + * Returns a mask with the given bit set. The bit should be a number from 0 inclusive to {@value Long#SIZE} exclusive. + * If the given bit is outside that range, then this method returns 0. The later condition is the main difference with + * the {@code 1L << bit} operation since {@code 1L << 64} computes 1. By contrast, {@code bitmask(64)} returns 0. + * + * <p>This method is invoked in contexts where we really need value 0 for a {@code bit} value of {@value Long#SIZE}. + * For example if we want to compute the maximal value of an unsigned integer of the given number of bits, we can use + * {@code bitmask(n) - 1}. If <var>n</var> = 64, then {@code bitmask(64) - 1} = -1 which is the desired value (the + * signed value -1 has the same bits pattern than the maximal possible value in unsigned integer representation).</p> + * + * @param bit the bit to set. + * @return a mask with the given bit set, or 0 if the given argument is negative or ≧ {@value Long#SIZE}. + */ + public static long bitmask(final int bit) { + return (bit >= 0 && bit < Long.SIZE) ? (1L << bit) : 0; + } + + /** * Returns the smallest (closest to negative infinity) long value that is greater than or equals to x/y. * * @param x the dividend. diff --git a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java index 9914d10..0e469e6 100644 --- a/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java +++ b/storage/sis-netcdf/src/main/java/org/apache/sis/internal/netcdf/Variable.java @@ -35,6 +35,7 @@ import org.apache.sis.measure.NumberRange; import org.apache.sis.util.Numbers; import org.apache.sis.util.ArraysExt; import org.apache.sis.util.collection.WeakHashSet; +import org.apache.sis.internal.util.Numerics; import org.apache.sis.internal.util.CollectionsExt; import org.apache.sis.util.logging.WarningListeners; import org.apache.sis.util.resources.Errors; @@ -505,7 +506,7 @@ public abstract class Variable extends NamedElement { final int size = dataType.size() * Byte.SIZE; if (size > 0 && size <= Long.SIZE) { long min = 0; - long max = (1L << size) - 1; + long max = Numerics.bitmask(size) - 1; if (!dataType.isUnsigned) { max >>>= 1; min = ~max; diff --git a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataOutput.java b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataOutput.java index 92ac00d..65d6272 100644 --- a/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataOutput.java +++ b/storage/sis-storage/src/main/java/org/apache/sis/internal/storage/io/ChannelDataOutput.java @@ -29,6 +29,7 @@ import java.nio.LongBuffer; import java.nio.ShortBuffer; import java.nio.channels.SeekableByteChannel; import java.nio.channels.WritableByteChannel; +import org.apache.sis.internal.util.Numerics; import org.apache.sis.internal.storage.Resources; import static org.apache.sis.util.ArgumentChecks.ensureBetween; @@ -171,7 +172,7 @@ public class ChannelDataOutput extends ChannelData implements Flushable { if (numBits != 0) { int bitOffset = getBitOffset(); if (bitOffset != 0) { - bits &= (1L << numBits) - 1; // Make sure that high-order bits are zero. + bits &= Numerics.bitmask(numBits) - 1; // Make sure that high-order bits are zero. final int r = numBits - (Byte.SIZE - bitOffset); /* * 'r' is the number of bits than we can not store in the current byte. This value may be negative,
