LUCENE-10329: Use computed mask for DirectMonotonicReader#get (#553)

* use computed mask

* CHANGES

* use block mask for getBounds too

Co-authored-by: guofeng.my <guofeng.my@bytedance.com>
diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt
index 4003e88..4f0065f 100644
--- a/lucene/CHANGES.txt
+++ b/lucene/CHANGES.txt
@@ -104,6 +104,8 @@
 Optimizations
 ---------------------
 
+* LUCENE-10329: Use computed block mask for DirectMonotonicReader#get. (Guo Feng)
+
 * LUCENE-10280: Optimize BKD leaves' doc IDs codec when they are continuous. (Guo Feng)
 
 * LUCENE-10233: Store BKD leaves' doc IDs as bitset in some cases (typically for low cardinality fields
diff --git a/lucene/core/src/java/org/apache/lucene/util/packed/DirectMonotonicReader.java b/lucene/core/src/java/org/apache/lucene/util/packed/DirectMonotonicReader.java
index 7feb7bd..884c664 100644
--- a/lucene/core/src/java/org/apache/lucene/util/packed/DirectMonotonicReader.java
+++ b/lucene/core/src/java/org/apache/lucene/util/packed/DirectMonotonicReader.java
@@ -127,6 +127,7 @@
   }
 
   private final int blockShift;
+  private final long blockMask;
   private final LongValues[] readers;
   private final long[] mins;
   private final float[] avgs;
@@ -136,6 +137,7 @@
   private DirectMonotonicReader(
       int blockShift, LongValues[] readers, long[] mins, float[] avgs, byte[] bpvs) {
     this.blockShift = blockShift;
+    this.blockMask = (1L << blockShift) - 1;
     this.readers = readers;
     this.mins = mins;
     this.avgs = avgs;
@@ -157,7 +159,7 @@
   @Override
   public long get(long index) {
     final int block = (int) (index >>> blockShift);
-    final long blockIndex = index & ((1 << blockShift) - 1);
+    final long blockIndex = index & blockMask;
     final long delta = readers[block].get(blockIndex);
     return mins[block] + (long) (avgs[block] * blockIndex) + delta;
   }
@@ -165,7 +167,7 @@
   /** Get lower/upper bounds for the value at a given index without hitting the direct reader. */
   private long[] getBounds(long index) {
     final int block = Math.toIntExact(index >>> blockShift);
-    final long blockIndex = index & ((1 << blockShift) - 1);
+    final long blockIndex = index & blockMask;
     final long lowerBound = mins[block] + (long) (avgs[block] * blockIndex);
     final long upperBound = lowerBound + (1L << bpvs[block]) - 1;
     if (bpvs[block] == 64 || upperBound < lowerBound) { // overflow