Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
aptr288 authored Dec 13, 2017
1 parent 0728d95 commit f6e27a1
Show file tree
Hide file tree
Showing 6 changed files with 686 additions and 231 deletions.
321 changes: 321 additions & 0 deletions IntMap.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,321 @@
#include "IntMap.h"

#include <algorithm>

using namespace std;

#pragma warning(disable: 4996)

IntMap::IntMap() {
init(1 << 2);
}

IntMap::IntMap(int size) {
init(size, 0.75f);
}

IntMap::IntMap(int size, float fillFactor) {
init(size, fillFactor);
}

void IntMap::init(int size)
{
init(size, 0.75f);
}

void IntMap::init(int size, float fillFactor)
{
if (fillFactor <= 0 || fillFactor >= 1)
{
printf("FillFactor must be in (0, 1)");
}
if (size <= 0)
{
printf("Size must be positive!");
}
int capacity = arraySize(size, fillFactor);
m_mask = capacity - 1;
m_mask2 = capacity * 2 - 1;
m_fillFactor = fillFactor;

m_data.resize(capacity * 2);// = new int[capacity * 2];
m_threshold = (int)(capacity * fillFactor);
}

int IntMap::get(int key) {
int ptr = (phiMix(key) & m_mask) << 1;

if (key == FREE_KEY)
return m_hasFreeKey ? m_freeValue : NO_VALUE;

int k = m_data[ptr];

if (k == FREE_KEY)
return NO_VALUE; //end of chain already
if (k == key) //we check FREE prior to this call
return m_data[ptr + 1];

while (true) {
ptr = ptr + 2 & m_mask2; //that's next index
k = m_data[ptr];
if (k == FREE_KEY)
return NO_VALUE;
if (k == key)
return m_data[ptr + 1];
}
}

// for use as IntSet - Paul Tarau

bool IntMap::contains(int key) {
return NO_VALUE != get(key);
}

bool IntMap::add(int key) {
return NO_VALUE != put(key, 666);
}

bool IntMap::del(int key) {
return NO_VALUE != remove(key);
}

bool IntMap::isEmpty() {
return 0 == m_size;
}

void IntMap::intersect0(IntMap * m, vector<IntMap *> maps, vector<IntMap *> vmaps, IntStack * r) {
vector<int> data = m->m_data;
//int[] data = m.m_data;
for (int k = 0; k < data.size(); k += 2) {
bool found = true;
int key = data[k];
if (FREE_KEY == key) {
continue;
}
for (int i = 1; i < maps.size(); i++) {
IntMap * mp = maps[i];
int val = mp->get(key);

if (NO_VALUE == val) {
IntMap * vmap = vmaps[i];
int vval = vmap->get(key);
if (NO_VALUE == vval) {
found = false;
break;
}
}
}
if (found) {
r->push(key);
}
}
}

IntStack * IntMap::intersect(vector<IntMap *> maps, vector <IntMap *> vmaps) {
IntStack * r = new IntStack();

intersect0(maps[0], maps, vmaps, r);
intersect0(vmaps[0], maps, vmaps, r);
return r;
}

// end changes

int IntMap::put(int key, int value) {
if (key == FREE_KEY) {
int ret = m_freeValue;
if (!m_hasFreeKey) {
++m_size;
}
m_hasFreeKey = true;
m_freeValue = value;
return ret;
}

int ptr = (phiMix(key) & m_mask) << 1;
int k = m_data[ptr];
if (k == FREE_KEY) //end of chain already
{
m_data[ptr] = key;
m_data[ptr + 1] = value;
if (m_size >= m_threshold) {
rehash(m_data.size() * 2); //size is set inside
} else {
++m_size;
}
return NO_VALUE;
} else if (k == key) //we check FREE prior to this call
{
int ret = m_data[ptr + 1];
m_data[ptr + 1] = value;
return ret;
}

while (true) {
ptr = ptr + 2 & m_mask2; //that's next index calculation
k = m_data[ptr];
if (k == FREE_KEY) {
m_data[ptr] = key;
m_data[ptr + 1] = value;
if (m_size >= m_threshold) {
rehash(m_data.size() * 2); //size is set inside
} else {
++m_size;
}
return NO_VALUE;
} else if (k == key) {
int ret = m_data[ptr + 1];
m_data[ptr + 1] = value;
return ret;
}
}
}

int IntMap::remove(int key) {
if (key == FREE_KEY) {
if (!m_hasFreeKey)
return NO_VALUE;
m_hasFreeKey = false;
--m_size;
return m_freeValue; //value is not cleaned
}

int ptr = (phiMix(key) & m_mask) << 1;
int k = m_data[ptr];
if (k == key) //we check FREE prior to this call
{
int res = m_data[ptr + 1];
shiftKeys(ptr);
--m_size;
return res;
} else if (k == FREE_KEY)
return NO_VALUE; //end of chain already
while (true) {
ptr = ptr + 2 & m_mask2; //that's next index calculation
k = m_data[ptr];
if (k == key) {
int res = m_data[ptr + 1];
shiftKeys(ptr);
--m_size;
return res;
} else if (k == FREE_KEY)
return NO_VALUE;
}
}

int IntMap::shiftKeys(int pos) {
// Shift entries with the same hash.
int last, slot;
int k;
vector<int> data = m_data;
// int[] data = m_data;
while (true) {
pos = (last = pos) + 2 & m_mask2;
while (true) {
if ((k = data[pos]) == FREE_KEY) {
data[last] = FREE_KEY;
return last;
}
slot = (phiMix(k) & m_mask) << 1; //calculate the starting slot for the current key
if (last <= pos ? last >= slot || slot > pos : last >= slot && slot > pos) {
break;
}
pos = pos + 2 & m_mask2; //go to the next entry
}
data[last] = k;
data[last + 1] = data[pos + 1];
}
}

int IntMap::size() {
return m_size;
}

void IntMap::rehash(int newCapacity) {
m_threshold = (int) (newCapacity / 2 * m_fillFactor);
m_mask = newCapacity / 2 - 1;
m_mask2 = newCapacity - 1;

int oldCapacity = m_data.size();
vector<int> oldData = m_data;

m_data.clear();
m_data.resize(newCapacity);// = new int[newCapacity];
m_size = m_hasFreeKey ? 1 : 0;

for (int i = 0; i < oldCapacity; i += 2) {
int oldKey = oldData[i];
if (oldKey != FREE_KEY) {
put(oldKey, oldData[i + 1]);
}
}
}

/** Taken from FastUtil implementation */

/** Return the least power of two greater than or equal to the specified value.
*
* <p>Note that this function will return 1 when the argument is 0.
*
* @param x a long integer smaller than or equal to 2<sup>62</sup>.
* @return the least power of two greater than or equal to the specified value.
*/
int IntMap::nextPowerOfTwo(long x) {
if (x == 0)
return 1;
x--;
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
return (x | x >> 32) + 1;
}

/** Returns the least power of two smaller than or equal to 2<sup>30</sup>
* and larger than or equal to <code>Math.ceil( expected / f )</code>.
*
* @param expected the expected number of elements in a hash table.
* @param f the load factor.
* @return the minimum possible size for a backing array.
* @throws IllegalArgumentException if the necessary size is larger than 2<sup>30</sup>.
*/
int IntMap::arraySize(int expected, float f) {
long s = max(2, nextPowerOfTwo((long) ceil(expected / f)));
if (s > 1 << 30)
{
char buffer[256];
sprintf(buffer, "Too large (%d expected elements with load factor %f)\n", expected, f);
printf(buffer);
}
return (int) s;
}

int IntMap::phiMix(int x) {
int h = x * INT_PHI;
return h ^ h >> 16;
}

string IntMap::toString() {
//return java.util.Arrays.toString(m_data);
string b = "{";
// StringBuffer b = new StringBuffer("{");
int l = m_data.size();
bool first = true;
for (int i = 0; i < l; i += 2) {

int v = m_data[i];
if (v != FREE_KEY) {
if (!first) {
b += ",";
}
first = false;
char tmp[10];
sprintf(tmp, "%d", v - 1);
b += tmp;
// b.append(v - 1);
}
}
b += "}"; //.append("}");
return b;
}
Loading

0 comments on commit f6e27a1

Please sign in to comment.