minidraco 0.4.0 → 0.5.0

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.
package/dist/three.js CHANGED
@@ -1276,6 +1276,8 @@ var MetadataDecoder = class {
1276
1276
  var ANS_P8_PRECISION = 256;
1277
1277
  var ANS_L_BASE = 4096;
1278
1278
  var ANS_IO_BASE = 256;
1279
+ var COARSE_STREAM_FACTOR = 8;
1280
+ var COARSE_BUCKET_BITS = 8;
1279
1281
  function memGetLe16(buf, offset) {
1280
1282
  return buf[offset] | buf[offset + 1] << 8;
1281
1283
  }
@@ -1353,6 +1355,13 @@ var RAnsDecoder = class {
1353
1355
  lutTable;
1354
1356
  probTable;
1355
1357
  cumProbTable;
1358
+ // Short-stream mode (see ransBuildLookUpTable): no full-precision lut; a
1359
+ // 256-entry bucket table narrows each lookup to a symbol range that a short
1360
+ // cumProb scan finishes. cumProbTable then carries one extra trailing entry
1361
+ // (== ransPrecision) so the scan needs no bounds check.
1362
+ coarse;
1363
+ bucketShift;
1364
+ bucketTable;
1356
1365
  buf;
1357
1366
  bufOffset;
1358
1367
  // First valid byte of this decoder's slice within buf (absolute offsets,
@@ -1367,6 +1376,9 @@ var RAnsDecoder = class {
1367
1376
  this.lutTable = null;
1368
1377
  this.probTable = null;
1369
1378
  this.cumProbTable = null;
1379
+ this.coarse = false;
1380
+ this.bucketShift = 0;
1381
+ this.bucketTable = null;
1370
1382
  this.buf = null;
1371
1383
  this.bufOffset = 0;
1372
1384
  this.bufStart = 0;
@@ -1426,6 +1438,10 @@ var RAnsDecoder = class {
1426
1438
  tablePool.push(this.cumProbTable);
1427
1439
  this.cumProbTable = null;
1428
1440
  }
1441
+ if (this.bucketTable !== null) {
1442
+ tablePool.push(this.bucketTable);
1443
+ this.bucketTable = null;
1444
+ }
1429
1445
  return this.state === this.lRansBase;
1430
1446
  }
1431
1447
  ransRead() {
@@ -1439,7 +1455,14 @@ var RAnsDecoder = class {
1439
1455
  }
1440
1456
  const quo = state >>> this.ransPrecisionBits;
1441
1457
  const rem = state & this.ransPrecisionMask;
1442
- const symbol = this.lutTable[rem];
1458
+ let symbol;
1459
+ if (this.coarse) {
1460
+ const cumProbTable = this.cumProbTable;
1461
+ symbol = this.bucketTable[rem >> this.bucketShift];
1462
+ while (cumProbTable[symbol + 1] <= rem) symbol++;
1463
+ } else {
1464
+ symbol = this.lutTable[rem];
1465
+ }
1443
1466
  this.state = quo * this.probTable[symbol] + rem - this.cumProbTable[symbol];
1444
1467
  this.bufOffset = bufOffset;
1445
1468
  return symbol;
@@ -1451,6 +1474,10 @@ var RAnsDecoder = class {
1451
1474
  // once here so each loop body stays monomorphic on its concrete type. The
1452
1475
  // three bodies are intentionally identical copies.
1453
1476
  decodeSymbols(out, count) {
1477
+ if (this.coarse) {
1478
+ this._decodeSymbolsCoarse(out, count);
1479
+ return;
1480
+ }
1454
1481
  const lutTable = this.lutTable;
1455
1482
  if (lutTable instanceof Uint8Array) {
1456
1483
  this._decodeSymbolsU8(out, count, lutTable);
@@ -1504,6 +1531,33 @@ var RAnsDecoder = class {
1504
1531
  this.state = state;
1505
1532
  this.bufOffset = bufOffset;
1506
1533
  }
1534
+ // Short-stream loop: bucket table + cumProb scan instead of the full lut.
1535
+ // Same state arithmetic as the lut loops, so the output is identical.
1536
+ _decodeSymbolsCoarse(out, count) {
1537
+ const buf = this.buf;
1538
+ const lRansBase = this.lRansBase;
1539
+ const ransPrecisionBits = this.ransPrecisionBits;
1540
+ const ransPrecisionMask = this.ransPrecisionMask;
1541
+ const probTable = this.probTable;
1542
+ const cumProbTable = this.cumProbTable;
1543
+ const bucketTable = this.bucketTable;
1544
+ const bucketShift = this.bucketShift;
1545
+ let state = this.state;
1546
+ let bufOffset = this.bufOffset;
1547
+ const bufStart = this.bufStart;
1548
+ for (let i = 0; i < count; ++i) {
1549
+ while (state < lRansBase && bufOffset > bufStart) {
1550
+ state = state << 8 | buf[--bufOffset];
1551
+ }
1552
+ const rem = state & ransPrecisionMask;
1553
+ let symbol = bucketTable[rem >> bucketShift];
1554
+ while (cumProbTable[symbol + 1] <= rem) symbol++;
1555
+ out[i] = symbol;
1556
+ state = (state >>> ransPrecisionBits) * probTable[symbol] + rem - cumProbTable[symbol];
1557
+ }
1558
+ this.state = state;
1559
+ this.bufOffset = bufOffset;
1560
+ }
1507
1561
  _decodeSymbolsU32(out, count, lutTable) {
1508
1562
  const buf = this.buf;
1509
1563
  const lRansBase = this.lRansBase;
@@ -1526,23 +1580,62 @@ var RAnsDecoder = class {
1526
1580
  this.state = state;
1527
1581
  this.bufOffset = bufOffset;
1528
1582
  }
1529
- // Builds the ransPrecision-entry lookup table. Returns false on bad input data.
1530
- ransBuildLookUpTable(tokenProbs, numSymbols) {
1531
- const LutArray = numSymbols <= 256 ? Uint8Array : numSymbols <= 65536 ? Uint16Array : Uint32Array;
1532
- const lutTable = acquirePooled(LutArray, this.ransPrecision);
1583
+ // Builds the decoding tables. Returns false on bad input data.
1584
+ //
1585
+ // expectedCount is how many symbols the caller will decode from this stream.
1586
+ // The full lut has ransPrecision (>= 4096) entries, and a primitive-heavy
1587
+ // file builds thousands of them to decode a few dozen symbols each -- on such
1588
+ // files the table builds cost more than the decodes. Short streams therefore
1589
+ // get a coarse 256-entry bucket table (symbol at the start of each
1590
+ // precision/256-wide bucket) and finish each lookup with a scan of the
1591
+ // cumulative probabilities; long streams keep the exact lut, whose per-symbol
1592
+ // cost is lower.
1593
+ ransBuildLookUpTable(tokenProbs, numSymbols, expectedCount = 2147483647) {
1594
+ const ransPrecision = this.ransPrecision;
1595
+ const coarse = numSymbols <= 65535 && expectedCount * COARSE_STREAM_FACTOR < ransPrecision;
1596
+ this.coarse = coarse;
1533
1597
  const probTable = acquirePooled(Uint32Array, numSymbols);
1534
- const cumProbTable = acquirePooled(Uint32Array, numSymbols);
1535
- this.lutTable = lutTable;
1598
+ const cumProbTable = acquirePooled(Uint32Array, numSymbols + 1);
1536
1599
  this.probTable = probTable;
1537
1600
  this.cumProbTable = cumProbTable;
1538
1601
  let cumProb = 0;
1602
+ if (coarse) {
1603
+ this.lutTable = null;
1604
+ for (let i = 0; i < numSymbols; ++i) {
1605
+ const prob = tokenProbs[i];
1606
+ probTable[i] = prob;
1607
+ cumProbTable[i] = cumProb;
1608
+ cumProb += prob;
1609
+ if (cumProb > ransPrecision) {
1610
+ return false;
1611
+ }
1612
+ }
1613
+ if (cumProb !== ransPrecision) {
1614
+ return false;
1615
+ }
1616
+ cumProbTable[numSymbols] = ransPrecision;
1617
+ const bucketShift = this.ransPrecisionBits - COARSE_BUCKET_BITS;
1618
+ const bucketTable = acquirePooled(Uint16Array, 1 << COARSE_BUCKET_BITS);
1619
+ this.bucketShift = bucketShift;
1620
+ this.bucketTable = bucketTable;
1621
+ let symbol = 0;
1622
+ for (let b = 0; b < 1 << COARSE_BUCKET_BITS; ++b) {
1623
+ const rem = b << bucketShift;
1624
+ while (cumProbTable[symbol + 1] <= rem) symbol++;
1625
+ bucketTable[b] = symbol;
1626
+ }
1627
+ return true;
1628
+ }
1629
+ const LutArray = numSymbols <= 256 ? Uint8Array : numSymbols <= 65536 ? Uint16Array : Uint32Array;
1630
+ const lutTable = acquirePooled(LutArray, ransPrecision);
1631
+ this.lutTable = lutTable;
1539
1632
  let actProb = 0;
1540
1633
  for (let i = 0; i < numSymbols; ++i) {
1541
1634
  const prob = tokenProbs[i];
1542
1635
  probTable[i] = prob;
1543
1636
  cumProbTable[i] = cumProb;
1544
1637
  cumProb += prob;
1545
- if (cumProb > this.ransPrecision) {
1638
+ if (cumProb > ransPrecision) {
1546
1639
  return false;
1547
1640
  }
1548
1641
  if (prob < 32) {
@@ -1554,9 +1647,10 @@ var RAnsDecoder = class {
1554
1647
  }
1555
1648
  actProb = cumProb;
1556
1649
  }
1557
- if (cumProb !== this.ransPrecision) {
1650
+ if (cumProb !== ransPrecision) {
1558
1651
  return false;
1559
1652
  }
1653
+ cumProbTable[numSymbols] = ransPrecision;
1560
1654
  return true;
1561
1655
  }
1562
1656
  };
@@ -2005,14 +2099,18 @@ var PointCloudDecoder = class _PointCloudDecoder {
2005
2099
  for (let i2 = 0; i2 < decoders.length; i2++) {
2006
2100
  decoders[i2].collectPendingSymbolStreams(pending);
2007
2101
  }
2102
+ const paired = pending.filter((stream) => !stream.ans.coarse);
2008
2103
  let i = 0;
2009
- for (; i + 1 < pending.length; i += 2) {
2010
- const a = pending[i];
2011
- const b = pending[i + 1];
2104
+ for (; i + 1 < paired.length; i += 2) {
2105
+ const a = paired[i];
2106
+ const b = paired[i + 1];
2012
2107
  ransDecodeSymbolsPair(a.ans, a.out, a.count, b.ans, b.out, b.count);
2013
2108
  }
2014
- if (i < pending.length) {
2015
- pending[i].ans.decodeSymbols(pending[i].out, pending[i].count);
2109
+ if (i < paired.length) {
2110
+ paired[i].ans.decodeSymbols(paired[i].out, paired[i].count);
2111
+ }
2112
+ for (const stream of pending) {
2113
+ if (stream.ans.coarse) stream.ans.decodeSymbols(stream.out, stream.count);
2016
2114
  }
2017
2115
  for (let k = 0; k < decoders.length; k++) {
2018
2116
  if (!decoders[k].decodeAttributesFinish()) {
@@ -2582,8 +2680,10 @@ var RAnsSymbolDecoder = class {
2582
2680
  get numSymbols() {
2583
2681
  return this.numSymbols_;
2584
2682
  }
2585
- // Initialize the decoder and decode the probability table.
2586
- create(buffer) {
2683
+ // Initialize the decoder and decode the probability table. expectedCount is
2684
+ // the number of symbols the caller will decode (lets short streams skip the
2685
+ // full lookup table; see RAnsDecoder.ransBuildLookUpTable).
2686
+ create(buffer, expectedCount = 2147483647) {
2587
2687
  if (buffer.bitstreamVersion === 0) {
2588
2688
  return false;
2589
2689
  }
@@ -2624,7 +2724,7 @@ var RAnsSymbolDecoder = class {
2624
2724
  }
2625
2725
  }
2626
2726
  buffer.advance(pos - startPos);
2627
- if (!this.ans_.ransBuildLookUpTable(this.probabilityTable_, this.numSymbols_)) {
2727
+ if (!this.ans_.ransBuildLookUpTable(this.probabilityTable_, this.numSymbols_, expectedCount)) {
2628
2728
  return false;
2629
2729
  }
2630
2730
  return true;
@@ -2666,7 +2766,7 @@ function decodeSymbols(numValues, numComponents, srcBuffer, outValues) {
2666
2766
  }
2667
2767
  function decodeTaggedSymbols(numValues, numComponents, srcBuffer, outValues) {
2668
2768
  const tagDecoder = new RAnsSymbolDecoder(5);
2669
- if (!tagDecoder.create(srcBuffer)) {
2769
+ if (!tagDecoder.create(srcBuffer, Math.ceil(numValues / numComponents))) {
2670
2770
  return false;
2671
2771
  }
2672
2772
  if (!tagDecoder.startDecoding(srcBuffer)) {
@@ -2731,7 +2831,7 @@ function parseRawSymbolStream(numValues, srcBuffer) {
2731
2831
  return null;
2732
2832
  }
2733
2833
  const decoder = new RAnsSymbolDecoder(maxBitLength);
2734
- if (!decoder.create(srcBuffer)) {
2834
+ if (!decoder.create(srcBuffer, numValues)) {
2735
2835
  return null;
2736
2836
  }
2737
2837
  if (numValues > 0 && decoder.numSymbols === 0) {
@@ -2744,7 +2844,7 @@ function parseRawSymbolStream(numValues, srcBuffer) {
2744
2844
  }
2745
2845
  function decodeRawSymbolsInternal(uniqueSymbolsBitLength, numValues, srcBuffer, outValues) {
2746
2846
  const decoder = new RAnsSymbolDecoder(uniqueSymbolsBitLength);
2747
- if (!decoder.create(srcBuffer)) {
2847
+ if (!decoder.create(srcBuffer, numValues)) {
2748
2848
  return false;
2749
2849
  }
2750
2850
  if (numValues > 0 && decoder.numSymbols === 0) {
@@ -4246,11 +4346,16 @@ var PredictionSchemeDeltaDecoder = class extends PredictionSchemeDecoder {
4246
4346
  return true;
4247
4347
  }
4248
4348
  computeOriginalValues(inCorr, outData, size, numComponents, entryToPointIdMap) {
4249
- this._transform.init(numComponents);
4349
+ const transform = this._transform;
4350
+ transform.init(numComponents);
4351
+ if (transform.computeOriginalValuesDelta) {
4352
+ transform.computeOriginalValuesDelta(inCorr, outData, size, numComponents);
4353
+ return true;
4354
+ }
4250
4355
  const zeroVals = new Int32Array(numComponents);
4251
- this._transform.computeOriginalValue(zeroVals, 0, inCorr, 0, outData, 0);
4356
+ transform.computeOriginalValue(zeroVals, 0, inCorr, 0, outData, 0);
4252
4357
  for (let i = numComponents; i < size; i += numComponents) {
4253
- this._transform.computeOriginalValue(outData, i - numComponents, inCorr, i, outData, i);
4358
+ transform.computeOriginalValue(outData, i - numComponents, inCorr, i, outData, i);
4254
4359
  }
4255
4360
  return true;
4256
4361
  }
@@ -4791,7 +4896,6 @@ var AttributeTransform = class {
4791
4896
  // src/decoder/attributes/AttributeOctahedronTransform.ts
4792
4897
  var AttributeOctahedronTransform = class extends AttributeTransform {
4793
4898
  _quantizationBits;
4794
- _tmpVec;
4795
4899
  constructor() {
4796
4900
  super();
4797
4901
  this._quantizationBits = -1;
@@ -4823,15 +4927,30 @@ var AttributeOctahedronTransform = class extends AttributeTransform {
4823
4927
  const srcI32 = new Int32Array(srcAddr.buffer, srcAddr.byteOffset, numPoints * 2);
4824
4928
  const dstAddr = targetAttribute.getAddress(0);
4825
4929
  const dstF32 = new Float32Array(dstAddr.buffer, dstAddr.byteOffset, numPoints * 3);
4826
- const outVec = this._tmpVec || (this._tmpVec = new Float32Array(3));
4930
+ const fround = Math.fround;
4931
+ const scale = toolBox._dequantizationScale;
4827
4932
  let si = 0;
4828
4933
  let di = 0;
4829
4934
  for (let i = 0; i < numPoints; i++) {
4830
- toolBox.quantizedOctahedralCoordsToUnitVector(srcI32[si], srcI32[si + 1], outVec);
4935
+ let y = fround(fround(fround(srcI32[si]) * scale) - 1);
4936
+ let z = fround(fround(fround(srcI32[si + 1]) * scale) - 1);
4831
4937
  si += 2;
4832
- dstF32[di] = outVec[0];
4833
- dstF32[di + 1] = outVec[1];
4834
- dstF32[di + 2] = outVec[2];
4938
+ const x = fround(fround(1 - Math.abs(y)) - Math.abs(z));
4939
+ let xOffset = -x;
4940
+ if (xOffset < 0) xOffset = 0;
4941
+ y = fround(y + (y < 0 ? xOffset : -xOffset));
4942
+ z = fround(z + (z < 0 ? xOffset : -xOffset));
4943
+ const normSquared = fround(fround(fround(x * x) + fround(y * y)) + fround(z * z));
4944
+ if (normSquared < 1e-6) {
4945
+ dstF32[di] = 0;
4946
+ dstF32[di + 1] = 0;
4947
+ dstF32[di + 2] = 0;
4948
+ } else {
4949
+ const d = fround(1 / fround(Math.sqrt(normSquared)));
4950
+ dstF32[di] = fround(x * d);
4951
+ dstF32[di + 1] = fround(y * d);
4952
+ dstF32[di + 2] = fround(z * d);
4953
+ }
4835
4954
  di += 3;
4836
4955
  }
4837
4956
  return true;
@@ -5001,6 +5120,140 @@ var PredictionSchemeNormalOctahedronCanonicalizedDecodingTransform = class exten
5001
5120
  outOrigVals[outOffset] = origS + center;
5002
5121
  outOrigVals[outOffset + 1] = origT + center;
5003
5122
  }
5123
+ // Fused delta loop for PredictionSchemeDeltaDecoder: the whole
5124
+ // value[i] = original(value[i-1], corr[i]) chain in one call, with the
5125
+ // toolbox fields hoisted to locals and the previous output carried in
5126
+ // locals. This is the hot path for PREDICTION_DIFFERENCE normals (one call
5127
+ // per value through the interface was ~8% of decode time on the bundles).
5128
+ // The arithmetic is computeOriginalValue above verbatim -- keep them in
5129
+ // sync; only the plumbing differs.
5130
+ computeOriginalValuesDelta(inCorr, outData, size, numComponents) {
5131
+ const toolBox = this._octahedronToolBox;
5132
+ const center = toolBox._centerValue;
5133
+ const maxQuantizedValue = toolBox._maxQuantizedValue;
5134
+ let prevS = 0;
5135
+ let prevT = 0;
5136
+ for (let i = 0; i < size; i += numComponents) {
5137
+ const corrS = inCorr[i];
5138
+ const corrT = inCorr[i + 1];
5139
+ let predS = prevS - center;
5140
+ let predT = prevT - center;
5141
+ const predIsInDiamond = Math.abs(predS) + Math.abs(predT) <= center;
5142
+ if (!predIsInDiamond) {
5143
+ let signS = 0;
5144
+ let signT = 0;
5145
+ if (predS >= 0 && predT >= 0) {
5146
+ signS = 1;
5147
+ signT = 1;
5148
+ } else if (predS <= 0 && predT <= 0) {
5149
+ signS = -1;
5150
+ signT = -1;
5151
+ } else {
5152
+ signS = predS > 0 ? 1 : -1;
5153
+ signT = predT > 0 ? 1 : -1;
5154
+ }
5155
+ const cornerPointS = signS * center;
5156
+ const cornerPointT = signT * center;
5157
+ let us = predS * 2 - cornerPointS | 0;
5158
+ let ut = predT * 2 - cornerPointT | 0;
5159
+ if (signS * signT >= 0) {
5160
+ const temp = us;
5161
+ us = -ut;
5162
+ ut = -temp;
5163
+ } else {
5164
+ const temp = us;
5165
+ us = ut;
5166
+ ut = temp;
5167
+ }
5168
+ predS = (us + cornerPointS) / 2 | 0;
5169
+ predT = (ut + cornerPointT) / 2 | 0;
5170
+ }
5171
+ const predIsInBottomLeft = predS === 0 && predT === 0 || predS < 0 && predT <= 0;
5172
+ let rotationCount = 0;
5173
+ if (predS === 0) {
5174
+ if (predT > 0) rotationCount = 3;
5175
+ else if (predT < 0) rotationCount = 1;
5176
+ } else if (predS > 0) {
5177
+ if (predT >= 0) rotationCount = 2;
5178
+ else rotationCount = 1;
5179
+ } else {
5180
+ if (predT > 0) rotationCount = 3;
5181
+ }
5182
+ if (!predIsInBottomLeft) {
5183
+ const s = predS, t = predT;
5184
+ switch (rotationCount) {
5185
+ case 1:
5186
+ predS = t;
5187
+ predT = -s | 0;
5188
+ break;
5189
+ case 2:
5190
+ predS = -s | 0;
5191
+ predT = -t | 0;
5192
+ break;
5193
+ case 3:
5194
+ predS = -t | 0;
5195
+ predT = s;
5196
+ break;
5197
+ }
5198
+ }
5199
+ let origS = predS + corrS | 0;
5200
+ if (origS > center) origS -= maxQuantizedValue;
5201
+ else if (origS < -center) origS += maxQuantizedValue;
5202
+ let origT = predT + corrT | 0;
5203
+ if (origT > center) origT -= maxQuantizedValue;
5204
+ else if (origT < -center) origT += maxQuantizedValue;
5205
+ if (!predIsInBottomLeft) {
5206
+ const s = origS, t = origT;
5207
+ switch (4 - rotationCount & 3) {
5208
+ case 1:
5209
+ origS = t;
5210
+ origT = -s | 0;
5211
+ break;
5212
+ case 2:
5213
+ origS = -s | 0;
5214
+ origT = -t | 0;
5215
+ break;
5216
+ case 3:
5217
+ origS = -t | 0;
5218
+ origT = s;
5219
+ break;
5220
+ }
5221
+ }
5222
+ if (!predIsInDiamond) {
5223
+ let signS = 0;
5224
+ let signT = 0;
5225
+ if (origS >= 0 && origT >= 0) {
5226
+ signS = 1;
5227
+ signT = 1;
5228
+ } else if (origS <= 0 && origT <= 0) {
5229
+ signS = -1;
5230
+ signT = -1;
5231
+ } else {
5232
+ signS = origS > 0 ? 1 : -1;
5233
+ signT = origT > 0 ? 1 : -1;
5234
+ }
5235
+ const cornerPointS = signS * center;
5236
+ const cornerPointT = signT * center;
5237
+ let us = origS * 2 - cornerPointS | 0;
5238
+ let ut = origT * 2 - cornerPointT | 0;
5239
+ if (signS * signT >= 0) {
5240
+ const temp = us;
5241
+ us = -ut;
5242
+ ut = -temp;
5243
+ } else {
5244
+ const temp = us;
5245
+ us = ut;
5246
+ ut = temp;
5247
+ }
5248
+ origS = (us + cornerPointS) / 2 | 0;
5249
+ origT = (ut + cornerPointT) / 2 | 0;
5250
+ }
5251
+ prevS = origS + center | 0;
5252
+ prevT = origT + center | 0;
5253
+ outData[i] = prevS;
5254
+ outData[i + 1] = prevT;
5255
+ }
5256
+ }
5004
5257
  };
5005
5258
 
5006
5259
  // src/decoder/compression/attributes/prediction_schemes/PredictionSchemeNormalOctahedronDecodingTransform.ts
@@ -7235,7 +7488,7 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
7235
7488
  return false;
7236
7489
  }
7237
7490
  const decoder = new RAnsSymbolDecoder(maxBitLength);
7238
- if (!decoder.create(outBuffer)) {
7491
+ if (!decoder.create(outBuffer, numSymbols)) {
7239
7492
  return false;
7240
7493
  }
7241
7494
  if (decoder.numSymbols === 0) {
@@ -7251,37 +7504,38 @@ var MeshEdgebreakerTraversalValenceDecoder = class extends MeshEdgebreakerTraver
7251
7504
  this._contextCounters[i] = 0;
7252
7505
  }
7253
7506
  }
7254
- const allU8 = pending.every((entry) => entry.decoder.ans_.lutTable instanceof Uint8Array);
7507
+ const lockstep = pending.filter((entry) => entry.decoder.ans_.lutTable instanceof Uint8Array);
7255
7508
  let p = 0;
7256
- if (allU8) {
7257
- while (pending.length - p >= 3) {
7258
- const a = pending[p];
7259
- const b = pending[p + 1];
7260
- const c = pending[p + 2];
7261
- ransDecodeSymbolsTrioU8(
7262
- a.decoder.ans_,
7263
- a.out,
7264
- a.count,
7265
- b.decoder.ans_,
7266
- b.out,
7267
- b.count,
7268
- c.decoder.ans_,
7269
- c.out,
7270
- c.count
7271
- );
7272
- p += 3;
7273
- }
7274
- if (pending.length - p === 2) {
7275
- const a = pending[p];
7276
- const b = pending[p + 1];
7277
- ransDecodeSymbolsPairU8(a.decoder.ans_, a.out, a.count, b.decoder.ans_, b.out, b.count);
7278
- p += 2;
7279
- }
7509
+ while (lockstep.length - p >= 3) {
7510
+ const a = lockstep[p];
7511
+ const b = lockstep[p + 1];
7512
+ const c = lockstep[p + 2];
7513
+ ransDecodeSymbolsTrioU8(
7514
+ a.decoder.ans_,
7515
+ a.out,
7516
+ a.count,
7517
+ b.decoder.ans_,
7518
+ b.out,
7519
+ b.count,
7520
+ c.decoder.ans_,
7521
+ c.out,
7522
+ c.count
7523
+ );
7524
+ p += 3;
7280
7525
  }
7281
- for (; p < pending.length; ++p) {
7282
- pending[p].decoder.ans_.decodeSymbols(pending[p].out, pending[p].count);
7526
+ if (lockstep.length - p === 2) {
7527
+ const a = lockstep[p];
7528
+ const b = lockstep[p + 1];
7529
+ ransDecodeSymbolsPairU8(a.decoder.ans_, a.out, a.count, b.decoder.ans_, b.out, b.count);
7530
+ p += 2;
7531
+ }
7532
+ for (; p < lockstep.length; ++p) {
7533
+ lockstep[p].decoder.ans_.decodeSymbols(lockstep[p].out, lockstep[p].count);
7283
7534
  }
7284
7535
  for (const entry of pending) {
7536
+ if (!(entry.decoder.ans_.lutTable instanceof Uint8Array)) {
7537
+ entry.decoder.ans_.decodeSymbols(entry.out, entry.count);
7538
+ }
7285
7539
  entry.decoder.endDecoding();
7286
7540
  }
7287
7541
  return true;