@gmod/cram
Version:
read CRAM files with pure Javascript
224 lines • 7.41 kB
JavaScript
"use strict";
/* eslint-disable no-var */
// @ts-nocheck
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.decode = decode;
/*
* Copyright (c) 2019-2020 Genome Research Ltd.
* Author(s): James Bonfield
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* 3. Neither the names Genome Research Ltd and Wellcome Trust Sanger
* Institute nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY GENOME RESEARCH LTD AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENOME RESEARCH
* LTD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
const iostream_ts_1 = __importDefault(require("./iostream.js"));
// ----------------------------------------------------------------------
// rANS primitives itself
//
// RansGet* is decoder side
function RansGetCumulativeFreq(R) {
return R & 0xfff;
}
function RansGetSymbolFromFreq(C, f) {
// NOTE: Inefficient.
// In practice we would implement this via a precomputed
// lookup table C2S[f]; see RansBuildC2S below.
let s = 0;
while (f >= C[s + 1]) {
s++;
}
return s;
}
function RansBuildC2S(C) {
const C2S = new Array(0x1000);
let s = 0;
for (let f = 0; f < 0x1000; f++) {
while (f >= C[s + 1]) {
s++;
}
C2S[f] = s;
}
return C2S;
}
function RansAdvanceStep(R, c, f) {
return f * (R >> 12) + (R & 0xfff) - c;
}
function RansRenorm(src, R) {
while (R < 1 << 23) {
R = (R << 8) + src.ReadByte();
}
return R;
}
// ----------------------------------------------------------------------
// Main rANS entry function: decodes a compressed src and
// returns the uncompressed buffer.
function decode(src) {
const stream = new iostream_ts_1.default(src);
const order = stream.ReadByte();
const n_in = stream.ReadUint32();
const n_out = stream.ReadUint32();
return order == 0 ? RansDecode0(stream, n_out) : RansDecode1(stream, n_out);
}
// ----------------------------------------------------------------------
// Order-0 decoder
// Decode a single table of order-0 frequences,
// filling out the F and C arrays.
function ReadFrequencies0(src, F, C) {
// Initialise; not in the specification - implicit?
for (var i = 0; i < 256; i++) {
F[i] = 0;
}
let sym = src.ReadByte();
let last_sym = sym;
let rle = 0;
// Read F[]
do {
const f = src.ReadITF8();
F[sym] = f;
if (rle > 0) {
rle--;
sym++;
}
else {
sym = src.ReadByte();
if (sym == last_sym + 1) {
rle = src.ReadByte();
}
}
last_sym = sym;
} while (sym != 0);
// Compute C[] from F[]
C[0] = 0;
for (var i = 0; i <= 255; i++) {
C[i + 1] = C[i] + F[i];
}
}
function RansDecode0(src, nbytes) {
// Decode frequencies
const F = new Array(256);
const C = new Array(256);
ReadFrequencies0(src, F, C);
// Fast lookup to avoid slow RansGetSymbolFromFreq
const C2S = RansBuildC2S(C);
// Initialise rANS state
const R = new Array(4);
for (var i = 0; i < 4; i++) {
R[i] = src.ReadUint32();
}
// Main decode loop
const output = new Uint8Array(nbytes);
for (var i = 0; i < nbytes; i++) {
const i4 = i % 4;
const f = RansGetCumulativeFreq(R[i4]);
const s = C2S[f]; // Equiv to RansGetSymbolFromFreq(C, f);
output[i] = s;
R[i4] = RansAdvanceStep(R[i4], C[s], F[s]);
R[i4] = RansRenorm(src, R[i4]);
}
return output;
}
// ----------------------------------------------------------------------
// Order-1 decoder
// Decode a table of order-1 frequences,
// filling out the F and C arrays.
function ReadFrequencies1(src, F, C) {
// Initialise; not in the specification - implicit?
for (let i = 0; i < 256; i++) {
F[i] = new Array(256);
C[i] = new Array(256);
for (let j = 0; j < 256; j++) {
F[i][j] = 0;
}
}
let sym = src.ReadByte();
let last_sym = sym;
let rle = 0;
// Read F[]
do {
ReadFrequencies0(src, F[sym], C[sym]);
if (rle > 0) {
rle--;
sym++;
}
else {
sym = src.ReadByte();
if (sym == last_sym + 1) {
rle = src.ReadByte();
}
}
last_sym = sym;
} while (sym != 0);
}
function RansDecode1(src, nbytes) {
// Decode frequencies
const F = new Array(256);
const C = new Array(256);
ReadFrequencies1(src, F, C);
// Fast lookup to avoid slow RansGetSymbolFromFreq
const C2S = new Array(256);
for (var i = 0; i < 256; i++) {
C2S[i] = RansBuildC2S(C[i]);
}
// Initialise rANS state
const R = new Array(4);
const L = new Array(4);
for (var j = 0; j < 4; j++) {
R[j] = src.ReadUint32();
L[j] = 0;
}
// Main decode loop
const output = new Uint8Array(nbytes);
const nbytes4 = Math.floor(nbytes / 4);
for (var i = 0; i < nbytes4; i++) {
for (var j = 0; j < 4; j++) {
var f = RansGetCumulativeFreq(R[j]);
// var s = RansGetSymbolFromFreq(C[L[j]], f);
var s = C2S[L[j]][f]; // Precomputed version of above
output[i + j * nbytes4] = s;
R[j] = RansAdvanceStep(R[j], C[L[j]][s], F[L[j]][s]);
R[j] = RansRenorm(src, R[j]);
L[j] = s;
}
}
// Now deal with the remainder if buffer size is not a multiple of 4,
// using rANS state 3 exclusively. (It'd have been nice to have
// designed this to just act as if we kept going with a bail out.)
i = 4 * i;
while (i < nbytes) {
var f = RansGetCumulativeFreq(R[3]);
var s = RansGetSymbolFromFreq(C[L[3]], f);
output[i++] = s;
R[3] = RansAdvanceStep(R[3], C[L[3]][s], F[L[3]][s]);
R[3] = RansRenorm(src, R[3]);
L[3] = s;
}
return output;
}
//# sourceMappingURL=rans.js.map