// CompressionSearch
// The terms are flying all over the place with this one
// (compressor, decompressor, compression, decompression, ...)
// Basic idea: INPUT DATA (byte list) is compressed into a
// CUSTOM OBJECT (called the "COMPRESSION"), which, when run
// under a fitting COMPRESSION REGIME produces the INPUT DATA.
//
// Every compression can also be converted to and from a byte array
// (the compression regime does this).
sclass CompressionSearch implements Steppable {
// user-set
CompressionRegime regime;
L inputData;
Steppable searcher; // main object that performs the search (optional)
// public output variables
new Best best;
bool searcherDone;
*(CompressionRegime *regime) {}
*(CompressionRegime *regime, LByte *inputData) {}
*(CompressionRegime *regime, byte[] inputData) { this.inputData = byteArrayToList(inputData); }
// can submit concurrently!
Submission submit(A compression) { ret _submit(compression); }
// private (although Submission is returned)
class Submission {
toString {
ret linesLL(
"Compressor " + (correct() ? "correct" : "incorrect"),
"Compression factor " + score(),
"Code:",
indentx(str(decompressor())),
"Code as bytes:",
indentx(bytesToHex(compressed()))
);
}
void setDecompressor(A decompressor) {
this.decompressor_cache = decompressor;
}
LByte inputData() { ret inputData; }
byte[] inputDataAsArray() { ret byteListToArray(inputData); }
simplyCached byte[] compressed() {
ret decompressor_cache == null ?: regime.decompressorToBytes(decompressor_cache);
}
simplyCached A decompressor() {
ret compressed_cache == null ?: regime.decompressorFromBytes(compressed_cache);
}
int compressedSize() { ret l(compressed()); }
simplyCached double score() {
ret doubleRatio(inputDataSize(), compressedSize());
}
bool decompressed;
O decompressedValue;
O decompressed() {
if (!decompressed) {
decompressedValue = regime.runDecompressor(decompressor());
set decompressed;
}
ret decompressedValue;
}
simplyCached Bool correct() {
ret eq(toByteList(decompressed()), inputData());
}
}
int inputDataSize() { ret l(inputData); }
Submission _submit(A compression) {
if (compression == null) null;
new Submission s;
s.setDecompressor(compression);
if (s.score() > best.score())
if (!s.correct())
warn("Compressor didn't verify");
else
best.put(s, s.score());
ret s;
}
public bool step() {
if (searcherDone || searcher == null) false;
if (searcher.step()) true;
set searcherDone;
false;
}
}