@@ -298,6 +298,8 @@ function buildAscendingBounds(sortedBounds: readonly (readonly [Bounds, LayoutIn
298
298
function generateLayoutDiscriminator (
299
299
layouts : readonly Layout [ ]
300
300
) : [ boolean , ( encoded : BytesType ) => readonly LayoutIndex [ ] ] {
301
+ //for debug output:
302
+ // const candStr = (candidate: Bitset) => candidate.toString(2).padStart(layouts.length, '0');
301
303
302
304
if ( layouts . length === 0 )
303
305
throw new Error ( "Cannot discriminate empty set of layouts" ) ;
@@ -357,6 +359,11 @@ function generateLayoutDiscriminator(
357
359
for ( let j = 0 ; j < serialized . length ; ++ j )
358
360
fixedKnownBytes [ offset + j ] ! . push ( [ serialized [ j ] ! , i ] ) ;
359
361
362
+ //debug output:
363
+ // console.log("fixedKnownBytes:",
364
+ // fixedKnownBytes.map((v, i) => v.length > 0 ? [i, v] : undefined).filter(v => v !== undefined)
365
+ // );
366
+
360
367
let bestBytes = [ ] ;
361
368
for ( const [ bytePos , fixedKnownByte ] of fixedKnownBytes . entries ( ) ) {
362
369
//the number of layouts with a given size is an upper bound on the discriminatory power of
@@ -376,7 +383,7 @@ function generateLayoutDiscriminator(
376
383
distinctValues . set ( byteVal , distinctValues . get ( byteVal ) ! | 1n << BigInt ( candidate ) ) ;
377
384
}
378
385
379
- let power = count ( lwba ) ;
386
+ let power = layouts . length - Math . max ( count ( anyValueLayouts ) , count ( outOfBoundsLayouts ) ) ;
380
387
for ( const layoutsWithValue of distinctValues . values ( ) ) {
381
388
//if we find the byte value associated with this set of layouts, we can eliminate
382
389
// all other layouts that don't have this value at this position and all layouts
@@ -385,6 +392,17 @@ function generateLayoutDiscriminator(
385
392
power = Math . min ( power , curPower ) ;
386
393
}
387
394
395
+ //debug output:
396
+ // console.log(
397
+ // "bytePos:", bytePos,
398
+ // "\npower:", power,
399
+ // "\nfixedKnownByte:", fixedKnownByte,
400
+ // "\nlwba:", candStr(lwba),
401
+ // "\nanyValueLayouts:", candStr(anyValueLayouts),
402
+ // "\noutOfBoundsLayouts:", candStr(outOfBoundsLayouts),
403
+ // "\ndistinctValues:", new Map([...distinctValues].map(([k, v]) => [k, candStr(v)]))
404
+ // );
405
+
388
406
if ( power === 0 )
389
407
continue ;
390
408
@@ -521,14 +539,31 @@ function generateLayoutDiscriminator(
521
539
throw new Error ( "Implementation error in layout discrimination algorithm" ) ;
522
540
} ;
523
541
542
+ //debug output:
543
+ // console.log("strategies:", JSON.stringify(
544
+ // new Map([...strategies].map(([cands, strat]) => [
545
+ // candStr(cands),
546
+ // typeof strat === "string"
547
+ // ? strat
548
+ // : [
549
+ // strat[0], //bytePos
550
+ // candStr(strat[1]), //outOfBoundsLayouts
551
+ // new Map([...strat[2]].map(([value, cands]) => [value, candStr(cands)]))
552
+ // ]
553
+ // ]
554
+ // ))
555
+ // ));
556
+
524
557
return [ distinguishable , ( encoded : BytesType ) => {
525
558
let candidates = allLayouts ;
526
559
527
- for (
528
- let strategy = strategies . get ( candidates ) ! ;
529
- strategy !== "indistinguishable" ;
530
- strategy = strategies . get ( candidates ) ?? findSmallestSuperSetStrategy ( candidates )
531
- ) {
560
+ let strategy = strategies . get ( candidates ) ! ;
561
+ while ( strategy !== "indistinguishable" ) {
562
+ //debug output:
563
+ // console.log(
564
+ // "applying strategy", strategy,
565
+ // "\nfor remaining candidates:", candStr(candidates)
566
+ // );
532
567
if ( strategy === "size" )
533
568
candidates &= layoutsWithSize ( encoded . length ) ;
534
569
else {
@@ -546,9 +581,13 @@ function generateLayoutDiscriminator(
546
581
}
547
582
548
583
if ( count ( candidates ) <= 1 )
549
- return bitsetToArray ( candidates ) ;
584
+ break ;
585
+
586
+ strategy = strategies . get ( candidates ) ?? findSmallestSuperSetStrategy ( candidates )
550
587
}
551
588
589
+ //debug output:
590
+ // console.log("final candidates", candStr(candidates));
552
591
return bitsetToArray ( candidates ) ;
553
592
} ] ;
554
593
}
0 commit comments