blob: da17154e103e43dc2903d116c21ed7ebf46e26aa [file] [log] [blame]
/*=========================================================================
* Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
* This product is protected by U.S. and international copyright
* and intellectual property laws. Pivotal products are covered by
* one or more patents listed at http://www.pivotal.io/patents.
*=========================================================================
*/
/*
* Copyright (C) 2012 Clearspring Technologies, Inc.
*
* 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.
*/
package com.gemstone.gemfire.cache.hdfs.internal.cardinality;
public class RegisterSet
{
public final static int LOG2_BITS_PER_WORD = 6;
public final static int REGISTER_SIZE = 5;
public final int count;
public final int size;
private final int[] M;
public RegisterSet(int count)
{
this(count, null);
}
public RegisterSet(int count, int[] initialValues)
{
this.count = count;
int bits = getBits(count);
if (initialValues == null)
{
if (bits == 0)
{
this.M = new int[1];
}
else if (bits % Integer.SIZE == 0)
{
this.M = new int[bits];
}
else
{
this.M = new int[bits + 1];
}
}
else
{
this.M = initialValues;
}
this.size = this.M.length;
}
public static int getBits(int count)
{
return count / LOG2_BITS_PER_WORD;
}
public void set(int position, int value)
{
int bucketPos = position / LOG2_BITS_PER_WORD;
int shift = REGISTER_SIZE * (position - (bucketPos * LOG2_BITS_PER_WORD));
this.M[bucketPos] = (this.M[bucketPos] & ~(0x1f << shift)) | (value << shift);
}
public int get(int position)
{
int bucketPos = position / LOG2_BITS_PER_WORD;
int shift = REGISTER_SIZE * (position - (bucketPos * LOG2_BITS_PER_WORD));
return (this.M[bucketPos] & (0x1f << shift)) >>> shift;
}
public boolean updateIfGreater(int position, int value)
{
int bucket = position / LOG2_BITS_PER_WORD;
int shift = REGISTER_SIZE * (position - (bucket * LOG2_BITS_PER_WORD));
int mask = 0x1f << shift;
// Use long to avoid sign issues with the left-most shift
long curVal = this.M[bucket] & mask;
long newVal = value << shift;
if (curVal < newVal) {
this.M[bucket] = (int)((this.M[bucket] & ~mask) | newVal);
return true;
} else {
return false;
}
}
public void merge(RegisterSet that)
{
for (int bucket = 0; bucket < M.length; bucket++)
{
int word = 0;
for (int j = 0; j < LOG2_BITS_PER_WORD; j++)
{
int mask = 0x1f << (REGISTER_SIZE * j);
int thisVal = (this.M[bucket] & mask);
int thatVal = (that.M[bucket] & mask);
word |= (thisVal < thatVal) ? thatVal : thisVal;
}
this.M[bucket] = word;
}
}
public int[] bits()
{
int[] copy = new int[size];
System.arraycopy(M, 0, copy, 0, M.length);
return copy;
}
}