///|
/// From extra bits, generate base values and reverse index map
/// Returns (b: base values array of 31, r: reverse map)
fn freb(
eb : FixedArray[Byte],
start : Int,
) -> (FixedArray[Int], FixedArray[Int]) {
let b : FixedArray[Int] = FixedArray::make(31, 0)
let mut s = start
for i in 0..<31 {
// In JS: b[i] = start += 1 << eb[i - 1]
// eb[-1] is undefined in JS, so 1 << undefined = 1
let shift = if i > 0 { eb[i - 1].to_int() } else { 0 }
s = s + (1 << shift)
b[i] = s
}
// numbers here are at max 18 bits
let r : FixedArray[Int] = FixedArray::make(b[30], 0)
for i in 1..<30 {
for j in b[i].. FixedArray[Int] {
let s = cd.length()
// count codes of each length
let l : FixedArray[Int] = FixedArray::make(mb, 0)
for i in 0..> rvb] = sv
v += 1
}
}
}
co2
} else {
let co2 = FixedArray::make(s, 0)
for i in 0..> (15 - cd[i].to_int())
le[cd[i].to_int() - 1] = le[cd[i].to_int() - 1] + 1
}
}
co2
}
co
}
///|
/// Recursively get max depth and assign code lengths using implicit array tree
fn ln_node(
node_idx : Int,
s_arr : FixedArray[Int],
l_arr : FixedArray[Int],
r_arr : FixedArray[Int],
lengths : FixedArray[Int],
d : Int,
) -> Int {
if s_arr[node_idx] == -1 {
let left = l_arr[node_idx]
let right = r_arr[node_idx]
let left_max = if left != -1 {
ln_node(left, s_arr, l_arr, r_arr, lengths, d + 1)
} else {
d
}
let right_max = if right != -1 {
ln_node(right, s_arr, l_arr, r_arr, lengths, d + 1)
} else {
d
}
if left_max > right_max {
left_max
} else {
right_max
}
} else {
lengths[s_arr[node_idx]] = d
d
}
}
///|
let h_tree_s_pool : Array[FixedArray[Int]] = []
///|
let h_tree_f_pool : Array[FixedArray[Int]] = []
///|
let h_tree_l_pool : Array[FixedArray[Int]] = []
///|
let h_tree_r_pool : Array[FixedArray[Int]] = []
///|
/// Create code lengths from a frequency table
/// d: frequency table, mb: max allowed bits
/// Returns (t: code lengths, l: max bits used)
fn h_tree(d : FixedArray[Int], mb : Int) -> (FixedArray[Byte], Int) {
let et : FixedArray[Byte] = FixedArray::make(0, b'\x00')
let s_arr = match h_tree_s_pool.pop() {
Some(arr) => arr
None => FixedArray::make(600, 0)
}
let f_arr = match h_tree_f_pool.pop() {
Some(arr) => arr
None => FixedArray::make(600, 0)
}
let l_arr = match h_tree_l_pool.pop() {
Some(arr) => arr
None => FixedArray::make(600, -1)
}
let r_arr = match h_tree_r_pool.pop() {
Some(arr) => arr
None => FixedArray::make(600, -1)
}
let nodes : Array[Int] = []
let mut next_node_idx = 0
for i in 0.. max_sym {
max_sym = s_arr[t2[i]]
}
}
// Compute code lengths
let tr : FixedArray[Int] = FixedArray::make(max_sym + 1, 0)
let mut mbt = ln_node(nodes[i1 - 1], s_arr, l_arr, r_arr, tr, 0)
if mbt > mb {
// Limit code lengths to mb
let mut i = 0
let mut dt = 0
let lft = mbt - mb
let cst = 1 << lft
// Sort by code length desc, then frequency asc
t2.sort_by(fn(a, b) {
if tr[s_arr[b]] != tr[s_arr[a]] {
tr[s_arr[b]] - tr[s_arr[a]]
} else {
f_arr[a] - f_arr[b]
}
})
while i < s {
let i2v = s_arr[t2[i]]
if tr[i2v] > mb {
dt += cst - (1 << (mbt - tr[i2v]))
tr[i2v] = mb
i += 1
} else {
break
}
}
dt = dt >> lft
while dt > 0 {
let i2v = s_arr[t2[i]]
if tr[i2v] < mb {
dt -= 1 << (mb - tr[i2v] - 1)
tr[i2v] = tr[i2v] + 1
} else {
i += 1
}
}
// i >= 0 check
while i > 0 && dt < 0 {
i -= 1
let i2v = s_arr[t2[i]]
if tr[i2v] == mb {
tr[i2v] = tr[i2v] - 1
dt += 1
}
}
mbt = mb
}
h_tree_s_pool.push(s_arr)
h_tree_f_pool.push(f_arr)
h_tree_l_pool.push(l_arr)
h_tree_r_pool.push(r_arr)
// Convert to byte array
let result : FixedArray[Byte] = FixedArray::make(max_sym + 1, b'\x00')
for i in 0..<=max_sym {
result[i] = tr[i].to_byte()
}
(result, mbt)
}
///|
/// Generate length codes from a code length array
/// Returns (codes array, count of meaningful entries)
fn lc_gen(c : FixedArray[Byte]) -> (FixedArray[Int], Int) {
let mut s = c.length()
// Find last nonzero
while s > 0 && c[s - 1] == b'\x00' {
s -= 1
}
if s == 0 {
// Return a single zero-length code entry (represents 1 symbol with length 0)
return (FixedArray::make(1, 0), 1)
}
let cl : FixedArray[Int] = FixedArray::make(s * 3, 0)
let mut cli = 0
let mut cln = c[0].to_int()
let mut cls = 1
for i in 1..<=s {
if i < s && c[i].to_int() == cln {
cls += 1
} else {
if cln == 0 && cls > 2 {
while cls > 138 {
cl[cli] = 32754
cli += 1
cls -= 138
}
if cls > 2 {
if cls > 10 {
cl[cli] = ((cls - 11) << 5) | 28690
} else {
cl[cli] = ((cls - 3) << 5) | 12305
}
cli += 1
cls = 0
}
} else if cls > 3 {
cl[cli] = cln
cli += 1
cls -= 1
while cls > 6 {
cl[cli] = 8304
cli += 1
cls -= 6
}
if cls > 2 {
cl[cli] = ((cls - 3) << 5) | 8208
cli += 1
cls = 0
}
}
while cls > 0 {
cl[cli] = cln
cli += 1
cls -= 1
}
cls = 1
if i < s {
cln = c[i].to_int()
}
}
}
// Return slice of used portion
let result : FixedArray[Int] = FixedArray::make(cli, 0)
for i in 0.. Int {
let mut l = 0
for i in 0..