package uk.ac.manchester.cs.jfact.helpers;
import java.io.Serializable;
/* This file is part of the JFact DL reasoner
Copyright 2011-2013 by Ignazio Palmisano, Dmitry Tsarkov, University of Manchester
This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA*/
import java.util.Arrays;
/**
* map int to int
*
* @author ignazio
*/
public class ArrayIntMap implements Serializable {
private static final long serialVersionUID = 11000L;
private int[][] values;
private int size = 0;
private static final int defaultSize = 16;
private int insertionIndex(int key) {
if (size == 0) {
return -1;
}
if (key < values[0][0]) {
return -1;
}
if (key > values[0][size - 1]) {
return -size - 1;
}
int lowerbound = 0;
if (size < AbstractFastSet.limit) {
for (; lowerbound < size; lowerbound++) {
if (values[0][lowerbound] == key) {
return lowerbound;
}
if (values[0][lowerbound] > key) {
return -lowerbound - 1;
}
}
return -lowerbound - 1;
}
int upperbound = size - 1;
while (lowerbound <= upperbound) {
int intermediate = lowerbound + (upperbound - lowerbound) / 2;
if (values[0][intermediate] == key) {
return intermediate;
}
if (values[0][intermediate] < key) {
lowerbound = intermediate + 1;
} else {
upperbound = intermediate - 1;
}
}
return -lowerbound - 1;
}
private void init() {
values = new int[2][defaultSize];
size = 0;
}
/**
* @param e
* e
* @param v
* v
*/
public void put(int e, int v) {
int pos = -1;
if (values == null) {
init();
// pos stays at -1, in an empty set that's the place to start - it
// will become 0
} else {
// else find the right place
pos = insertionIndex(e);
}
if (pos > -1) {
return;
}
int i = -pos - 1;
// i is now the insertion point
if (i >= values[0].length || size >= values[0].length) {
// no space left, increase
int[][] replacementvalues = new int[2][values[0].length
+ defaultSize];
for (int j = 0; j < values[0].length; j++) {
replacementvalues[0][j] = values[0][j];
replacementvalues[1][j] = values[1][j];
}
values = replacementvalues;
}
// size ensured, shift and insert now
for (int j = size - 1; j >= i; j--) {
values[0][j + 1] = values[0][j];
values[1][j + 1] = values[1][j];
}
values[0][i] = e;
values[1][i] = v;
// increase used size
size++;
}
/** clear the map */
public void clear() {
values = null;
size = 0;
}
/**
* @param o
* o
* @return true if o is a key
*/
public boolean containsKey(int o) {
if (values != null) {
return insertionIndex(o) > -1;
}
return false;
}
/**
* @param c
* c
* @return true if all elements in c are contained
*/
public boolean containsAll(ArrayIntMap c) {
if (c.size == 0) {
return true;
}
if (size == 0) {
return false;
}
if (c.size > size) {
return false;
}
if (size == c.size) {
for (int i = 0; i < size; i++) {
if (values[0][i] != c.values[0][i]) {
return false;
}
}
return true;
}
if (values[0][0] > c.values[0][0]
|| values[0][size - 1] < c.values[0][c.size() - 1]) {
// c boundaries are outside this set
return false;
}
int i = 0;
int j = 0;
int currentValue;
while (j < c.size()) {
currentValue = c.values[0][j];
boolean found = false;
while (i < size) {
if (values[0][i] == currentValue) {
// found the current value, next element in c - increase j
found = true;
break;
}
if (values[0][i] > currentValue) {
// found a value larger than the value it's looking for - c
// is not contained
return false;
}
// get(i) is < than current value: check next i
i++;
}
if (!found) {
// finished exploring this and currentValue was not found - it
// happens if currentValue < any element in this set
return false;
}
j++;
}
return true;
}
/** @return true if empty */
public boolean isEmpty() {
return values == null;
}
/**
* @param o
* o
*/
public void remove(int o) {
if (values == null) {
return;
}
int i = insertionIndex(o);
removeAt(i);
}
/** @return size */
public int size() {
return size;
}
/**
* @param i
* i
*/
public void removeAt(int i) {
if (values == null) {
return;
}
if (i > -1 && i < size) {
if (size == 1) {
values = null;
size = 0;
return;
}
for (int j = i; j < size - 1; j++) {
values[0][j] = values[0][j + 1];
values[1][j] = values[1][j + 1];
}
size--;
}
if (size == 0) {
values = null;
}
}
/**
* @param value
* value
* @return true if value is a value in
*/
public boolean containsValue(int value) {
for (int i = 0; i < size; i++) {
if (values[1][i] == value) {
return true;
}
}
return false;
}
/** @return all values */
public int[] values() {
return Arrays.copyOf(values[1], size);
}
/**
* @param key
* key
* @return value for key
*/
public int get(int key) {
int index = insertionIndex(key);
if (index < 0) {
return Integer.MIN_VALUE;
}
return values[1][index];
}
/** @return all keys */
public int[] keySet() {
return Arrays.copyOf(values[0], size);
}
/**
* @param i
* i
* @return key at position i
*/
public int keySet(int i) {
return values[0][i];
}
@Override
public int hashCode() {
int sum = 0;
for (int i = 0; i < size; i++) {
sum += values[0][i];
}
return sum;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (this == obj) {
return true;
}
if (obj instanceof ArrayIntMap) {
ArrayIntMap o = (ArrayIntMap) obj;
if (size != o.size) {
return false;
}
if (size == 0) {
// same size and both empty: equal
return true;
}
for (int i = 0; i < size; i++) {
if (values[0][i] != o.values[0][i]) {
return false;
}
}
return true;
}
return false;
}
@Override
public String toString() {
if (values != null) {
return Arrays.toString(Arrays.copyOf(values[0], size)) + '\n'
+ Arrays.toString(Arrays.copyOf(values[1], size));
}
return "[]";
}
}