001/* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013package org.jikesrvm.util; 014 015import java.io.Serializable; 016 017/** 018 * Implements a bit vector. 019 */ 020public final class BitVector implements Serializable { 021 /** Support for serialization */ 022 static final long serialVersionUID = 6961578653974090041L; 023 024 private static final int LOG_BITS_PER_UNIT = 5; 025 private static final int MASK = 0xffffffff; 026 private static final int LOW_MASK = 0x1f; 027 private final int[] bits; 028 private final int nbits; 029 030 /** 031 * Convert bitIndex to a subscript into the bits[] array. 032 * 033 * @param bitIndex the bit index 034 * @return subscript into the array 035 */ 036 private static int subscript(int bitIndex) { 037 return bitIndex >> LOG_BITS_PER_UNIT; 038 } 039 040 /** 041 * Creates an empty string with the specified size. 042 * @param nbits the size of the string 043 */ 044 public BitVector(int nbits) { 045 // subscript(nbits) is the length of the array needed to 046 // hold nbits 047 bits = new int[subscript(nbits) + 1]; 048 this.nbits = nbits; 049 } 050 051 /** 052 * Creates a copy of a Bit String 053 * @param s the string to copy 054 */ 055 public BitVector(BitVector s) { 056 bits = new int[s.bits.length]; 057 this.nbits = s.nbits; 058 System.arraycopy(s.bits, 0, this.bits, 0, s.bits.length); 059 } 060 061 public void setAll() { 062 for (int i = 0; i < bits.length; i++) { 063 bits[i] = MASK; 064 } 065 } 066 067 /** 068 * Sets a bit. 069 * @param bit the bit to be set 070 */ 071 public void set(int bit) { 072 int shiftBits = bit & LOW_MASK; 073 bits[subscript(bit)] |= (1 << shiftBits); 074 } 075 076 /** 077 * Clears all bits. 078 */ 079 public void clearAll() { 080 for (int i = 0; i < bits.length; i++) { 081 bits[i] = 0; 082 } 083 } 084 085 /** 086 * Clears a bit. 087 * @param bit the bit to be cleared 088 */ 089 public void clear(int bit) { 090 int shiftBits = bit & LOW_MASK; 091 bits[subscript(bit)] &= ~(1 << shiftBits); 092 } 093 094 /** 095 * Gets a bit. 096 * @param bit the bit to be gotten 097 * @return the value of the bit, {@code 0} for {@code false} 098 */ 099 public boolean get(int bit) { 100 int shiftBits = bit & LOW_MASK; 101 int n = subscript(bit); 102 return ((bits[n] & (1 << shiftBits)) != 0); 103 } 104 105 /** 106 * Logically NOT this bit string 107 */ 108 public void not() { 109 for (int i = 0; i < bits.length; i++) { 110 bits[i] ^= MASK; 111 } 112 } 113 114 public static BitVector not(BitVector s) { 115 BitVector b = new BitVector(s); 116 b.not(); 117 return b; 118 } 119 120 /** 121 * Logically ANDs this bit set with the specified set of bits. 122 * @param set the bit set to be ANDed with 123 */ 124 public void and(BitVector set) { 125 if (this == set) { 126 return; 127 } 128 int n = bits.length; 129 for (int i = n; i-- > 0;) { 130 bits[i] &= set.bits[i]; 131 } 132 } 133 134 public static BitVector and(BitVector b1, BitVector b2) { 135 BitVector b = new BitVector(b1); 136 b.and(b2); 137 return b; 138 } 139 140 /** 141 * Logically ORs this bit set with the specified set of bits. 142 * @param set the bit set to be ORed with 143 */ 144 public void or(BitVector set) { 145 if (this == set) { // should help alias analysis 146 return; 147 } 148 int setLength = set.bits.length; 149 for (int i = setLength; i-- > 0;) { 150 bits[i] |= set.bits[i]; 151 } 152 } 153 154 public static BitVector or(BitVector b1, BitVector b2) { 155 BitVector b = new BitVector(b1); 156 b.or(b2); 157 return b; 158 } 159 160 /** 161 * Logically XORs this bit set with the specified set of bits. 162 * @param set the bit set to be XORed with 163 */ 164 public void xor(BitVector set) { 165 int setLength = set.bits.length; 166 for (int i = setLength; i-- > 0;) { 167 bits[i] ^= set.bits[i]; 168 } 169 } 170 171 /** 172 * @param other the set to check intersection with 173 * @return whether the intersection of the two sets is empty 174 */ 175 public boolean intersectionEmpty(BitVector other) { 176 int n = bits.length; 177 for (int i = n; i-- > 0;) { 178 if ((bits[i] & other.bits[i]) != 0) return false; 179 } 180 return true; 181 } 182 183 /** 184 * Copies the values of the bits in the specified set into this set. 185 * @param set the bit set to copy the bits from 186 */ 187 public void copyBits(BitVector set) { 188 System.arraycopy(set.bits, 0, this.bits, 0, set.bits.length); 189 } 190 191 @Override 192 public int hashCode() { 193 int h = 1234; 194 for (int i = bits.length; --i >= 0;) { 195 h ^= bits[i] * (i + 1); 196 } 197 return h; 198 } 199 200 /** 201 * @return number of bits that are set 202 */ 203 public int populationCount() { 204 int count = 0; 205 for (int bit : bits) { 206 count += Integer.bitCount(bit); 207 } 208 return count; 209 } 210 211 /** 212 * Calculates and returns the set's size in bits. 213 * The maximum element in the set is the size - 1st element. 214 * 215 * @return the length of this set in bits 216 */ 217 public int length() { 218 return bits.length << LOG_BITS_PER_UNIT; 219 } 220 221 /** 222 * Compares this object against the specified object. 223 * @param obj the object to compare with 224 * @return true if the objects are the same; false otherwise. 225 */ 226 @Override 227 public boolean equals(Object obj) { 228 if (obj instanceof BitVector) { 229 if (this == obj) { // should help alias analysis 230 return true; 231 } 232 BitVector set = (BitVector) obj; 233 int n = bits.length; 234 if (n != set.bits.length) return false; 235 for (int i = n; i-- > 0;) { 236 if (bits[i] != set.bits[i]) { 237 return false; 238 } 239 } 240 return true; 241 } 242 return false; 243 } 244 245 public boolean isZero() { 246 int setLength = bits.length; 247 for (int i = setLength; i-- > 0;) { 248 if (bits[i] != 0) return false; 249 } 250 return true; 251 } 252 253 public BitVector dup() { 254 return new BitVector(this); 255 } 256 257 @Override 258 public String toString() { 259 StringBuilder buffer = new StringBuilder(); 260 boolean needSeparator = false; 261 buffer.append('{'); 262// int limit = length(); 263 int limit = this.nbits; 264 for (int i = 0; i < limit; i++) { 265 if (get(i)) { 266 if (needSeparator) { 267 buffer.append(", "); 268 } else { 269 needSeparator = true; 270 } 271 buffer.append(i); 272 } 273 } 274 buffer.append('}'); 275 return buffer.toString(); 276 } 277}