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