langtools/src/share/classes/com/sun/tools/javac/util/Bits.java
changeset 17282 c6964ad7df63
parent 14049 3207422a0f9b
child 19941 8b91e8eb2d20
equal deleted inserted replaced
17281:7c38e715fd75 17282:c6964ad7df63
     1 /*
     1 /*
     2  * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    25 
    25 
    26 package com.sun.tools.javac.util;
    26 package com.sun.tools.javac.util;
    27 
    27 
    28 import java.util.Arrays;
    28 import java.util.Arrays;
    29 
    29 
       
    30 import static com.sun.tools.javac.util.Bits.BitsOpKind.*;
       
    31 
    30 /** A class for extensible, mutable bit sets.
    32 /** A class for extensible, mutable bit sets.
    31  *
    33  *
    32  *  <p><b>This is NOT part of any supported API.
    34  *  <p><b>This is NOT part of any supported API.
    33  *  If you write code that depends on this, you do so at your own risk.
    35  *  If you write code that depends on this, you do so at your own risk.
    34  *  This code and its internal interfaces are subject to change or
    36  *  This code and its internal interfaces are subject to change or
    35  *  deletion without notice.</b>
    37  *  deletion without notice.</b>
    36  */
    38  */
    37 public class Bits {
    39 public class Bits {
    38 
    40 
       
    41     public enum BitsOpKind {
       
    42         INIT,
       
    43         CLEAR,
       
    44         INCL_BIT,
       
    45         EXCL_BIT,
       
    46         ASSIGN,
       
    47         AND_SET,
       
    48         OR_SET,
       
    49         DIFF_SET,
       
    50         XOR_SET,
       
    51         INCL_RANGE,
       
    52         EXCL_RANGE,
       
    53     }
       
    54 
       
    55     //       ____________      reset    _________
       
    56     //      /  UNKNOWN   \   <-------- / UNINIT  \
       
    57     //      \____________/       |     \_________/
       
    58     //            |              |          |
       
    59     //            |assign        |          | any
       
    60     //            |        ___________      |
       
    61     //            ------> /  NORMAL   \ <----
       
    62     //                    \___________/     |
       
    63     //                            |         |
       
    64     //                            |         |
       
    65     //                            -----------
       
    66     //                               any
       
    67     private enum BitsState {
       
    68         /*  A Bits instance is in UNKNOWN state if it has been explicitly reset.
       
    69          *  It is possible to get to this state from any other by calling the
       
    70          *  reset method. An instance in the UNKNOWN state can pass to the
       
    71          *  NORMAL state after being assigned another Bits instance.
       
    72          */
       
    73         UNKNOWN,
       
    74         /*  A Bits instance is in UNINIT when it is created with the default
       
    75          *  constructor but it isn't explicitly reset. The main objective of this
       
    76          *  internal state is to save some memory.
       
    77          */
       
    78         UNINIT,
       
    79         /*  The normal state is reached after creating a Bits instance from an
       
    80          *  existing one or after applying any operation to an instance on UNINIT
       
    81          *  or NORMAL state. From this state a bits instance can pass to the
       
    82          *  UNKNOWN state by calling the reset method.
       
    83          */
       
    84         NORMAL;
       
    85 
       
    86         static BitsState getState(int[] someBits, boolean reset) {
       
    87             if (reset) {
       
    88                 return UNKNOWN;
       
    89             } else {
       
    90                 if (someBits != unassignedBits) {
       
    91                     return NORMAL;
       
    92                 } else {
       
    93                     return UNINIT;
       
    94                 }
       
    95             }
       
    96         }
       
    97 
       
    98     }
    39 
    99 
    40     private final static int wordlen = 32;
   100     private final static int wordlen = 32;
    41     private final static int wordshift = 5;
   101     private final static int wordshift = 5;
    42     private final static int wordmask = wordlen - 1;
   102     private final static int wordmask = wordlen - 1;
    43 
   103 
    44     private int[] bits;
   104     public int[] bits = null;
       
   105     // This field will store last version of bits after every change.
       
   106     public int[] oldBits = null;
       
   107 
       
   108     public BitsOpKind lastOperation = null;
       
   109 
       
   110     private static final int[] unassignedBits = new int[0];
       
   111 
       
   112     private BitsState currentState;
    45 
   113 
    46     /** Construct an initially empty set.
   114     /** Construct an initially empty set.
    47      */
   115      */
    48     public Bits() {
   116     public Bits() {
    49         this(new int[1]);
   117         this(false);
       
   118     }
       
   119 
       
   120     public Bits(Bits someBits) {
       
   121         this(someBits.dup().bits, BitsState.getState(someBits.bits, false));
       
   122     }
       
   123 
       
   124     public Bits(boolean reset) {
       
   125         this(unassignedBits, BitsState.getState(unassignedBits, reset));
    50     }
   126     }
    51 
   127 
    52     /** Construct a set consisting initially of given bit vector.
   128     /** Construct a set consisting initially of given bit vector.
    53      */
   129      */
    54     public Bits(int[] bits) {
   130     private Bits(int[] bits, BitsState initState) {
    55         this.bits = bits;
   131         this.bits = bits;
    56     }
   132         this.currentState = initState;
    57 
   133         switch (initState) {
    58     /** Construct a set consisting initially of given range.
   134             case UNKNOWN:
    59      */
   135                 reset(); //this will also set current state;
    60     public Bits(int start, int limit) {
   136                 break;
    61         this();
   137             case NORMAL:
    62         inclRange(start, limit);
   138                 Assert.check(bits != unassignedBits);
    63     }
   139                 lastOperation = INIT;
       
   140                 break;
       
   141         }
       
   142     }
       
   143 
       
   144     /** This method will be called after any operation that causes a change to
       
   145      *  the bits. Subclasses can thus override it in order to extract information
       
   146      *  from the changes produced to the bits by the given operation.
       
   147      */
       
   148     public void changed() {}
    64 
   149 
    65     private void sizeTo(int len) {
   150     private void sizeTo(int len) {
    66         if (bits.length < len) {
   151         if (bits.length < len) {
    67             bits = Arrays.copyOf(bits, len);
   152             bits = Arrays.copyOf(bits, len);
    68         }
   153         }
    69     }
   154     }
    70 
   155 
    71     /** This set = {}.
   156     /** This set = {}.
    72      */
   157      */
    73     public void clear() {
   158     public void clear() {
       
   159         Assert.check(currentState != BitsState.UNKNOWN);
       
   160         oldBits = bits;
       
   161         lastOperation = CLEAR;
    74         for (int i = 0; i < bits.length; i++) bits[i] = 0;
   162         for (int i = 0; i < bits.length; i++) bits[i] = 0;
       
   163         changed();
       
   164         currentState = BitsState.NORMAL;
       
   165     }
       
   166 
       
   167     public void reset() {
       
   168         bits = null;
       
   169         oldBits = null;
       
   170         currentState = BitsState.UNKNOWN;
       
   171     }
       
   172 
       
   173     public boolean isReset() {
       
   174         return currentState == BitsState.UNKNOWN;
       
   175     }
       
   176 
       
   177     public Bits assign(Bits someBits) {
       
   178         lastOperation = ASSIGN;
       
   179         oldBits = bits;
       
   180         bits = someBits.dup().bits;
       
   181         changed();
       
   182         currentState = BitsState.NORMAL;
       
   183         return this;
    75     }
   184     }
    76 
   185 
    77     /** Return a copy of this set.
   186     /** Return a copy of this set.
    78      */
   187      */
    79     public Bits dup() {
   188     private Bits dup() {
    80         int[] newbits = new int[bits.length];
   189         Assert.check(currentState != BitsState.UNKNOWN);
    81         System.arraycopy(bits, 0, newbits, 0, bits.length);
   190         Bits tmp = new Bits();
    82         return new Bits(newbits);
   191         if (currentState != BitsState.NORMAL) {
       
   192             tmp.bits = bits;
       
   193         } else {
       
   194             tmp.bits = new int[bits.length];
       
   195             System.arraycopy(bits, 0, tmp.bits, 0, bits.length);
       
   196         }
       
   197         currentState = BitsState.NORMAL;
       
   198         return tmp;
    83     }
   199     }
    84 
   200 
    85     /** Include x in this set.
   201     /** Include x in this set.
    86      */
   202      */
    87     public void incl(int x) {
   203     public void incl(int x) {
       
   204         Assert.check(currentState != BitsState.UNKNOWN);
    88         Assert.check(x >= 0);
   205         Assert.check(x >= 0);
       
   206         oldBits = bits;
       
   207         lastOperation = INCL_BIT;
    89         sizeTo((x >>> wordshift) + 1);
   208         sizeTo((x >>> wordshift) + 1);
    90         bits[x >>> wordshift] = bits[x >>> wordshift] |
   209         bits[x >>> wordshift] = bits[x >>> wordshift] |
    91             (1 << (x & wordmask));
   210             (1 << (x & wordmask));
       
   211         changed();
       
   212         currentState = BitsState.NORMAL;
    92     }
   213     }
    93 
   214 
    94 
   215 
    95     /** Include [start..limit) in this set.
   216     /** Include [start..limit) in this set.
    96      */
   217      */
    97     public void inclRange(int start, int limit) {
   218     public void inclRange(int start, int limit) {
       
   219         Assert.check(currentState != BitsState.UNKNOWN);
       
   220         oldBits = bits;
       
   221         lastOperation = INCL_RANGE;
    98         sizeTo((limit >>> wordshift) + 1);
   222         sizeTo((limit >>> wordshift) + 1);
    99         for (int x = start; x < limit; x++)
   223         for (int x = start; x < limit; x++) {
   100             bits[x >>> wordshift] = bits[x >>> wordshift] |
   224             bits[x >>> wordshift] = bits[x >>> wordshift] |
   101                 (1 << (x & wordmask));
   225                 (1 << (x & wordmask));
       
   226         }
       
   227         changed();
       
   228         currentState = BitsState.NORMAL;
   102     }
   229     }
   103 
   230 
   104     /** Exclude [start...end] from this set.
   231     /** Exclude [start...end] from this set.
   105      */
   232      */
   106     public void excludeFrom(int start) {
   233     public void excludeFrom(int start) {
       
   234         Assert.check(currentState != BitsState.UNKNOWN);
       
   235         oldBits = bits;
       
   236         lastOperation = EXCL_RANGE;
   107         Bits temp = new Bits();
   237         Bits temp = new Bits();
   108         temp.sizeTo(bits.length);
   238         temp.sizeTo(bits.length);
   109         temp.inclRange(0, start);
   239         temp.inclRange(0, start);
   110         andSet(temp);
   240         internalAndSet(temp);
       
   241         changed();
       
   242         currentState = BitsState.NORMAL;
   111     }
   243     }
   112 
   244 
   113     /** Exclude x from this set.
   245     /** Exclude x from this set.
   114      */
   246      */
   115     public void excl(int x) {
   247     public void excl(int x) {
       
   248         Assert.check(currentState != BitsState.UNKNOWN);
   116         Assert.check(x >= 0);
   249         Assert.check(x >= 0);
       
   250         oldBits = bits;
       
   251         lastOperation = EXCL_BIT;
   117         sizeTo((x >>> wordshift) + 1);
   252         sizeTo((x >>> wordshift) + 1);
   118         bits[x >>> wordshift] = bits[x >>> wordshift] &
   253         bits[x >>> wordshift] = bits[x >>> wordshift] &
   119             ~(1 << (x & wordmask));
   254             ~(1 << (x & wordmask));
       
   255         changed();
       
   256         currentState = BitsState.NORMAL;
   120     }
   257     }
   121 
   258 
   122     /** Is x an element of this set?
   259     /** Is x an element of this set?
   123      */
   260      */
   124     public boolean isMember(int x) {
   261     public boolean isMember(int x) {
       
   262         Assert.check(currentState != BitsState.UNKNOWN);
   125         return
   263         return
   126             0 <= x && x < (bits.length << wordshift) &&
   264             0 <= x && x < (bits.length << wordshift) &&
   127             (bits[x >>> wordshift] & (1 << (x & wordmask))) != 0;
   265             (bits[x >>> wordshift] & (1 << (x & wordmask))) != 0;
   128     }
   266     }
   129 
   267 
   130     /** {@literal this set = this set & xs}.
   268     /** {@literal this set = this set & xs}.
   131      */
   269      */
   132     public Bits andSet(Bits xs) {
   270     public Bits andSet(Bits xs) {
       
   271         Assert.check(currentState != BitsState.UNKNOWN);
       
   272         oldBits = bits;
       
   273         lastOperation = AND_SET;
       
   274         internalAndSet(xs);
       
   275         changed();
       
   276         currentState = BitsState.NORMAL;
       
   277         return this;
       
   278     }
       
   279 
       
   280     private void internalAndSet(Bits xs) {
       
   281         Assert.check(currentState != BitsState.UNKNOWN);
   133         sizeTo(xs.bits.length);
   282         sizeTo(xs.bits.length);
   134         for (int i = 0; i < xs.bits.length; i++)
   283         for (int i = 0; i < xs.bits.length; i++) {
   135             bits[i] = bits[i] & xs.bits[i];
   284             bits[i] = bits[i] & xs.bits[i];
       
   285         }
       
   286     }
       
   287 
       
   288     /** this set = this set | xs.
       
   289      */
       
   290     public Bits orSet(Bits xs) {
       
   291         Assert.check(currentState != BitsState.UNKNOWN);
       
   292         oldBits = bits;
       
   293         lastOperation = OR_SET;
       
   294         sizeTo(xs.bits.length);
       
   295         for (int i = 0; i < xs.bits.length; i++) {
       
   296             bits[i] = bits[i] | xs.bits[i];
       
   297         }
       
   298         changed();
       
   299         currentState = BitsState.NORMAL;
   136         return this;
   300         return this;
   137     }
   301     }
   138 
   302 
   139     /** this set = this set | xs.
       
   140      */
       
   141     public Bits orSet(Bits xs) {
       
   142         sizeTo(xs.bits.length);
       
   143         for (int i = 0; i < xs.bits.length; i++)
       
   144             bits[i] = bits[i] | xs.bits[i];
       
   145         return this;
       
   146     }
       
   147 
       
   148     /** this set = this set \ xs.
   303     /** this set = this set \ xs.
   149      */
   304      */
   150     public Bits diffSet(Bits xs) {
   305     public Bits diffSet(Bits xs) {
       
   306         Assert.check(currentState != BitsState.UNKNOWN);
       
   307         oldBits = bits;
       
   308         lastOperation = DIFF_SET;
   151         for (int i = 0; i < bits.length; i++) {
   309         for (int i = 0; i < bits.length; i++) {
   152             if (i < xs.bits.length) {
   310             if (i < xs.bits.length) {
   153                 bits[i] = bits[i] & ~xs.bits[i];
   311                 bits[i] = bits[i] & ~xs.bits[i];
   154             }
   312             }
   155         }
   313         }
       
   314         changed();
       
   315         currentState = BitsState.NORMAL;
   156         return this;
   316         return this;
   157     }
   317     }
   158 
   318 
   159     /** this set = this set ^ xs.
   319     /** this set = this set ^ xs.
   160      */
   320      */
   161     public Bits xorSet(Bits xs) {
   321     public Bits xorSet(Bits xs) {
       
   322         Assert.check(currentState != BitsState.UNKNOWN);
       
   323         oldBits = bits;
       
   324         lastOperation = XOR_SET;
   162         sizeTo(xs.bits.length);
   325         sizeTo(xs.bits.length);
   163         for (int i = 0; i < xs.bits.length; i++)
   326         for (int i = 0; i < xs.bits.length; i++) {
   164             bits[i] = bits[i] ^ xs.bits[i];
   327             bits[i] = bits[i] ^ xs.bits[i];
       
   328         }
       
   329         changed();
       
   330         currentState = BitsState.NORMAL;
   165         return this;
   331         return this;
   166     }
   332     }
   167 
   333 
   168     /** Count trailing zero bits in an int. Algorithm from "Hacker's
   334     /** Count trailing zero bits in an int. Algorithm from "Hacker's
   169      *  Delight" by Henry S. Warren Jr. (figure 5-13)
   335      *  Delight" by Henry S. Warren Jr. (figure 5-13)
   185      *  <pre>{@code
   351      *  <pre>{@code
   186      *  for (int i = bits.nextBit(0); i>=0; i = bits.nextBit(i+1)) ...
   352      *  for (int i = bits.nextBit(0); i>=0; i = bits.nextBit(i+1)) ...
   187      *  }</pre>
   353      *  }</pre>
   188      */
   354      */
   189     public int nextBit(int x) {
   355     public int nextBit(int x) {
       
   356         Assert.check(currentState != BitsState.UNKNOWN);
   190         int windex = x >>> wordshift;
   357         int windex = x >>> wordshift;
   191         if (windex >= bits.length) return -1;
   358         if (windex >= bits.length) return -1;
   192         int word = bits[windex] & ~((1 << (x & wordmask))-1);
   359         int word = bits[windex] & ~((1 << (x & wordmask))-1);
   193         while (true) {
   360         while (true) {
   194             if (word != 0)
   361             if (word != 0)
   200     }
   367     }
   201 
   368 
   202     /** a string representation of this set.
   369     /** a string representation of this set.
   203      */
   370      */
   204     public String toString() {
   371     public String toString() {
   205         char[] digits = new char[bits.length * wordlen];
   372         if (bits.length > 0) {
   206         for (int i = 0; i < bits.length * wordlen; i++)
   373             char[] digits = new char[bits.length * wordlen];
   207             digits[i] = isMember(i) ? '1' : '0';
   374             for (int i = 0; i < bits.length * wordlen; i++)
   208         return new String(digits);
   375                 digits[i] = isMember(i) ? '1' : '0';
       
   376             return new String(digits);
       
   377         } else {
       
   378             return "[]";
       
   379         }
   209     }
   380     }
   210 
   381 
   211     /** Test Bits.nextBit(int). */
   382     /** Test Bits.nextBit(int). */
   212     public static void main(String[] args) {
   383     public static void main(String[] args) {
   213         java.util.Random r = new java.util.Random();
   384         java.util.Random r = new java.util.Random();
   214         Bits bits = new Bits();
   385         Bits bits = new Bits();
   215         int dupCount = 0;
       
   216         for (int i=0; i<125; i++) {
   386         for (int i=0; i<125; i++) {
   217             int k;
   387             int k;
   218             do {
   388             do {
   219                 k = r.nextInt(250);
   389                 k = r.nextInt(250);
   220             } while (bits.isMember(k));
   390             } while (bits.isMember(k));