-
Notifications
You must be signed in to change notification settings - Fork 100
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create default implementation of ranked bit vector.
This class has 'rank' implemented (method 'countBits').
- Loading branch information
Julian Mendez
committed
Feb 18, 2014
1 parent
8d37c74
commit 86ac91f
Showing
2 changed files
with
439 additions
and
0 deletions.
There are no files selected for viewing
220 changes: 220 additions & 0 deletions
220
...orage/src/main/java/org/wikidata/wdtk/storage/datastructure/impl/RankedBitVectorImpl.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,220 @@ | ||
package org.wikidata.wdtk.storage.datastructure.impl; | ||
|
||
/* | ||
* #%L | ||
* Wikidata Toolkit Data Model | ||
* %% | ||
* Copyright (C) 2014 Wikidata Toolkit Developers | ||
* %% | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* #L% | ||
*/ | ||
|
||
import java.util.ArrayList; | ||
import java.util.Iterator; | ||
import java.util.List; | ||
|
||
import org.wikidata.wdtk.storage.datastructure.intf.BitVector; | ||
import org.wikidata.wdtk.storage.datastructure.intf.RankedBitVector; | ||
|
||
/** | ||
* Default implementation of {@link RankedBitVector}. This implementation | ||
* divides the bit vector in blocks of equal size. It keeps an array with the | ||
* count of <code>true</code> values present in each block. <br /> | ||
* For example, given the bit vector: 10010, with a block size of 2, the array | ||
* contains: [1, 2, 2]. The first block contains 1 <code>true</code> value, the | ||
* second block contains 1 more <code>true</code> value, in total 2. The third | ||
* block is incomplete, since it has only one bit, and it does not contain more | ||
* <code>true</code> values. | ||
* | ||
* @author Julian Mendez | ||
*/ | ||
public class RankedBitVectorImpl implements RankedBitVector, Iterable<Boolean> { | ||
|
||
BitVectorImpl bitVector; | ||
int blockSize = 0x10; | ||
|
||
/** | ||
* This array contains the number of <code>true</code> values found in each | ||
* block. | ||
*/ | ||
List<Long> count = new ArrayList<Long>(); | ||
|
||
/** | ||
* Constructor of a ranked bit vector of size 0. | ||
*/ | ||
public RankedBitVectorImpl() { | ||
this.bitVector = new BitVectorImpl(); | ||
} | ||
|
||
/** | ||
* Copy constructor of a ranked bit vector. | ||
* | ||
* @param bitVector | ||
* bit vector | ||
*/ | ||
public RankedBitVectorImpl(BitVector bitVector) { | ||
this.bitVector = new BitVectorImpl(bitVector); | ||
if (bitVector instanceof RankedBitVectorImpl) { | ||
this.blockSize = ((RankedBitVectorImpl) bitVector).blockSize; | ||
} | ||
updateCount(0); | ||
} | ||
|
||
/** | ||
* Constructor of a ranked bit vector of size <i>initialSize</i>. The bit | ||
* vector contains <code>false</code> at all indexes. | ||
* | ||
* @param initialSize | ||
* initial size of this ranked bit vector | ||
*/ | ||
public RankedBitVectorImpl(long initialSize) { | ||
this.bitVector = new BitVectorImpl(initialSize); | ||
updateCount(0); | ||
} | ||
|
||
/** | ||
* Constructor of a ranked bit vector of size <i>initialSize</i> and block | ||
* size <i>blockSize</i>. The bit vector contains <code>false</code> at all | ||
* indexes. | ||
* | ||
* @param initialSize | ||
* initial size of this ranked bit vector | ||
* @param blockSize | ||
* block size of this ranked bit vector | ||
*/ | ||
public RankedBitVectorImpl(long initialSize, int blockSize) { | ||
this.bitVector = new BitVectorImpl(initialSize); | ||
this.blockSize = blockSize; | ||
updateCount(0); | ||
} | ||
|
||
@Override | ||
public boolean addBit(boolean bit) { | ||
boolean ret = this.bitVector.addBit(bit); | ||
updateCount(this.bitVector.size() - 1); | ||
return ret; | ||
} | ||
|
||
@Override | ||
public long countBits(boolean bit, long position) { | ||
int blockNumber = getBlockNumber(position); | ||
long mark = ((long) blockNumber) * this.blockSize; | ||
long trueValues = 0; | ||
if (blockNumber > 0) { | ||
trueValues = this.count.get(blockNumber - 1); | ||
} | ||
for (long index = mark; index <= position; index++) { | ||
trueValues += this.bitVector.getBit(index) ? 1 : 0; | ||
} | ||
return bit ? trueValues : ((position + 1) - trueValues); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object obj) { | ||
if (this == obj) { | ||
return true; | ||
} | ||
if (!(obj instanceof BitVector)) { | ||
return false; | ||
} | ||
return this.bitVector.equals(obj); | ||
} | ||
|
||
@Override | ||
public long findPosition(boolean bit, long nOccurrence) { | ||
throw new UnsupportedOperationException(); | ||
} | ||
|
||
@Override | ||
public boolean getBit(long position) { | ||
return this.bitVector.getBit(position); | ||
} | ||
|
||
/** | ||
* Returns the block number for a given position in the bit vector. | ||
* | ||
* @param positionInBitVector | ||
* position in bit vector | ||
* @return the block number for a given position in the bit vector | ||
*/ | ||
int getBlockNumber(long positionInBitVector) { | ||
return (int) (positionInBitVector / this.blockSize); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return this.bitVector.hashCode(); | ||
} | ||
|
||
@Override | ||
public Iterator<Boolean> iterator() { | ||
return this.bitVector.iterator(); | ||
} | ||
|
||
@Override | ||
public void setBit(long position, boolean bit) { | ||
boolean oldBit = getBit(position); | ||
if (oldBit != bit) { | ||
this.bitVector.setBit(position, bit); | ||
int blockNumber = getBlockNumber(position); | ||
if (bit) { | ||
for (int index = blockNumber; index < this.count.size(); index++) { | ||
this.count.set(index, this.count.get(index) + 1); | ||
} | ||
} else { | ||
for (int index = blockNumber; index < this.count.size(); index++) { | ||
this.count.set(index, this.count.get(index) - 1); | ||
} | ||
} | ||
} | ||
} | ||
|
||
@Override | ||
public long size() { | ||
return this.bitVector.size(); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return this.bitVector.toString(); | ||
} | ||
|
||
/** | ||
* This method updates the whole count starting from a given position | ||
* <i>startingPosition</i>. This method assumes that all the previous | ||
* positions are updated. | ||
* | ||
* @param startingPosition | ||
* starting position to update the count | ||
* @param bit | ||
* bit | ||
*/ | ||
void updateCount(long startingPosition) { | ||
for (long index = startingPosition; index < this.bitVector.size(); index++) { | ||
int positionInCount = getBlockNumber(index); | ||
if (positionInCount >= this.count.size()) { | ||
long lastValue = 0; | ||
if (this.count.size() > 0) { | ||
lastValue = this.count.get(this.count.size() - 1); | ||
} | ||
this.count.add(lastValue); | ||
} | ||
if (this.bitVector.getBit(index)) { | ||
this.count.set(positionInCount, | ||
this.count.get(positionInCount) + 1); | ||
} | ||
} | ||
} | ||
|
||
} |
Oops, something went wrong.