/* Copyright 2008, 2009, 2010 by the Oxford University Computing Laboratory
This file is part of HermiT.
HermiT 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 3 of the License, or
(at your option) any later version.
HermiT 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 HermiT. If not, see <http://www.gnu.org/licenses/>.
*/
package org.semanticweb.HermiT.tableau;
import java.io.Serializable;
/**
* The actual implementation of the tuple tables used in the ExtensionTable
* class.
*/
public final class TupleTable implements Serializable {
private static final long serialVersionUID=-7712458276004062803L;
protected static final int PAGE_SIZE=512; // Must be a power of two!
protected final int m_arity;
protected Page[] m_pages;
protected int m_numberOfPages;
protected int m_tupleCapacity;
protected int m_firstFreeTupleIndex;
public TupleTable(int arity) {
m_arity=arity;
clear();
}
public int sizeInMemory() {
int size=m_pages.length*4;
for (int i=m_pages.length-1;i>=0;--i)
if (m_pages[i]!=null)
size+=m_pages[i].sizeInMemory();
return size;
}
public int getFirstFreeTupleIndex() {
return m_firstFreeTupleIndex;
}
public int addTuple(Object[] tupleBuffer) {
int newTupleIndex=m_firstFreeTupleIndex;
if (newTupleIndex==m_tupleCapacity) {
if (m_numberOfPages==m_pages.length) {
Page[] newPages=new Page[m_numberOfPages*3/2];
System.arraycopy(m_pages,0,newPages,0,m_numberOfPages);
m_pages=newPages;
}
m_pages[m_numberOfPages++]=new Page(m_arity);
m_tupleCapacity+=PAGE_SIZE;
}
m_pages[newTupleIndex / PAGE_SIZE].storeTuple((newTupleIndex % PAGE_SIZE)*m_arity,tupleBuffer);
m_firstFreeTupleIndex++;
return newTupleIndex;
}
public boolean tupleEquals(Object[] tupleBuffer,int tupleIndex,int compareLength) {
return m_pages[tupleIndex / PAGE_SIZE].tupleEquals(tupleBuffer,(tupleIndex % PAGE_SIZE)*m_arity,compareLength);
}
public boolean tupleEquals(Object[] tupleBuffer,int[] positionIndexes,int tupleIndex,int compareLength) {
return m_pages[tupleIndex / PAGE_SIZE].tupleEquals(tupleBuffer,positionIndexes,(tupleIndex % PAGE_SIZE)*m_arity,compareLength);
}
public void retrieveTuple(Object[] tupleBuffer,int tupleIndex) {
m_pages[tupleIndex / PAGE_SIZE].retrieveTuple((tupleIndex % PAGE_SIZE)*m_arity,tupleBuffer);
}
public Object getTupleObject(int tupleIndex,int objectIndex) {
assert objectIndex < m_arity;
return m_pages[tupleIndex / PAGE_SIZE].m_objects[(tupleIndex % PAGE_SIZE)*m_arity+objectIndex];
}
public void setTupleObject(int tupleIndex,int objectIndex,Object object) {
m_pages[tupleIndex / PAGE_SIZE].m_objects[(tupleIndex % PAGE_SIZE)*m_arity+objectIndex]=object;
}
public void truncate(int newFirstFreeTupleIndex) {
m_firstFreeTupleIndex=newFirstFreeTupleIndex;
}
public void nullifyTuple(int tupleIndex) {
m_pages[tupleIndex / PAGE_SIZE].nullifyTuple((tupleIndex % PAGE_SIZE)*m_arity);
}
public void clear() {
m_pages=new Page[10];
m_numberOfPages=1;
m_pages[0]=new Page(m_arity);
m_tupleCapacity=m_numberOfPages*PAGE_SIZE;
m_firstFreeTupleIndex=0;
}
protected final static class Page implements Serializable {
private static final long serialVersionUID=2239482172592108644L;
public final int m_arity;
public Object[] m_objects;
public Page(int arity) {
m_arity=arity;
m_objects=new Object[m_arity*PAGE_SIZE];
}
public int sizeInMemory() {
return m_objects.length*4;
}
public void storeTuple(int tupleStartIndex,Object[] tupleBuffer) {
System.arraycopy(tupleBuffer,0,m_objects,tupleStartIndex,tupleBuffer.length);
}
public void retrieveTuple(int tupleStartIndex,Object[] tupleBuffer) {
System.arraycopy(m_objects,tupleStartIndex,tupleBuffer,0,tupleBuffer.length);
}
public void nullifyTuple(int tupleStartIndex) {
for (int index=0;index<m_arity;index++)
m_objects[tupleStartIndex+index]=null;
}
public boolean tupleEquals(Object[] tupleBuffer,int tupleStartIndex,int compareLength) {
int sourceIndex=compareLength-1;
int targetIndex=tupleStartIndex+sourceIndex;
while (sourceIndex>=0) {
if (!tupleBuffer[sourceIndex].equals(m_objects[targetIndex]))
return false;
sourceIndex--;
targetIndex--;
}
return true;
}
public boolean tupleEquals(Object[] tupleBuffer,int[] positionIndexes,int tupleStartIndex,int compareLength) {
int sourceIndex=compareLength-1;
int targetIndex=tupleStartIndex+sourceIndex;
while (sourceIndex>=0) {
if (!tupleBuffer[positionIndexes[sourceIndex]].equals(m_objects[targetIndex]))
return false;
sourceIndex--;
targetIndex--;
}
return true;
}
}
}