001/*******************************************************************************
002 * This software is provided as a supplement to the authors' textbooks on digital
003 * image processing published by Springer-Verlag in various languages and editions.
004 * Permission to use and distribute this software is granted under the BSD 2-Clause
005 * "Simplified" License (see http://opensource.org/licenses/BSD-2-Clause).
006 * Copyright (c) 2006-2023 Wilhelm Burger, Mark J. Burge. All rights reserved.
007 * Visit https://imagingbook.com for additional details.
008 ******************************************************************************/
009package imagingbook.common.util.bits;
010
011/**
012 * This class implements {@link BitVector} with internal 64-bit {@code long} data.
013 *
014 * @author WB
015 */
016public class BitVector64 implements BitVector {
017        
018        private static final int WL = 64;
019        
020        private final long[] data;
021        private final int length;
022        
023        public BitVector64(int length) {
024                if (length <= 0) {
025                        throw new IllegalArgumentException("bit vector length must be at least 1");
026                }
027                this.length = length;
028                int n = (length % WL == 0) ? length / WL : length / WL + 1;     // word count
029                this.data = new long[n];
030        }
031        
032        public BitVector64(byte[] bytes) {
033                this(bytes.length);
034                for (int i = 0; i < bytes.length; i++) {
035                        if (bytes[i] != 0) {
036                                this.set(i);
037                        }
038                }
039        }
040        
041        public BitVector64(boolean[] bools) {
042                this(bools.length);
043                for (int i = 0; i < bools.length; i++) {
044                        this.set(i, bools[i]);
045                }
046        }
047        
048        // ---------------------------------------------------------------------
049
050        @Override
051        public int getLength() {
052                return this.length;
053        }
054        
055        @Override
056        public boolean get(int i) {
057                if (i < 0 || i >= length) {
058                        throw new IndexOutOfBoundsException("illegal index " + i);
059                }
060                final long mask = 1L << (i % WL);
061                return (data[i / WL] & mask) != 0L;
062        }
063        
064        @Override
065        public void set(int i) {
066                if (i < 0 || i >= length) {
067                        throw new IndexOutOfBoundsException("illegal index " + i);
068                }
069                final int j = i / WL;   // word index
070                final long mask = 1L << (i % WL);
071                data[j] =  data[j] | mask;
072        }
073        
074        @Override
075        public void unset(int i) {
076                if (i < 0 || i >= length) {
077                        throw new IndexOutOfBoundsException("illegal index " + i);
078                }
079                final int j = i / WL;   // word index
080                long mask = 1L << (i % WL);
081                data[j] =  data[j] & ~mask;
082        }
083        
084        @Override
085        public void setAll() {
086                for (int j = 0; j < data.length; j++) {
087                        data[j] = ~0L;
088                }
089        }
090
091        @Override
092        public void unsetAll() {
093                for (int j = 0; j < data.length; j++) {
094                        data[j] = 0L;
095                }
096        }
097                
098        
099        @Override
100        public String toString() {
101                StringBuilder buf = new StringBuilder();
102                buf.append(BitVector64.class.getSimpleName() + "[");
103                for (int i = 0; i < length; i++) {
104                        buf.append(this.get(i) ? "1" : "0");
105                }
106                buf.append("]");
107                return buf.toString();
108        }
109
110}