File Manager
/**
* @namespace WPGMZA
* @module EliasFano
* @requires WPGMZA
*/
jQuery(function($) {
WPGMZA.EliasFano = function()
{
if(!WPGMZA.EliasFano.isSupported)
throw new Error("Elias Fano encoding is not supported on browsers without Uint8Array");
if(!WPGMZA.EliasFano.decodingTablesInitialised)
WPGMZA.EliasFano.createDecodingTable();
}
WPGMZA.EliasFano.isSupported = ("Uint8Array" in window);
WPGMZA.EliasFano.decodingTableHighBits = [];
WPGMZA.EliasFano.decodingTableDocIDNumber = null;
WPGMZA.EliasFano.decodingTableHighBitsCarryover = null;
WPGMZA.EliasFano.createDecodingTable = function()
{
WPGMZA.EliasFano.decodingTableDocIDNumber = new Uint8Array(256);
WPGMZA.EliasFano.decodingTableHighBitsCarryover = new Uint8Array(256);
var decodingTableHighBits = WPGMZA.EliasFano.decodingTableHighBits;
var decodingTableDocIDNumber = WPGMZA.EliasFano.decodingTableDocIDNumber;
var decodingTableHighBitsCarryover = WPGMZA.EliasFano.decodingTableHighBitsCarryover;
for(var i = 0; i < 256; i++)
{
var zeroCount = 0;
decodingTableHighBits[i] = [];
for(var j = 7; j >= 0; j--)
{
if((i & (1 << j)) > 0)
{
decodingTableHighBits[i][decodingTableDocIDNumber[i]] = zeroCount;
decodingTableDocIDNumber[i]++;
zeroCount = 0;
}
else
zeroCount = (zeroCount + 1) % 0xFF;
}
decodingTableHighBitsCarryover[i] = zeroCount;
}
WPGMZA.EliasFano.decodingTablesInitialised = true;
}
WPGMZA.EliasFano.prototype.encode = function(list)
{
var lastDocID = 0,
buffer1 = 0,
bufferLength1 = 0,
buffer2 = 0,
bufferLength2 = 0;
if(list.length == 0)
return result;
function toByte(n)
{
return n & 0xFF;
}
var compressedBufferPointer1 = 0;
var compressedBufferPointer2 = 0;
var largestBlockID = list[list.length - 1];
var averageDelta = largestBlockID / list.length;
var averageDeltaLog = Math.log2(averageDelta);
var lowBitsLength = Math.floor(averageDeltaLog);
var lowBitsMask = (1 << lowBitsLength) - 1;
var prev = null;
var maxCompressedSize = Math.floor(
(
2 + Math.ceil(
Math.log2(averageDelta)
)
) * list.length / 8
) + 6;
var compressedBuffer = new Uint8Array(maxCompressedSize);
if(lowBitsLength < 0)
lowBitsLength = 0;
compressedBufferPointer2 = Math.floor(lowBitsLength * list.length / 8 + 6);
compressedBuffer[compressedBufferPointer1++] = toByte( list.length );
compressedBuffer[compressedBufferPointer1++] = toByte( list.length >> 8 );
compressedBuffer[compressedBufferPointer1++] = toByte( list.length >> 16 );
compressedBuffer[compressedBufferPointer1++] = toByte( list.length >> 24 );
compressedBuffer[compressedBufferPointer1++] = toByte( lowBitsLength );
list.forEach(function(docID) {
var docIDDelta = (docID - lastDocID - 1);
if(!WPGMZA.isNumeric(docID))
throw new Error("Value is not numeric");
// NB: Force docID to an integer in case it's a string
docID = parseInt(docID);
if(prev !== null && docID <= prev)
throw new Error("Elias Fano encoding can only be used on a sorted, ascending list of unique integers.");
prev = docID;
buffer1 <<= lowBitsLength;
buffer1 |= (docIDDelta & lowBitsMask);
bufferLength1 += lowBitsLength;
// Flush buffer 1
while(bufferLength1 > 7)
{
bufferLength1 -= 8;
compressedBuffer[compressedBufferPointer1++] = toByte( buffer1 >> bufferLength1 );
}
var unaryCodeLength = (docIDDelta >> lowBitsLength) + 1;
buffer2 <<= unaryCodeLength;
buffer2 |= 1;
bufferLength2 += unaryCodeLength;
// Flush buffer 2
while(bufferLength2 > 7)
{
bufferLength2 -= 8;
compressedBuffer[compressedBufferPointer2++] = toByte( buffer2 >> bufferLength2 );
}
lastDocID = docID;
});
if(bufferLength1 > 0)
compressedBuffer[compressedBufferPointer1++] = toByte( buffer1 << (8 - bufferLength1) );
if(bufferLength2 > 0)
compressedBuffer[compressedBufferPointer2++] = toByte( buffer2 << (8 - bufferLength2) );
var result = new Uint8Array(compressedBuffer);
result.pointer = compressedBufferPointer2;
return result;
}
WPGMZA.EliasFano.prototype.decode = function(compressedBuffer)
{
var resultPointer = 0;
var list = [];
//console.log("Decoding buffer from pointer " + compressedBuffer.pointer);
//console.log(compressedBuffer);
var decodingTableHighBits = WPGMZA.EliasFano.decodingTableHighBits;
var decodingTableDocIDNumber = WPGMZA.EliasFano.decodingTableDocIDNumber;
var decodingTableHighBitsCarryover = WPGMZA.EliasFano.decodingTableHighBitsCarryover;
var lowBitsPointer = 0,
lastDocID = 0,
docID = 0,
docIDNumber = 0;
var listCount = compressedBuffer[lowBitsPointer++];
//console.log("listCount is now " + listCount);
listCount |= compressedBuffer[lowBitsPointer++] << 8;
//console.log("listCount is now " + listCount);
listCount |= compressedBuffer[lowBitsPointer++] << 16;
//console.log("listCount is now " + listCount);
listCount |= compressedBuffer[lowBitsPointer++] << 24;
//console.log("Read list count " + listCount);
var lowBitsLength = compressedBuffer[lowBitsPointer++];
//console.log("lowBitsLength = " + lowBitsLength);
var highBitsPointer,
lowBitsCount = 0,
lowBits = 0,
cb = 1;
for(
highBitsPointer = Math.floor(lowBitsLength * listCount / 8 + 6);
highBitsPointer < compressedBuffer.pointer;
highBitsPointer++
)
{
docID += decodingTableHighBitsCarryover[cb];
cb = compressedBuffer[highBitsPointer];
docIDNumber = decodingTableDocIDNumber[cb];
for(var i = 0; i < docIDNumber; i++)
{
docID <<= lowBitsCount;
docID |= lowBits & ((1 << lowBitsCount) - 1);
while(lowBitsCount < lowBitsLength)
{
docID <<= 8;
lowBits = compressedBuffer[lowBitsPointer++];
docID |= lowBits;
lowBitsCount += 8;
}
lowBitsCount -= lowBitsLength;
docID >>= lowBitsCount;
docID += (decodingTableHighBits[cb][i] << lowBitsLength) + lastDocID + 1;
list[resultPointer++] = docID;
lastDocID = docID;
docID = 0;
}
}
return list;
}
});
File Manager Version 1.0, Coded By Lucas
Email: hehe@yahoo.com