@gmod/cram 3.0.6 → 3.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/dist/cram-bundle.js +1 -1
  2. package/dist/cramFile/codecs/byteArrayStop.d.ts +2 -2
  3. package/dist/cramFile/file.js +8 -10
  4. package/dist/cramFile/file.js.map +1 -1
  5. package/dist/cramFile/util.js.map +1 -1
  6. package/dist/htscodecs/arith_gen.d.ts +26 -0
  7. package/dist/htscodecs/arith_gen.js +558 -0
  8. package/dist/htscodecs/arith_gen.js.map +1 -0
  9. package/dist/htscodecs/arith_sh.d.ts +16 -0
  10. package/dist/htscodecs/arith_sh.js +128 -0
  11. package/dist/htscodecs/arith_sh.js.map +1 -0
  12. package/dist/htscodecs/byte_model.d.ts +11 -0
  13. package/dist/htscodecs/byte_model.js +113 -0
  14. package/dist/htscodecs/byte_model.js.map +1 -0
  15. package/dist/htscodecs/fqzcomp.d.ts +2 -0
  16. package/dist/htscodecs/fqzcomp.js +744 -0
  17. package/dist/htscodecs/fqzcomp.js.map +1 -0
  18. package/dist/htscodecs/index.d.ts +5 -0
  19. package/dist/htscodecs/index.js +70 -0
  20. package/dist/htscodecs/index.js.map +1 -0
  21. package/dist/htscodecs/iostream.d.ts +26 -0
  22. package/dist/htscodecs/iostream.js +242 -0
  23. package/dist/htscodecs/iostream.js.map +1 -0
  24. package/dist/htscodecs/main_arith_gen.d.ts +1 -0
  25. package/dist/htscodecs/main_arith_gen.js +86 -0
  26. package/dist/htscodecs/main_arith_gen.js.map +1 -0
  27. package/dist/htscodecs/main_fqzcomp.d.ts +1 -0
  28. package/dist/htscodecs/main_fqzcomp.js +112 -0
  29. package/dist/htscodecs/main_fqzcomp.js.map +1 -0
  30. package/dist/htscodecs/main_rans.d.ts +1 -0
  31. package/dist/htscodecs/main_rans.js +83 -0
  32. package/dist/htscodecs/main_rans.js.map +1 -0
  33. package/dist/htscodecs/main_rans4x16.d.ts +1 -0
  34. package/dist/htscodecs/main_rans4x16.js +82 -0
  35. package/dist/htscodecs/main_rans4x16.js.map +1 -0
  36. package/dist/htscodecs/main_tok3.d.ts +1 -0
  37. package/dist/htscodecs/main_tok3.js +84 -0
  38. package/dist/htscodecs/main_tok3.js.map +1 -0
  39. package/dist/htscodecs/rans.d.ts +2 -0
  40. package/dist/htscodecs/rans.js +480 -0
  41. package/dist/htscodecs/rans.js.map +1 -0
  42. package/dist/htscodecs/rans4x16.d.ts +2 -0
  43. package/dist/htscodecs/rans4x16.js +896 -0
  44. package/dist/htscodecs/rans4x16.js.map +1 -0
  45. package/dist/htscodecs/tok3.d.ts +2 -0
  46. package/dist/htscodecs/tok3.js +347 -0
  47. package/dist/htscodecs/tok3.js.map +1 -0
  48. package/esm/cramFile/codecs/byteArrayStop.d.ts +2 -2
  49. package/esm/cramFile/file.js +8 -10
  50. package/esm/cramFile/file.js.map +1 -1
  51. package/esm/cramFile/util.js.map +1 -1
  52. package/esm/htscodecs/arith_gen.d.ts +26 -0
  53. package/esm/htscodecs/arith_gen.js +558 -0
  54. package/esm/htscodecs/arith_gen.js.map +1 -0
  55. package/esm/htscodecs/arith_sh.d.ts +16 -0
  56. package/esm/htscodecs/arith_sh.js +128 -0
  57. package/esm/htscodecs/arith_sh.js.map +1 -0
  58. package/esm/htscodecs/byte_model.d.ts +11 -0
  59. package/esm/htscodecs/byte_model.js +113 -0
  60. package/esm/htscodecs/byte_model.js.map +1 -0
  61. package/esm/htscodecs/fqzcomp.d.ts +2 -0
  62. package/esm/htscodecs/fqzcomp.js +744 -0
  63. package/esm/htscodecs/fqzcomp.js.map +1 -0
  64. package/esm/htscodecs/index.d.ts +5 -0
  65. package/esm/htscodecs/index.js +70 -0
  66. package/esm/htscodecs/index.js.map +1 -0
  67. package/esm/htscodecs/iostream.d.ts +26 -0
  68. package/esm/htscodecs/iostream.js +242 -0
  69. package/esm/htscodecs/iostream.js.map +1 -0
  70. package/esm/htscodecs/main_arith_gen.d.ts +1 -0
  71. package/esm/htscodecs/main_arith_gen.js +86 -0
  72. package/esm/htscodecs/main_arith_gen.js.map +1 -0
  73. package/esm/htscodecs/main_fqzcomp.d.ts +1 -0
  74. package/esm/htscodecs/main_fqzcomp.js +112 -0
  75. package/esm/htscodecs/main_fqzcomp.js.map +1 -0
  76. package/esm/htscodecs/main_rans.d.ts +1 -0
  77. package/esm/htscodecs/main_rans.js +83 -0
  78. package/esm/htscodecs/main_rans.js.map +1 -0
  79. package/esm/htscodecs/main_rans4x16.d.ts +1 -0
  80. package/esm/htscodecs/main_rans4x16.js +82 -0
  81. package/esm/htscodecs/main_rans4x16.js.map +1 -0
  82. package/esm/htscodecs/main_tok3.d.ts +1 -0
  83. package/esm/htscodecs/main_tok3.js +84 -0
  84. package/esm/htscodecs/main_tok3.js.map +1 -0
  85. package/esm/htscodecs/rans.d.ts +2 -0
  86. package/esm/htscodecs/rans.js +480 -0
  87. package/esm/htscodecs/rans.js.map +1 -0
  88. package/esm/htscodecs/rans4x16.d.ts +2 -0
  89. package/esm/htscodecs/rans4x16.js +896 -0
  90. package/esm/htscodecs/rans4x16.js.map +1 -0
  91. package/esm/htscodecs/tok3.d.ts +2 -0
  92. package/esm/htscodecs/tok3.js +347 -0
  93. package/esm/htscodecs/tok3.js.map +1 -0
  94. package/package.json +1 -2
  95. package/src/cramFile/file.ts +8 -10
  96. package/src/cramFile/util.ts +0 -1
  97. package/src/htscodecs/Makefile +142 -0
  98. package/src/htscodecs/README.md +64 -0
  99. package/src/htscodecs/arith_gen.js +607 -0
  100. package/src/htscodecs/arith_sh.js +138 -0
  101. package/src/htscodecs/byte_model.js +126 -0
  102. package/src/htscodecs/fqzcomp.js +834 -0
  103. package/src/htscodecs/index.js +79 -0
  104. package/src/htscodecs/iostream.js +256 -0
  105. package/src/htscodecs/main_arith_gen.js +96 -0
  106. package/src/htscodecs/main_fqzcomp.js +113 -0
  107. package/src/htscodecs/main_rans.js +88 -0
  108. package/src/htscodecs/main_rans4x16.js +87 -0
  109. package/src/htscodecs/main_tok3.js +86 -0
  110. package/src/htscodecs/rans.js +545 -0
  111. package/src/htscodecs/rans4x16.js +1003 -0
  112. package/src/htscodecs/tok3.js +396 -0
  113. package/src/typings/htscodecs.d.ts +0 -6
@@ -0,0 +1,834 @@
1
+ /*
2
+ * Copyright (c) 2019 Genome Research Ltd.
3
+ * Author(s): James Bonfield
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are met:
7
+ *
8
+ * 1. Redistributions of source code must retain the above copyright notice,
9
+ * this list of conditions and the following disclaimer.
10
+ *
11
+ * 2. Redistributions in binary form must reproduce the above
12
+ * copyright notice, this list of conditions and the following
13
+ * disclaimer in the documentation and/or other materials provided
14
+ * with the distribution.
15
+ *
16
+ * 3. Neither the names Genome Research Ltd and Wellcome Trust Sanger
17
+ * Institute nor the names of its contributors may be used to endorse
18
+ * or promote products derived from this software without specific
19
+ * prior written permission.
20
+ *
21
+ * THIS SOFTWARE IS PROVIDED BY GENOME RESEARCH LTD AND CONTRIBUTORS "AS
22
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENOME RESEARCH
25
+ * LTD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
+ */
33
+
34
+ const IOStream = require('./iostream')
35
+ const ByteModel = require('./byte_model')
36
+ const RangeCoder = require('./arith_sh')
37
+
38
+ //----------------------------------------------------------------------
39
+ // Main arithmetic entry function: decodes a compressed src and
40
+ // returns the uncompressed buffer.
41
+
42
+ function read_array(src, tab, size) {
43
+ var j = 0 // array value
44
+ var z = 0 // array index: tab[j]
45
+ var last = -1
46
+
47
+ // Remove first level of run-length encoding
48
+ var R = new Array(1024) // runs
49
+ while (z < size) {
50
+ var run = src.ReadByte()
51
+ R[j++] = run
52
+ z += run
53
+
54
+ if (run == last) {
55
+ var copy = src.ReadByte()
56
+ z += run * copy
57
+ while (copy--) R[j++] = run
58
+ }
59
+ last = run
60
+ }
61
+
62
+ // Now expand runs in R to tab, noting 255 is max run
63
+ var i = 0
64
+ j = 0
65
+ z = 0
66
+ while (z < size) {
67
+ var run_len = 0
68
+ do {
69
+ var part = R[j++]
70
+ run_len += part
71
+ } while (part == 255)
72
+
73
+ while (run_len--) tab[z++] = i
74
+ i++
75
+ }
76
+ }
77
+
78
+ const QMAX = 256
79
+
80
+ const FLAG_DEDUP = 2
81
+ const FLAG_FLEN = 4
82
+ const FLAG_SEL = 8 // whether selector is used in context
83
+ const FLAG_QMAP = 16
84
+ const FLAG_PTAB = 32
85
+ const FLAG_DTAB = 64
86
+ const FLAG_QTAB = 128
87
+
88
+ const GFLAG_MULTI_PARAM = 1
89
+ const GFLAG_HAVE_STAB = 2
90
+ const GFLAG_DO_REV = 4
91
+
92
+ // Compute a new context from our current state and qual q
93
+ function fqz_update_ctx(params, state, q) {
94
+ var last = params.context
95
+ state.qctx = (state.qctx << params.qshift) + params.qtab[q] // >>> 0
96
+ last += (state.qctx & ((1 << params.qbits) - 1)) << params.qloc // >>> 0
97
+
98
+ if (params.do_pos) last += params.ptab[Math.min(state.p, 1023)] << params.ploc
99
+
100
+ if (params.do_delta) {
101
+ last += params.dtab[Math.min(state.delta, 255)] << params.dloc
102
+ // Is it better to use q here or qtab[q]?
103
+ // If qtab[q] we can map eg [a-z0-9A-Z]->0 ,->1 and have
104
+ // delta being a token number count into comma separated lists?
105
+ state.delta += state.prevq != q ? 1 : 0
106
+ state.prevq = q
107
+ }
108
+
109
+ if (params.do_sel) last += state.s << params.sloc
110
+
111
+ state.p--
112
+
113
+ return last & 0xffff
114
+ }
115
+
116
+ function decode_fqz_single_param(src) {
117
+ var p = {} // params
118
+
119
+ // Load FQZ parameters
120
+ p.context = src.ReadUint16()
121
+ p.pflags = src.ReadByte()
122
+
123
+ p.do_dedup = p.pflags & FLAG_DEDUP
124
+ p.fixed_len = p.pflags & FLAG_FLEN
125
+ p.do_sel = p.pflags & FLAG_SEL
126
+ p.do_qmap = p.pflags & FLAG_QMAP
127
+ p.do_pos = p.pflags & FLAG_PTAB
128
+ p.do_delta = p.pflags & FLAG_DTAB
129
+ p.do_qtab = p.pflags & FLAG_QTAB
130
+
131
+ p.max_sym = src.ReadByte()
132
+
133
+ var x = src.ReadByte()
134
+ p.qbits = x >> 4
135
+ p.qshift = x & 15
136
+ x = src.ReadByte()
137
+ p.qloc = x >> 4
138
+ p.sloc = x & 15
139
+ x = src.ReadByte()
140
+ p.ploc = x >> 4
141
+ p.dloc = x & 15
142
+
143
+ // Qual map, eg to "unbin" Illumina qualities
144
+ p.qmap = new Array(256)
145
+ if (p.pflags & FLAG_QMAP) {
146
+ for (var i = 0; i < p.max_sym; i++) p.qmap[i] = src.ReadByte()
147
+ } else {
148
+ // Useful optimisation to speed up main loop
149
+ for (var i = 0; i < 256; i++) p.qmap[i] = i // NOP
150
+ }
151
+
152
+ // Read tables
153
+ p.qtab = new Array(1024)
154
+ if (p.qbits > 0 && p.pflags & FLAG_QTAB) {
155
+ read_array(src, p.qtab, 256)
156
+ } else {
157
+ // Useful optimisation to speed up main loop
158
+ for (var i = 0; i < 256; i++) p.qtab[i] = i // NOP
159
+ }
160
+
161
+ p.ptab = new Array(1024)
162
+ if (p.pflags & FLAG_PTAB) read_array(src, p.ptab, 1024)
163
+
164
+ p.dtab = new Array(256)
165
+ if (p.pflags & FLAG_DTAB) read_array(src, p.dtab, 256)
166
+
167
+ return p
168
+ }
169
+
170
+ function decode_fqz_params(src) {
171
+ var gparams = {
172
+ max_sym: 0,
173
+ }
174
+
175
+ // Check fqz format version
176
+ var vers = src.ReadByte()
177
+ if (vers != 5) {
178
+ console.error('Invalid FQZComp version number')
179
+ return
180
+ }
181
+
182
+ var gflags = src.ReadByte()
183
+ var nparam = gflags & GFLAG_MULTI_PARAM ? src.ReadByte() : 1
184
+ var max_sel = gflags.nparam > 1 ? gflags.nparam - 1 : 0 // Note max_sel, not num_sel
185
+
186
+ var stab = new Array(256)
187
+ if (gflags & GFLAG_HAVE_STAB) {
188
+ max_sel = src.ReadByte()
189
+ read_array(src, stab, 256)
190
+ } else {
191
+ for (var i = 0; i < nparam; i++) stab[i] = i
192
+ for (; i < 256; i++) stab[i] = nparam - 1
193
+ }
194
+ gparams.do_rev = gflags & GFLAG_DO_REV
195
+ gparams.stab = stab
196
+ gparams.max_sel = max_sel
197
+
198
+ gparams.params = new Array(gparams.nparam)
199
+ for (var p = 0; p < nparam; p++) {
200
+ gparams.params[p] = decode_fqz_single_param(src)
201
+ if (gparams.max_sym < gparams.params[p].max_sym)
202
+ gparams.max_sym = gparams.params[p].max_sym
203
+ }
204
+
205
+ return gparams
206
+ }
207
+
208
+ function fqz_create_models(gparams) {
209
+ var model = {}
210
+
211
+ model.qual = new Array(1 << 16)
212
+ for (var i = 0; i < 1 << 16; i++)
213
+ model.qual[i] = new ByteModel(gparams.max_sym + 1) // +1 as max value not num. values
214
+
215
+ model.len = new Array(4)
216
+ for (var i = 0; i < 4; i++) model.len[i] = new ByteModel(256)
217
+
218
+ model.rev = new ByteModel(2)
219
+ model.dup = new ByteModel(2)
220
+
221
+ if (gparams.max_sel > 0) model.sel = new ByteModel(gparams.max_sel + 1) // +1 as max value not num. values
222
+
223
+ return model
224
+ }
225
+
226
+ // Initialise a new record, updating state.
227
+ // Returns 1 if dup, otherwise 0
228
+ function decode_fqz_new_record(src, rc, gparams, model, state, rev) {
229
+ // Parameter selector
230
+ if (gparams.max_sel > 0) {
231
+ state.s = model.sel.ModelDecode(src, rc)
232
+ } else {
233
+ state.s = 0
234
+ }
235
+ state.x = gparams.stab[state.s]
236
+
237
+ var params = gparams.params[state.x]
238
+
239
+ // Reset contexts at the start of each new record
240
+ if (params.fixed_len >= 0) {
241
+ // Not fixed or fixed but first record
242
+ var len = model.len[0].ModelDecode(src, rc)
243
+ len |= model.len[1].ModelDecode(src, rc) << 8
244
+ len |= model.len[2].ModelDecode(src, rc) << 16
245
+ len |= model.len[3].ModelDecode(src, rc) << 24
246
+ if (params.fixed_len > 0) params.fixed_len = -len
247
+ } else {
248
+ len = -params.fixed_len
249
+ }
250
+ state.len = len
251
+
252
+ if (gparams.do_rev) rev[state.rec] = model.rev.ModelDecode(src, rc)
253
+
254
+ state.is_dup = 0
255
+ if (params.pflags & FLAG_DEDUP) {
256
+ if (model.dup.ModelDecode(src, rc)) state.is_dup = 1
257
+ }
258
+
259
+ state.p = len // number of remaining bytes in this record
260
+ state.delta = 0
261
+ state.qctx = 0
262
+ state.prevq = 0
263
+ state.rec++
264
+ }
265
+
266
+ function decode_fqz(src, q_lens) {
267
+ // Decode parameter block
268
+ var n_out = src.ReadUint7()
269
+ var gparams = decode_fqz_params(src)
270
+ if (!gparams) return
271
+ var params = gparams.params
272
+ var rev = new Array(q_lens.length)
273
+
274
+ // Create initial models
275
+ var model = fqz_create_models(gparams)
276
+
277
+ // Create our entropy encoder and output buffers
278
+ var rc = new RangeCoder(src)
279
+ rc.RangeStartDecode(src)
280
+ var output = new Buffer.allocUnsafe(n_out)
281
+
282
+ // Internal FQZ state
283
+ var state = {
284
+ qctx: 0, // Qual-only sub-context
285
+ prevq: 0, // Previous quality value
286
+ delta: 0, // Running delta (q vs prevq)
287
+ p: 0, // Number of bases left in current record
288
+ s: 0, // Current parameter selector value (0 if unused)
289
+ x: 0, // "stab" tabulated copy of s
290
+ len: 0, // Length of current string
291
+ is_dup: 0, // This string is a duplicate of last
292
+ rec: 0, // Record number
293
+ }
294
+
295
+ // The main decode loop itself
296
+ var i = 0 // position in output buffer
297
+ while (i < n_out) {
298
+ if (state.p == 0) {
299
+ decode_fqz_new_record(src, rc, gparams, model, state, rev)
300
+ if (state.is_dup > 0) {
301
+ if (model.dup.ModelDecode(src, rc)) {
302
+ // Duplicate of last line
303
+ for (var x = 0; x < len; x++)
304
+ output[i + x] = output[i + x - state.len]
305
+ i += state.len
306
+ state.p = 0
307
+ continue
308
+ }
309
+ }
310
+ q_lens.push(state.len)
311
+
312
+ var params = gparams.params[state.x]
313
+ var last = params.context
314
+ }
315
+
316
+ // Decode the current quality (possibly mapped via qmap)
317
+ var Q = model.qual[last].ModelDecode(src, rc)
318
+
319
+ //if (params.do_qmap)
320
+ // output[i++] = params.qmap[Q];
321
+ //else
322
+ // output[i++] = Q
323
+ output[i++] = params.qmap[Q] // optimised version of above
324
+ last = fqz_update_ctx(params, state, Q)
325
+ }
326
+
327
+ if (gparams.do_rev) reverse_qualities(output, n_out, rev, q_lens)
328
+
329
+ return output
330
+ }
331
+
332
+ function reverse_qualities(qual, qual_len, rev, len) {
333
+ var rec = 0
334
+ var i = 0
335
+ while (i < qual_len) {
336
+ if (rev[rec]) {
337
+ var j = 0
338
+ var k = len[rec] - 1
339
+ while (j < k) {
340
+ var tmp = qual[i + j]
341
+ qual[i + j] = qual[i + k]
342
+ qual[i + k] = tmp
343
+ j++
344
+ k--
345
+ }
346
+ }
347
+
348
+ i += len[rec++]
349
+ }
350
+ }
351
+
352
+ function decode(src, q_lens) {
353
+ var stream = new IOStream(src)
354
+
355
+ //var n_out = stream.ReadUint32(); stream.ReadUint32(); // move to main
356
+
357
+ return decode_fqz(stream, q_lens)
358
+ }
359
+
360
+ //----------------------------------------------------------------------
361
+ // FQZComp encoder.
362
+
363
+ function pick_fqz_params(src, q_lens, q_dirs, qhist) {
364
+ // Find cardinality of q_dirs
365
+ var qd_last = q_dirs[0]
366
+ for (var i = 0; i < q_dirs.length; i++) if (q_dirs[i] != qd_last) break
367
+ var qd_fixed = i == q_dirs.length ? 1 : 0
368
+
369
+ // Scan input to find number of symbols and max symbol
370
+ var nsym = 0
371
+ var max_sym = 0
372
+
373
+ // selector == 0: Assume one single input dataset
374
+ for (var i = 0; i < 256; i++) qhist[0][i] = 0
375
+
376
+ var rec = 0
377
+ var len = 0
378
+ for (var i = 0; i < src.length; i++) {
379
+ if (len == 0) {
380
+ len = q_lens[rec < q_lens.length - 1 ? rec++ : rec]
381
+ }
382
+ qhist[0][src[i]]++
383
+ len--
384
+ }
385
+ for (var i = 0; i < 256; i++) {
386
+ if (!qhist[0][i]) continue
387
+ if (max_sym < i) max_sym = i
388
+ nsym++
389
+ }
390
+
391
+ var qshift = 5
392
+ var do_qmap = 0
393
+ // Reduced symbol frequencies implies lower qshift and
394
+ // a lookup table to go from qual to Q
395
+ if (nsym <= 16) {
396
+ do_qmap = 1 // based on qhist
397
+ if (nsym <= 2) qshift = 1
398
+ else if (nsym <= 4) qshift = 2
399
+ else if (nsym <= 8) qshift = 3
400
+ else qshift = 4
401
+ }
402
+
403
+ // // Two params and a 1-bit selector.
404
+ // // This is 1% overhead vs two data sets compressed independently.
405
+ // // It's 6.9% smaller than compressing both together with 1 param.
406
+ // if (0) return [{
407
+ // // q4
408
+ // qbits: 8,
409
+ // qshift: 2,
410
+ // qloc: 7,
411
+ //
412
+ // pbits: 7,
413
+ // pshift: 1,
414
+ // ploc: 0,
415
+ //
416
+ // dbits: 0,
417
+ // dshift: 0,
418
+ // dloc: 0,
419
+ //
420
+ // sbits: 0,
421
+ // sloc: 0,
422
+ //
423
+ // //sbits: 2,
424
+ // //do_stab: 1,
425
+ // sbits: 1,
426
+ // do_stab: 0,
427
+ // context: (0<<15),
428
+ //
429
+ // max_sym: 36,
430
+ // nsym: 4,
431
+ //
432
+ // do_qmap: 1,
433
+ // do_dedup: 0,
434
+ // fixed_len: 1,
435
+ // do_sel: 0,
436
+ // do_rev: 0,
437
+ // do_pos: 1,
438
+ // do_delta: 0,
439
+ // do_qtab: 0
440
+ // }, {
441
+ // //q40
442
+ // qbits: 9,
443
+ // qshift: 5,
444
+ // qloc: 7,
445
+ //
446
+ // pbits: 7,
447
+ // pshift: 0,
448
+ // ploc: 0,
449
+ //
450
+ // dbits: 0,
451
+ // dshift: 0,
452
+ // dloc: 0,
453
+ //
454
+ // sbits: 0,
455
+ // sloc: 0,
456
+ //
457
+ // //sbits: 2,
458
+ // //do_stab: 1,
459
+ // sbits: 1,
460
+ // do_stab: 0,
461
+ // context: (1<<15),
462
+ //
463
+ // max_sym: 44,
464
+ // nsym: 45,
465
+ //
466
+ // do_qmap: 0,
467
+ // do_dedup: 0,
468
+ // fixed_len: 1,
469
+ // do_sel: 0,
470
+ // do_rev: 0,
471
+ // do_pos: 1,
472
+ // do_delta: 0,
473
+ // do_qtab: 0
474
+ // }]
475
+
476
+ return [
477
+ {
478
+ qbits: 8 + (qshift > 4),
479
+ qshift: qshift,
480
+ qloc: 7,
481
+
482
+ pbits: 7,
483
+ pshift: q_lens[0] > 128 ? 1 : 0,
484
+ ploc: 0,
485
+
486
+ dbits: qshift > 4 ? 0 : 1,
487
+ dshift: 3,
488
+ dloc: 15,
489
+
490
+ // NB: Also useful as a way of embedding sel and doing sel
491
+ // specific contexts. Identical bar context. Eg 0<<15 or 1<<15.
492
+ sbits: 0,
493
+ sloc: 15,
494
+ do_stab: 0,
495
+ context: 0 << 15,
496
+
497
+ max_sym: max_sym,
498
+ nsym: nsym,
499
+
500
+ do_qmap: do_qmap,
501
+ do_dedup: 0,
502
+ fixed_len: q_lens.length == 1 ? 1 : 0,
503
+ do_sel: 0,
504
+ do_rev: 0,
505
+ do_pos: 1,
506
+ do_delta: qshift <= 4 ? 1 : 0,
507
+ do_qtab: 0,
508
+
509
+ // Override above with some attempt at using selectors
510
+ // when the q_dirs are specific and non-fixed.
511
+ qbits: 8 + (qshift > 4) - (qd_fixed == 0),
512
+ sbits: 1,
513
+ sloc: 15 - (qshift <= 4), // read1 vs read2
514
+ do_stab: 1,
515
+ do_sel: 1,
516
+
517
+ // // q4+dir: 7245769 with, 7353962 without. 1.5% saving
518
+ // qbits: 6,
519
+ // dbits: 2,
520
+ // dshift: 2,
521
+ // dloc: 13,
522
+ // sbits: 1,
523
+ // sloc: 15,
524
+ // do_stab: 1,
525
+ // do_sel: 1,
526
+
527
+ // with 20 bits of context, q40 = 31741545
528
+ // qbits 10, dbits 2, pbits 7, sbits 1
529
+ },
530
+ ]
531
+ }
532
+
533
+ function store_array(out, tab, size) {
534
+ var i = 0 // index into tab
535
+ var j = 0 // current value in tab[i]
536
+
537
+ var tmp1 = new Array(size * 2)
538
+ var sz1 = 0
539
+
540
+ // First level of RLE. Replace all runs of 'j' values
541
+ // with run-lengths, including zeros for missing values.
542
+ // Eg 0 1 2 2 2 3 3 3 4 4 4 5 5 5 5 7 7
543
+ // to 1 1 3 3 3 4 0 2
544
+ while (i < size) {
545
+ // Length of j^{th} element
546
+ var i_start = i
547
+ while (i < size && tab[i] == j) i++
548
+ var run_len = i - i_start
549
+
550
+ // Encode run length to tmp array
551
+ do {
552
+ var r = Math.min(255, run_len)
553
+ tmp1[sz1++] = r
554
+ run_len -= r
555
+ } while (r == 255)
556
+ j++
557
+ }
558
+
559
+ // Second round of RLE on our tmp array, using a different
560
+ // RLE algorithm.
561
+ // Eg 1 1 3 3 3 4 0 2
562
+ // to 1 1 +0 3 3 +1 4 0 2
563
+ var last = -1
564
+ var tmp2 = new Array(size * 2)
565
+ var sz2 = 0
566
+ i = 0 // index into tmp1]
567
+ // k is used size of tmp1[]
568
+ while (i < sz1) {
569
+ var curr = tmp1[i++]
570
+ tmp2[sz2++] = curr
571
+ if (curr == last) {
572
+ var i_start = i
573
+ while (i < sz1 && tmp1[i] == last && i - i_start < 255) i++
574
+ tmp2[sz2++] = i - i_start
575
+ } else {
576
+ last = curr
577
+ }
578
+ }
579
+
580
+ // Append 2nd RLE, tmp2, to out.
581
+ out.WriteData(tmp2, sz2)
582
+ }
583
+
584
+ // q_lens is an array of quality lengths per record.
585
+ // (If they're all the same, just set one value.)
586
+ function encode_fqz_params(out, params, qhist, qtab, ptab, dtab, stab) {
587
+ var dsqr = [
588
+ 0, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4,
589
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7,
590
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
591
+ ]
592
+
593
+ for (var i = 0; i < params.length; i++) stab[i] = i // 1 parameter set per selector value
594
+ for (; i < 256; i++) stab[i] = params.length - 1
595
+
596
+ // Store global meta-data
597
+ out.WriteByte(5) // FQZ format number
598
+ var gflags =
599
+ (params.length > 1 ? GFLAG_MULTI_PARAM : 0) |
600
+ (params[0].do_stab ? GFLAG_HAVE_STAB : 0)
601
+ out.WriteByte(gflags)
602
+
603
+ if (gflags & GFLAG_MULTI_PARAM) out.WriteByte(params.length) // Number of parameter blocks.
604
+
605
+ if (gflags & GFLAG_HAVE_STAB) {
606
+ var max_sel = 1 << params[0].sbits
607
+ if (max_sel > 0) max_sel--
608
+ out.WriteByte(max_sel)
609
+ store_array(out, stab, 256)
610
+ }
611
+
612
+ // Store per-param meta-data
613
+ for (var p = 0; p < params.length; p++) {
614
+ out.WriteUint16(params[p].context)
615
+ out.WriteByte(
616
+ (params[p].do_qtab ? FLAG_QTAB : 0) | // FLAG
617
+ (params[p].do_delta ? FLAG_DTAB : 0) |
618
+ (params[p].do_pos ? FLAG_PTAB : 0) |
619
+ (params[p].do_qmap ? FLAG_QMAP : 0) |
620
+ (params[p].do_sel ? FLAG_SEL : 0) |
621
+ (params[p].fixed_len ? FLAG_FLEN : 0) |
622
+ (params[p].do_dedup ? FLAG_DEDUP : 0),
623
+ )
624
+ if (params[p].do_qmap) out.WriteByte(params[p].nsym)
625
+ else out.WriteByte(params[p].max_sym)
626
+ out.WriteByte((params[p].qbits << 4) | params[p].qshift)
627
+ out.WriteByte((params[p].qloc << 4) | params[p].sloc)
628
+ out.WriteByte((params[p].ploc << 4) | params[p].dloc)
629
+
630
+ if (params[p].do_qmap) {
631
+ params[p].max_sym = params[p].nsym
632
+ var n = 0
633
+ for (var i = 0; i < 256; i++) {
634
+ if (qhist[p][i]) {
635
+ out.WriteByte(i)
636
+ qhist[p][i] = n++
637
+ }
638
+ }
639
+ // Ensure we have all matched input params
640
+ for (; n < params[p].nsym; n++) out.WriteByte(0)
641
+ } else {
642
+ //params[p].nsym = 255;
643
+ for (var i = 0; i < 256; i++) qhist[p][i] = i // NOP
644
+ }
645
+
646
+ if (params[p].qbits > 0) {
647
+ // // Eg map 0-44 to a smaller range, to improve context usage.
648
+ // // Makes q40 test set go from 33596471 to 33450075 (-0.4%)
649
+ // params[p].do_qtab = 1;
650
+ // for (var j = i = 0; i < params[p].max_sym; i++) {
651
+ // qtab[i]=j;
652
+ // if ((i%3)!=0 | i >= 28) j++
653
+ // console.log("qtab[",i,"]=",qtab[i]);
654
+ // }
655
+ // for (; i < 256; i++)
656
+ // qtab[i] = qtab[params[p].max_sym-1]
657
+
658
+ for (var i = 0; i < 256; i++) qtab[p][i] = i // NOP for now
659
+
660
+ if (params[p].do_qtab) store_array(out, qtab[p], 256)
661
+ }
662
+
663
+ if (params[p].pbits > 0) {
664
+ for (var i = 0; i < 1024; i++)
665
+ ptab[p][i] = Math.min((1 << params[p].pbits) - 1, i >> params[p].pshift)
666
+
667
+ store_array(out, ptab[p], 1024)
668
+ }
669
+
670
+ if (params[p].dbits > 0) {
671
+ for (var i = 0; i < 256; i++)
672
+ if (dsqr[i] > (1 << params[p].dbits) - 1)
673
+ dsqr[i] = (1 << params[p].dbits) - 1
674
+ for (var i = 0; i < 256; i++)
675
+ dtab[p][i] = dsqr[Math.min(dsqr.length - 1, i >> params[p].dshift)]
676
+
677
+ store_array(out, dtab[p], 256)
678
+ }
679
+ }
680
+
681
+ return out
682
+ }
683
+
684
+ function encode_fqz(
685
+ out,
686
+ src,
687
+ q_lens,
688
+ q_dirs,
689
+ params,
690
+ qhist,
691
+ qtab,
692
+ ptab,
693
+ dtab,
694
+ stab,
695
+ ) {
696
+ //console.error("0:",params[0])
697
+ //console.error("1:",params[1])
698
+
699
+ var max_sel = 1 << params[0].sbits
700
+ if (max_sel > 0) max_sel--
701
+ var n_in = src.length
702
+
703
+ // Create the models
704
+ var max_sym = 0
705
+ for (var p = 0; p < params.length; p++)
706
+ if (max_sym < params[p].max_sym) max_sym = params[p].max_sym
707
+
708
+ var model_qual = new Array(1 << 16)
709
+ for (var i = 0; i < 1 << 16; i++) model_qual[i] = new ByteModel(max_sym + 1)
710
+
711
+ var model_len = new Array(4)
712
+ for (var i = 0; i < 4; i++) model_len[i] = new ByteModel(256)
713
+
714
+ var model_rev = new ByteModel(2)
715
+ var model_dup = new ByteModel(2)
716
+ var model_sel = new ByteModel(max_sel + 1)
717
+
718
+ // Note: our JavaScript encoder doesn't have a way for reversing
719
+ // some quality strings, so we ignore do_rev for now.
720
+ var rc = new RangeCoder(src)
721
+
722
+ // The main encoding loop
723
+ var p = 0 // remaining position along current record
724
+ var i = 0 // index in src data
725
+ var rec = 0
726
+
727
+ while (i < n_in) {
728
+ if (p == 0) {
729
+ //var s = 0 // single non-mixed sample
730
+ var s = q_dirs[rec]
731
+ if (params[0].sbits > 0) {
732
+ // FIXME: check All params[].do_stab / sbits must be identical
733
+ //console.log("Ssel", s)
734
+ model_sel.ModelEncode(out, rc, s)
735
+ }
736
+ var x = stab[s]
737
+
738
+ // Reset contexts at the statr of each new record
739
+ var len = q_lens[Math.min(q_lens.length - 1, rec++)]
740
+ if (params[x].fixed_len) {
741
+ if (params[x].fixed_len > 0) {
742
+ // First length
743
+ //console.log("Len", len)
744
+ model_len[0].ModelEncode(out, rc, len & 0xff)
745
+ model_len[1].ModelEncode(out, rc, (len >> 8) & 0xff)
746
+ model_len[2].ModelEncode(out, rc, (len >> 16) & 0xff)
747
+ model_len[3].ModelEncode(out, rc, (len >> 24) & 0xff)
748
+ params[x].fixed_len = -1 // indicate we've stored it once
749
+ }
750
+ } else {
751
+ //console.log("len", len)
752
+ model_len[0].ModelEncode(out, rc, len & 0xff)
753
+ model_len[1].ModelEncode(out, rc, (len >> 8) & 0xff)
754
+ model_len[2].ModelEncode(out, rc, (len >> 16) & 0xff)
755
+ model_len[3].ModelEncode(out, rc, (len >> 24) & 0xff)
756
+ }
757
+
758
+ if (params[x].do_dedup) process.exit(1) // FIXME
759
+
760
+ p = len
761
+ var delta = 0
762
+ //var last = 0
763
+ var last = params[x].context
764
+ var qlast = 0
765
+ var q1 = 0
766
+ }
767
+
768
+ // Encode current quality
769
+ var q = src[i++]
770
+ var Q = qhist[x][q]
771
+ model_qual[last].ModelEncode(out, rc, Q)
772
+ //console.log("Ctx",last,qhist[x][q])
773
+
774
+ // Update contexts for next quality
775
+ qlast = (qlast << params[x].qshift) + qtab[x][Q]
776
+ last = params[x].context
777
+ last += (qlast & ((1 << params[x].qbits) - 1)) << params[x].qloc
778
+
779
+ // 46.6-48.6 billion cycles with ifs + "<< params[x].?loc" shifts
780
+ // 47.3-47.3 billion cycles with ifs
781
+ // 47.1-47.9 billion cycles without ifs
782
+ if (params[x].pbits > 0)
783
+ last += ptab[x][Math.min(p, 1023)] << params[x].ploc
784
+
785
+ if (params[x].dbits > 0) {
786
+ last += dtab[x][Math.min(delta, 255)] << params[x].dloc
787
+ delta += q1 != Q ? 1 : 0
788
+ q1 = Q
789
+ }
790
+
791
+ if (params[x].do_sel) last += s << params[x].sloc
792
+
793
+ last = last & 0xffff
794
+ p--
795
+ }
796
+
797
+ rc.RangeFinishEncode(out)
798
+ return out.buf.slice(0, out.pos)
799
+ }
800
+
801
+ function encode(src, q_lens, q_dirs) {
802
+ var qhist = new Array(2)
803
+ var qtab = new Array(2)
804
+ var ptab = new Array(2)
805
+ var dtab = new Array(2)
806
+ var stab = new Array(256)
807
+
808
+ for (var s = 0; s < 2; s++) {
809
+ qhist[s] = new Array(256)
810
+ qtab[s] = new Array(256)
811
+ ptab[s] = new Array(1024)
812
+ dtab[s] = new Array(256)
813
+ }
814
+
815
+ var out = new IOStream('', 0, src.length * 1.1 + 100) // FIXME: guestimate worst case
816
+
817
+ out.WriteUint7(src.length)
818
+ var params = pick_fqz_params(src, q_lens, q_dirs, qhist)
819
+ var out = encode_fqz_params(out, params, qhist, qtab, ptab, dtab, stab)
820
+ return encode_fqz(
821
+ out,
822
+ src,
823
+ q_lens,
824
+ q_dirs,
825
+ params,
826
+ qhist,
827
+ qtab,
828
+ ptab,
829
+ dtab,
830
+ stab,
831
+ )
832
+ }
833
+
834
+ module.exports = { decode, encode }