Skip to content
This repository was archived by the owner on Jul 13, 2022. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 83 additions & 0 deletions elfling_unpack.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#ifndef ELFLING_UNPACK_HPP
#define ELFLING_UNPACK_HPP

#include <stdint.h>

#if !defined(MAX_CONTEXT_COUNT)
#define MAX_CONTEXT_COUNT 16
#endif

#if !defined(MAX_CONTEXT_SIZE)
#define MAX_CONTEXT_SIZE (4 << 20)
#endif

static void elfling_unpack(const uint8_t* weights, const uint8_t* contexts, unsigned contextCount, void* work,
const void* in, void* out, unsigned outLen)
{
uint8_t* counters[MAX_CONTEXT_COUNT]; // Counter base offsets
uint8_t* cp[MAX_CONTEXT_COUNT]; // Current counters
const uint8_t* archive = static_cast<const uint8_t*>(in);
uint8_t* cout = static_cast<uint8_t*>(out);
uint8_t* base = static_cast<uint8_t*>(work);

for (uint8_t m = 0; m < contextCount; ++m) {
counters[m] = base;
cp[m] = base;
base += MAX_CONTEXT_SIZE;
}

*cout = 1;
uint32_t x1 = 0, x2 = 0xffffffff;
for (uint32_t j = outLen * 8; j > 0; --j) {
uint32_t n0 = 1, n1 = 1;
for (uint8_t m = 0; m < contextCount; ++m) {
n0 += cp[m][0] * weights[m];
n1 += cp[m][1] * weights[m];
}

uint32_t xmid = x1 + n0 * (uint64_t)(x2 - x1) / (n0 + n1);

uint8_t y;
cout[0] <<= 1;
if (*(uint32_t*)archive <= xmid) {
x2 = xmid;
y = 0;
} else {
cout[0] += 1;
x1 = xmid + 1;
y = 1;
}

if (((j - 1) & 7) == 0) { // Start new byte
cout++;
*cout = 1;
}

// Count y by context
for (uint8_t m = 0; m < contextCount; ++m) {
if (cp[m][y] < 255)
++cp[m][y];
if (cp[m][1 - y] > 2)
cp[m][1 - y] = cp[m][1 - y] / 2 + 1;
uint32_t off = 0;
for (char i = 0; i < 8; ++i) {
if (contexts[m] & (1 << i)) {
off = (off << 8) + cout[-i];
}
}
uint32_t c = 0;
while (*(uint32_t*)&counters[m][c] != 0 && *(uint32_t*)&counters[m][c] != off) c += 6;
*(uint32_t*)&counters[m][c] = off;
cp[m] = &counters[m][c + 4];
}

while (((x1 ^ x2) >> 24) == 0) {
x1 <<= 8;
x2 = (x2 << 8) + 255;
--archive;
}
}
}

#endif

6 changes: 3 additions & 3 deletions pack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ bool Compressor::Compress(CompressionParameters* params, void* in, int inLen, vo
CompressSingle(&c, in, inLen, out, &pats[pc].bs);
++pc;
}
qsort(pats, pc, sizeof(Context), (__compar_fn_t)CompareContext);
qsort(pats, pc, sizeof(Context), (int (*)(const void*, const void*))CompareContext);
if (verbose_) {
for (int i = 0; i < pc; ++i) {
printf("Pattern %2d [%2.2x] = %d bytes @ %d\n", i, pats[i].ctx, pats[i].bs, pats[i].bw);
Expand Down Expand Up @@ -154,7 +154,7 @@ bool Compressor::Compress(CompressionParameters* params, void* in, int inLen, vo
g[j].fitness = *outLen;
CompressSingle(&g[j].params, in, inLen, out, &g[j].fitness);
}
qsort(g, GENOME_SIZE, sizeof(Genome), (__compar_fn_t)CompareGenome);
qsort(g, GENOME_SIZE, sizeof(Genome), (int (*)(const void*, const void*))CompareGenome);
for (int j = 0; j < GENOME_SIZE; ++j) {
if (j >= 3) break;
printf("I[%3d,%d]: %d", i, j, g[j].fitness);
Expand Down Expand Up @@ -189,7 +189,7 @@ bool Compressor::Compress(CompressionParameters* params, void* in, int inLen, vo
trg2[k >> 1] = src2[k >> 1];
}
}
qsort(g, GENOME_SIZE / 2, sizeof(Genome), (__compar_fn_t)CompareGenome);
qsort(g, GENOME_SIZE / 2, sizeof(Genome), (int (*)(const void*, const void*))CompareGenome);
for (int j = 1; j < GENOME_SIZE / 2; ++j) {
if (!memcmp(g[j].params.weights, g[j - 1].params.weights, CONTEXT_COUNT) && !memcmp(g[j].params.contexts, g[j - 1].params.contexts, CONTEXT_COUNT)) {
int byte = rand() % (2 * CONTEXT_COUNT);
Expand Down
67 changes: 3 additions & 64 deletions unpack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,73 +16,12 @@

#include "pack.h"

#include <stdio.h>
#include "elfling_unpack.hpp"

#include <string.h>

void Compressor::Decompress(CompressionParameters* params, void* in, void* out, int outLen) {
u8* counters[MAX_CONTEXT_COUNT]; // Counter base offsets
u8* cp[MAX_CONTEXT_COUNT]; // Current counters
u8* archive = (u8*)in;
u8* cout = (u8*)out;

memset(modelCounters_, 0, MAX_CONTEXT_SIZE * params->contextCount);
u8* base = modelCounters_;
for (int m = 0; m < params->contextCount; ++m) {
counters[m] = base;
cp[m] = base;
base += MAX_CONTEXT_SIZE;
}

*cout = 1;
u32 x1 = 0, x2 = 0xffffffff;
for (u32 j = outLen * 8; j > 0; --j) {
u32 n0 = 1, n1 = 1;
for (char m = 0; m < params->contextCount; ++m) {
n0 += cp[m][0] * params->weights[m];
n1 += cp[m][1] * params->weights[m];
}

u32 xmid = x1 + n0 * (u64)(x2 - x1) / (n0 + n1);

char y;
cout[0] <<= 1;
if (*(u32*)archive <= xmid) {
x2 = xmid;
y = 0;
} else {
cout[0] += 1;
x1 = xmid + 1;
y = 1;
}

if (((j - 1) & 7) == 0) { // Start new byte
cout++;
*cout = 1;
}

// Count y by context
for (char m = 0; m < params->contextCount; ++m) {
if (cp[m][y] < 255)
++cp[m][y];
if (cp[m][1 - y] > 2)
cp[m][1 - y] = cp[m][1 - y] / 2 + 1;
u32 off = 0, cnt = 0;
for (char i = 0; i < 8; ++i) {
if (params->contexts[m] & (1 << i)) {
off = (off << 8) + cout[-i];
}
}
u32 c = 0;
while (*(u32*)&counters[m][c] != 0 && *(u32*)&counters[m][c] != off) c += 6;
*(u32*)&counters[m][c] = off;
cp[m] = &counters[m][c + 4];
}

while (((x1 ^ x2) >> 24) == 0) {
x1 <<= 8;
x2 = (x2 << 8) + 255;
--archive;
}
}
elfling_unpack(params->weights, params->contexts, params->contextCount, modelCounters_, in, out, outLen);
}