jaulib v1.3.0
Jau Support Library (C++, Java, ..)
Int32ArrayBitfield.java
Go to the documentation of this file.
1/**
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2020 Gothel Software e.K.
4 * Copyright (c) 2015 Gothel Software e.K.
5 * Copyright (c) 2015 JogAmp Community.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining
8 * a copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sublicense, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be
16 * included in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26package jau.util;
27
28import org.jau.util.BitMath;
29import org.jau.util.Bitfield;
30
31/**
32 * Simple bitfield interface for efficient storage access in O(1).
33 * <p>
34 * Implementation uses a 32bit integer array for storage.
35 * </p>
36 */
37public class Int32ArrayBitfield implements Bitfield {
38 private static final int UNIT_SHIFT = 5;
39 private final int[] storage;
40 private final int bitSize;
41
42 /**
43 * @param storageBitSize
44 */
45 public Int32ArrayBitfield(final int storageBitSize) {
46 final int units = Math.max(1, ( storageBitSize + 31 ) >>> UNIT_SHIFT);
47 this.storage = new int[units]; // initialized w/ default '0'
48 this.bitSize = units << UNIT_SHIFT;
49 }
50
51 @Override
52 public int size() {
53 return bitSize;
54 }
55
56 @Override
57 public final void clearField(final boolean bit) {
58 final int v;
59 if( bit ) {
61 } else {
62 v = 0;
63 }
64 for(int i=storage.length-1; i>=0; i--) {
65 storage[i] = v;
66 }
67 }
68
69 private static final void check(final int size, final int bitnum) throws IndexOutOfBoundsException {
70 if( 0 > bitnum || bitnum >= size ) {
71 throw new IndexOutOfBoundsException("Bitnum should be within [0.."+(size-1)+"], but is "+bitnum);
72 }
73 }
74
75 @Override
76 public final int get32(final int lowBitnum, final int length) throws IndexOutOfBoundsException {
77 if( 0 > length || length > 32 ) {
78 throw new IndexOutOfBoundsException("length should be within [0..32], but is "+length);
79 }
80 check(bitSize-length+1, lowBitnum);
81 final int u = lowBitnum >>> UNIT_SHIFT;
82 final int left = 32 - ( lowBitnum - ( u << UNIT_SHIFT ) ); // remaining bits of first chunk storage
83 if( 32 == left ) {
84 // fast path
85 final int m = BitMath.getBitMask(length);// mask of chunk
86 return m & storage[u];
87 } else {
88 // slow path
89 final int l = Math.min(length, left); // length of first chunk < 32
90 final int m = ( 1 << l ) - 1; // mask of first chunk
91 final int d = m & ( storage[u] >>> lowBitnum );
92 final int l2 = length - l; // length of last chunk < 32
93 if( l2 > 0 ) {
94 final int m2 = ( 1 << l2 ) - 1; // mask of last chunk
95 return d | ( ( m2 & storage[u+1] ) << l );
96 } else {
97 return d;
98 }
99 }
100 }
101 @Override
102 public final void put32(final int lowBitnum, final int length, final int data) throws IndexOutOfBoundsException {
103 if( 0 > length || length > 32 ) {
104 throw new IndexOutOfBoundsException("length should be within [0..32], but is "+length);
105 }
106 check(bitSize-length+1, lowBitnum);
107 final int u = lowBitnum >>> UNIT_SHIFT;
108 final int left = 32 - ( lowBitnum - ( u << UNIT_SHIFT ) ); // remaining bits of first chunk storage
109 if( 32 == left ) {
110 // fast path
111 final int m = BitMath.getBitMask(length);// mask of chunk
112 storage[u] = ( ( ~m ) & storage[u] ) // keep non-written storage bits
113 | ( m & data ); // overwrite storage w/ used data bits
114 } else {
115 // slow path
116 final int l = Math.min(length, left); // length of first chunk < 32
117 final int m = ( 1 << l ) - 1; // mask of first chunk
118 storage[u] = ( ( ~( m << lowBitnum ) ) & storage[u] ) // keep non-written storage bits
119 | ( ( m & data ) << lowBitnum ); // overwrite storage w/ used data bits
120 final int l2 = length - l; // length of last chunk < 32
121 if( l2 > 0 ) {
122 final int m2 = ( 1 << l2 ) - 1; // mask of last chunk
123 storage[u+1] = ( ( ~m2 ) & storage[u+1] ) // keep non-written storage bits
124 | ( m2 & ( data >>> l ) ); // overwrite storage w/ used data bits
125 }
126 }
127 }
128 @Override
129 public final int copy32(final int srcBitnum, final int dstBitnum, final int length) throws IndexOutOfBoundsException {
130 final int data = get32(srcBitnum, length);
131 put32(dstBitnum, length, data);
132 return data;
133 }
134
135 @Override
136 public final boolean get(final int bitnum) throws IndexOutOfBoundsException {
137 check(bitSize, bitnum);
138 final int u = bitnum >>> UNIT_SHIFT;
139 final int b = bitnum - ( u << UNIT_SHIFT );
140 return 0 != ( storage[u] & ( 1 << b ) ) ;
141 }
142
143 @Override
144 public final boolean put(final int bitnum, final boolean bit) throws IndexOutOfBoundsException {
145 check(bitSize, bitnum);
146 final int u = bitnum >>> UNIT_SHIFT;
147 final int b = bitnum - ( u << UNIT_SHIFT );
148 final int m = 1 << b;
149 final boolean prev = 0 != ( storage[u] & m ) ;
150 if( prev != bit ) {
151 if( bit ) {
152 storage[u] |= m;
153 } else {
154 storage[u] &= ~m;
155 }
156 }
157 return prev;
158 }
159 @Override
160 public final void set(final int bitnum) throws IndexOutOfBoundsException {
161 check(bitSize, bitnum);
162 final int u = bitnum >>> UNIT_SHIFT;
163 final int b = bitnum - ( u << UNIT_SHIFT );
164 final int m = 1 << b;
165 storage[u] |= m;
166 }
167 @Override
168 public final void clear(final int bitnum) throws IndexOutOfBoundsException {
169 check(bitSize, bitnum);
170 final int u = bitnum >>> UNIT_SHIFT;
171 final int b = bitnum - ( u << UNIT_SHIFT );
172 final int m = 1 << b;
173 storage[u] &= ~m;
174 }
175 @Override
176 public final boolean copy(final int srcBitnum, final int dstBitnum) throws IndexOutOfBoundsException {
177 check(bitSize, srcBitnum);
178 check(bitSize, dstBitnum);
179 final boolean bit;
180 // get
181 {
182 final int u = srcBitnum >>> UNIT_SHIFT;
183 final int b = srcBitnum - ( u << UNIT_SHIFT );
184 bit = 0 != ( storage[u] & ( 1 << b ) ) ;
185 }
186 // put
187 final int u = dstBitnum >>> UNIT_SHIFT;
188 final int b = dstBitnum - ( u << UNIT_SHIFT );
189 final int m = 1 << b;
190 if( bit ) {
191 storage[u] |= m;
192 } else {
193 storage[u] &= ~m;
194 }
195 return bit;
196 }
197
198 @Override
199 public int bitCount() {
200 int c = 0;
201 for(int i = storage.length-1; i>=0; i--) {
202 c += BitMath.bitCount(storage[i]);
203 }
204 return c;
205 }
206}
Simple bitfield interface for efficient storage access in O(1).
final void clear(final int bitnum)
Clear the bit at position bitnum according to bit.
int size()
Returns the storage size in bit units, e.g.
int bitCount()
Returns the number of one bits within this bitfield.
final boolean copy(final int srcBitnum, final int dstBitnum)
Copies the bit at position srcBitnum to position dstBitnum and returning true if the bit is set,...
final void put32(final int lowBitnum, final int length, final int data)
Puts length bits of given data into this storage, starting w/ the lowest bit to the storage position ...
final int copy32(final int srcBitnum, final int dstBitnum, final int length)
Copies length bits at position srcLowBitnum to position dstLowBitnum and returning the bits.
final void clearField(final boolean bit)
Set all bits of this bitfield to the given value bit.
final int get32(final int lowBitnum, final int length)
Returns length bits from this storage, starting with the lowest bit from the storage position lowBitn...
Int32ArrayBitfield(final int storageBitSize)
final boolean put(final int bitnum, final boolean bit)
Set or clear the bit at position bitnum according to bit and return the previous value.
static final int bitCount(int n)
Returns the number of set bits within given 32bit integer in O(1) using a HAKEM 169 Bit Count inspire...
Definition: BitMath.java:68
static int getBitMask(final int n)
Returns the 32 bit mask of n-bits, i.e.
Definition: BitMath.java:45
static final int UNSIGNED_INT_MAX_VALUE
Maximum 32 bit Unsigned Integer Value: 0xffffffff == {@value}.
Definition: BitMath.java:28
Simple bitfield interface for efficient bit storage access in O(1).
Definition: Bitfield.java:34