• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.storage.util;
18 
19 /** Utility functions for bit twiddling. */
20 public final class BitwiseUtils {
21 
22     // [0]  = ...00001
23     // [1]  = ...00010
24     // [63] = 10000...
25     private static final long[] SINGLE_BIT_MASK;
26 
27     static {
28         SINGLE_BIT_MASK = new long[64];
29         long bit = 1;
30         for (int i = 0; i < 64; i++) {
31             SINGLE_BIT_MASK[i] = bit;
32             bit <<= 1;
33         }
34     }
35 
36     // [{How many LSB bits are 1}] = mask
37     // [0]  = 00...000
38     // [1]  = 00...001
39     // [2]  = 00...011
40     // [3]  = 00...111
41     // ...
42     // [63] = 01...111
43     // [64] = 11...111
44     private static final long[] LOW_BITS_MASK;
45 
46     static {
47         LOW_BITS_MASK = new long[65];
48         long value = 0;
49         for (int i = 0; i < 65; i++) {
50             LOW_BITS_MASK[i] = value;
51             value = (value << 1) | 1;
52         }
53     }
54 
55     // [{How many MSB bits are 1}] = mask
56     // [0]  = 000...00
57     // [1]  = 100...00
58     // [2]  = 110...00
59     // [3]  = 111...00
60     // ...
61     // [63] = 111...10
62     // [64] = 111...11
63     private static final long[] HIGH_BITS_MASK;
64 
65     static {
66         HIGH_BITS_MASK = new long[65];
67         long value = ~0;
68         for (int i = 0; i < 65; i++) {
69             HIGH_BITS_MASK[64 - i] = value;
70             value <<= 1;
71         }
72     }
73 
BitwiseUtils()74     private BitwiseUtils() {
75     }
76 
77     /**
78      * Returns a mask covering the specified number of "low" bits. {@code bitCount} must be between
79      * 0 and 64 inclusive. An argument of zero returns a mask with no bits set. Otherwise, numbering
80      * bits from LSB = 0, this method returns bits 0 to (bitCount - 1) set to 1.
81      */
getLowBitsMask(int bitCount)82     public static long getLowBitsMask(int bitCount) {
83         if (bitCount < 0 || bitCount > 64) {
84             throw new IllegalArgumentException("bitCount " + bitCount + " out of range");
85         }
86         // Bits | Bit pattern
87         //    1 | 000...001
88         //    2 | 000...011
89         //    3 | 000...111
90         // ...
91         //   63 | 011...111
92         //   64 | 111...111
93         return LOW_BITS_MASK[bitCount];
94     }
95 
96     /**
97      * Returns (only) the {@code highBits} set of a {@code totalBitCount} value.
98      */
getMidBitsMask(int totalBitCount, int highBitCount)99     public static long getMidBitsMask(int totalBitCount, int highBitCount) {
100         if (totalBitCount < 1 || totalBitCount > 64) {
101             throw new IllegalArgumentException("totalBitCount " + totalBitCount + " out of range");
102         }
103         if (highBitCount < 1 || highBitCount > totalBitCount) {
104             throw new IllegalArgumentException("highBitCount " + highBitCount + " out of range");
105         }
106         return HIGH_BITS_MASK[(64 - totalBitCount) + highBitCount] & LOW_BITS_MASK[totalBitCount];
107     }
108 
109     /**
110      * Returns the most significant {@code highBits} bits of a long.
111      */
getHighBitsMask(int bitCount)112     public static long getHighBitsMask(int bitCount) {
113         if (bitCount < 1 || bitCount > 64) {
114             throw new IllegalArgumentException("bitCount " + bitCount + " out of range");
115         }
116         return HIGH_BITS_MASK[bitCount];
117     }
118 
119     /** Returns the least significant {@code bitCount} bits of the specified value. */
extractLowBits(int bitCount, long value)120     public static long extractLowBits(int bitCount, long value) {
121         if (bitCount < 1 || bitCount > 64) {
122             throw new IllegalArgumentException("bitCount " + bitCount + " out of range");
123         } else if (bitCount == 64) {
124             return value;
125         }
126         long mask = getLowBitsMask(bitCount);
127         return mask & value;
128     }
129 
130     /**
131      * Returns a mask with only the numbered bit set to 1. Bits are numbered from LSB = 0 to
132      * MSB = {type width - 1}.
133      */
getSingleBitMask(int bit)134     public static long getSingleBitMask(int bit) {
135         if (bit < 0 || bit > 63) {
136             throw new IllegalArgumentException("bit " + bit + " out of range");
137         }
138         return SINGLE_BIT_MASK[bit];
139     }
140 
141     /**
142      * Throws an {@link IllegalArgumentException} if value is outside of the range representable in
143      * {@code bitCount} bits as a signed or unsigned integer. Bit count must be between 1 and 64,
144      * inclusive otherwise an {@link IllegalArgumentException} is thrown.
145      */
checkValueInRange(int bitCount, long value, boolean signedValue)146     public static void checkValueInRange(int bitCount, long value, boolean signedValue) {
147         if (signedValue) {
148             checkSignedValueInRange(bitCount, value);
149         } else {
150             checkUnsignedValueInRange(bitCount, value);
151         }
152     }
153 
154     /**
155      * Throws an {@link IllegalArgumentException} if value is outside of the range representable in
156      * {@code bitCount} bits as a signed integer. Bit count must be between 1 and 64, inclusive
157      * otherwise an {@link IllegalArgumentException} is thrown.
158      */
checkSignedValueInRange(int bitCount, long value)159     public static void checkSignedValueInRange(int bitCount, long value) {
160         if (bitCount < 1 || bitCount > 64) {
161             throw new IllegalArgumentException("bitCount " + bitCount + " out of range");
162         }
163         long minSignedValue = minSignedValue(bitCount);
164         long maxSignedValue = maxSignedValue(bitCount);
165         if (value < minSignedValue || value > maxSignedValue) {
166             throw new IllegalArgumentException("value " + value + " out of range");
167         }
168     }
169 
170     /**
171      * Throws an {@link IllegalArgumentException} if value is outside of the range representable in
172      * {@code bitCount} bits as a signed integer. Bit count must be between 1 and 64, inclusive
173      * otherwise an {@link IllegalArgumentException} is thrown.
174      */
checkUnsignedValueInRange(int bitCount, long value)175     public static void checkUnsignedValueInRange(int bitCount, long value) {
176         if (bitCount < 0 || bitCount > 63) {
177             throw new IllegalArgumentException("bitCount " + bitCount + " out of range");
178         }
179         long maxUnsignedValue = maxUnsignedValue(bitCount);
180         if (value < 0 || value > maxUnsignedValue) {
181             throw new IllegalArgumentException("value " + value + " out of range");
182         }
183     }
184 
185     /** Sign extend the {@code value} of {@code bitCount} to be a long. */
signExtendToLong(int bitCount, long value)186     public static long signExtendToLong(int bitCount, long value) {
187         if (bitCount > 64) {
188             throw new IllegalArgumentException("bitCount " + bitCount + " out of range");
189         } else if (bitCount == 64) {
190             return value;
191         }
192         long signBitMask = getSingleBitMask(bitCount - 1);
193         // Is sign bit set?
194         if ((signBitMask & value) == signBitMask) {
195             // Extend value to long.
196             value |= getHighBitsMask(Long.SIZE - bitCount);
197         } else {
198             // This clears bits above the sign bit.
199             value &= getLowBitsMask(bitCount);
200         }
201         return value;
202     }
203 
204     /**
205      * Returns the most positive numeric value representable in {@code bitCount} when signed or
206      * unsigned. {@code bitCount} must be between 1 and 64 inclusive for signed, or 1 and 63
207      * inclusive for unsigned, or an {@link IllegalArgumentException} will be thrown.
208      */
maxValue(int bitCount, boolean signedValue)209     public static long maxValue(int bitCount, boolean signedValue) {
210         if (signedValue) {
211             return maxSignedValue(bitCount);
212         } else {
213             return maxUnsignedValue(bitCount);
214         }
215     }
216 
217     /**
218      * Returns the most positive numeric value that can be represented with the specified number of
219      * bits when signed. {@code bitCount} must be between 1 and 64 inclusive or an
220      * {@link IllegalArgumentException} will be thrown.
221      *
222      * Like {@link #maxUnsignedValue(int)} but returns the answer for signed types.
223      */
maxSignedValue(int bitCount)224     public static long maxSignedValue(int bitCount) {
225         if (bitCount < 1 || bitCount > 64) {
226             throw new IllegalArgumentException("bitCount " + bitCount + " out of range");
227         }
228         // Bits | Numeric | Bit pattern
229         //    1 |       0 | 000...000
230         //    2 |       1 | 000...001
231         //    3 |       3 | 000...011
232         //    4 |       7 | 000...111
233         // ...
234         //   64 |(2^63)-1 | 011...111
235         return LOW_BITS_MASK[bitCount - 1];
236     }
237 
238     /**
239      * Returns the most positive numeric value that can be represented with the specified number of
240      * bits when unsigned. {@code bitCount} must be between 1 and 63 inclusive or an
241      * {@link IllegalArgumentException} will be thrown.
242      *
243      * Like {@link #getLowBitsMask(int)} but intended for numeric types.
244      */
maxUnsignedValue(int bitCount)245     public static long maxUnsignedValue(int bitCount) {
246         if (bitCount < 1 || bitCount > 63) {
247             throw new IllegalArgumentException("bitCount " + bitCount + " out of range");
248         }
249         // Bits | Numeric | Bit pattern
250         //    1 |       1 | 000...001
251         //    2 |       3 | 000...011
252         //    3 |       7 | 000...111
253         // ...
254         //   63 |  (2^63) | 011...111
255         return LOW_BITS_MASK[bitCount];
256     }
257 
258     /**
259      * Returns the most negative value representable in {@code bitCount} when signed or unsigned.
260      * {@code bitCount} must be between 1 and 64 inclusive for signed, or 1 and 63 inclusive for
261      * unsigned, or an {@link IllegalArgumentException} will be thrown.
262      */
minValue(int bitCount, boolean signedValue)263     public static long minValue(int bitCount, boolean signedValue) {
264         if (signedValue) {
265             return minSignedValue(bitCount);
266         } else {
267             if (bitCount < 1 || bitCount > 63) {
268                 throw new IllegalArgumentException("bitCount " + bitCount + " out of range");
269             }
270             return 0;
271         }
272     }
273 
274     /**
275      * Returns the most negative numeric value that can be represented with the specified number of
276      * bits. {@code bitCount} must be between 1 and 64 inclusive or an {@link
277      * IllegalArgumentException} will be thrown.
278      */
minSignedValue(int bitCount)279     public static long minSignedValue(int bitCount) {
280         if (bitCount < 1 || bitCount > 64) {
281             throw new IllegalArgumentException("bitCount " + bitCount + " out of range");
282         }
283         // Bits | Numeric | Bit pattern
284         //    1 |      -1 | {sign extended} 1     (64 bits)
285         //    2 |      -2 | {sign extended} 10    (63 bits)
286         //    3 |      -4 | {sign extended} 100   (62 bits)
287         //    4 |      -8 | {sign extended} 1000  (61 bits)
288         // ...
289         //   64 |  -(2^63)| 100...000               (1 bit)
290         return HIGH_BITS_MASK[65 - bitCount];
291     }
292 
293     /**
294      * Prints out a human readable binary string for {@code value}, leading-zero padded to the
295      * specified length. If {@code value} cannot be represented in {@code bitCount} characters, an
296      * {@link IllegalArgumentException} is thrown.
297      */
toUnsignedString(int bitCount, long value)298     public static String toUnsignedString(int bitCount, long value) {
299         String binaryString = Long.toBinaryString(value);
300         if (binaryString.length() > bitCount) {
301             throw new IllegalArgumentException(
302                     "value=" + value + " is not representable in " + bitCount + " bits");
303         }
304         StringBuilder builder = new StringBuilder(bitCount);
305         for (int i = 0; i < bitCount - binaryString.length(); i++) {
306             builder.append('0');
307         }
308         builder.append(binaryString);
309         return builder.toString();
310     }
311 }
312