001    package org.jaga.util;
002    
003    
004    
005    /**
006     * TODO: Complete these comments.
007     *
008     * <p><u>Project:</u> JAGA - Java API for Genetic Algorithms.</p>
009     *
010     * <p><u>Company:</u> University College London and JAGA.Org
011     *    (<a href="http://www.jaga.org" target="_blank">http://www.jaga.org</a>).
012     * </p>
013     *
014     * <p><u>Copyright:</u> (c) 2004 by G. Paperin.<br/>
015     *    This program is free software; you can redistribute it and/or modify
016     *    it under the terms of the GNU General Public License as published by
017     *    the Free Software Foundation, ONLY if you include a note of the original
018     *    author(s) in any redistributed/modified copy.<br/>
019     *    This program is distributed in the hope that it will be useful,
020     *    but WITHOUT ANY WARRANTY; without even the implied warranty of
021     *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
022     *    GNU General Public License for more details.<br/>
023     *    You should have received a copy of the GNU General Public License
024     *    along with this program; if not, write to the Free Software
025     *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026     *    or see http://www.gnu.org/licenses/gpl.html</p>
027     *
028     * @author Greg Paperin (greg@jaga.org)
029     *
030     * @version JAGA public release 1.0 beta
031     */
032    
033    public class BitString {
034    
035            private int length;
036            private int [] content = null;
037    
038            private BitString() {
039                    throw new UnsupportedOperationException("Use BitString(int)");
040            }
041    
042            public BitString(int length) {
043                    this.length = length;
044                    int bufSize = length / 32;
045                    if (0 != length % 32)
046                            ++bufSize;
047                    content = new int[bufSize];
048                    for (int i = 0; i < bufSize; content[i++] = 0);
049            }
050    
051            public BitString(final BitString toCopy) {
052                    this.length = toCopy.length;
053                    int bufSize = length / 32;
054                    if (0 != length % 32)
055                            ++bufSize;
056                    this.content = new int[bufSize];
057                    System.arraycopy(toCopy.content, 0, this.content, 0, this.content.length);
058            }
059    
060            public Object clone() {
061                    BitString copy = new BitString(this.length);
062                    System.arraycopy(this.content, 0, copy.content, 0, copy.content.length);
063                    return copy;
064            }
065    
066            public int getLength() {
067                    return length;
068            }
069    
070            public BitString substring(int from, int to) {
071                    int len = checkSubLength(from, to);
072                    BitString substring = new BitString(len);
073                    for (int i = from; i < to; i++)
074                            substring.setUnchecked(i - from, this.getUnchecked(i));
075                    return substring;
076            }
077    
078            public boolean get(int index) {
079                    checkIndex(index);
080                    return getUnchecked(index);
081            }
082    
083            protected boolean getUnchecked(int index) {
084                    int segment = index / 32;
085                    int offset = index % 32;
086                    int mask = 0x1 << (32 - offset - 1);
087                    return 0 != (content[segment] & mask);
088            }
089    
090            public void set(int index, boolean value) {
091                    checkIndex(index);
092                    setUnchecked(index, value);
093            }
094    
095            public void setUnchecked(int index, boolean value) {
096                    int segment = index / 32;
097                    int offset = index % 32;
098                    int mask = 0x1 << (32 - offset - 1);
099                    if (value)
100                            content[segment] |= mask;
101                    else
102                            content[segment] &= ~mask;
103            }
104    
105            public void set(int from, int to, boolean value) {
106                    checkSubLength(from, to);
107                    for (int i = from; i < to; setUnchecked(i++, value));
108            }
109    
110            public void set(int from, int to, BitString values) {
111                    if (values.getLength() == 0)
112                            throw new IllegalArgumentException("Length of values must be > 0");
113                    int len = checkSubLength(from, to);
114                    int iV = 0;
115                    for (int i = from; i < to; i++, iV++) {
116                            if (iV >= values.getLength())
117                                    iV = 0;
118                            this.setUnchecked(i, values.getUnchecked(iV));
119                    }
120            }
121    
122            public void flip(int index) {
123                    checkIndex(index);
124                    int segment = index / 32;
125                    int offset = index % 32;
126                    int mask = 0x1 << (32 - offset - 1);
127                    content[segment] ^= mask;
128            }
129    
130            public String toString() {
131                    StringBuffer s = new StringBuffer(length);
132                    for (int i = 0; i < length; s.append(get(i++) ? 1 : 0));
133                    return s.toString();
134            }
135    
136            protected int checkSubLength(int from, int to) throws IndexOutOfBoundsException {
137                    checkIndex(from);
138                    checkIndex(to - 1);
139                    int sublen = to - from;
140                    if (0 > sublen)
141                            throw new IllegalArgumentException("must have 'from' <= 'to', but has "
142                                                                                               + from + " > " + to);
143                    return sublen;
144            }
145    
146            protected void checkIndex(int index) throws IndexOutOfBoundsException {
147                    if (index < 0 || index >= this.length)
148                            throw new IndexOutOfBoundsException("index is " + index
149                                                                                                    + ", but must be in [0, "
150                                                                                                    + (this.length - 1) + "]");
151            }
152    }