source: frontend/node_modules/tailwindcss/src/lib/remap-bitfield.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 12 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 2.5 KB
RevLine 
[9af201e]1// @ts-check
2
3/**
4 * We must remap all the old bits to new bits for each set variant
5 * Only arbitrary variants are considered as those are the only
6 * ones that need to be re-sorted at this time
7 *
8 * An iterated process that removes and sets individual bits simultaneously
9 * will not work because we may have a new bit that is also a later old bit
10 * This means that we would be removing a previously set bit which we don't
11 * want to do
12 *
13 * For example (assume `bN` = `1<<N`)
14 * Given the "total" mapping `[[b1, b3], [b2, b4], [b3, b1], [b4, b2]]`
15 * The mapping is "total" because:
16 * 1. Every input and output is accounted for
17 * 2. All combinations are unique
18 * 3. No one input maps to multiple outputs and vice versa
19 * And, given an offset with all bits set:
20 * V = b1 | b2 | b3 | b4
21 *
22 * Let's explore the issue with removing and setting bits simultaneously:
23 * V & ~b1 | b3 = b2 | b3 | b4
24 * V & ~b2 | b4 = b3 | b4
25 * V & ~b3 | b1 = b1 | b4
26 * V & ~b4 | b2 = b1 | b2
27 *
28 * As you can see, we end up with the wrong result.
29 * This is because we're removing a bit that was previously set.
30 * And, thus the final result is missing b3 and b4.
31 *
32 * Now, let's explore the issue with removing the bits first:
33 * V & ~b1 = b2 | b3 | b4
34 * V & ~b2 = b3 | b4
35 * V & ~b3 = b4
36 * V & ~b4 = 0
37 *
38 * And then setting the bits:
39 * V | b3 = b3
40 * V | b4 = b3 | b4
41 * V | b1 = b1 | b3 | b4
42 * V | b2 = b1 | b2 | b3 | b4
43 *
44 * We get the correct result because we're not removing any bits that were
45 * previously set thus properly remapping the bits to the new order
46 *
47 * To collect this into a single operation that can be done simultaneously
48 * we must first create a mask for the old bits that are set and a mask for
49 * the new bits that are set. Then we can remove the old bits and set the new
50 * bits simultaneously in a "single" operation like so:
51 * OldMask = b1 | b2 | b3 | b4
52 * NewMask = b3 | b4 | b1 | b2
53 *
54 * So this:
55 * V & ~oldMask | newMask
56 *
57 * Expands to this:
58 * V & ~b1 & ~b2 & ~b3 & ~b4 | b3 | b4 | b1 | b2
59 *
60 * Which becomes this:
61 * b1 | b2 | b3 | b4
62 *
63 * Which is the correct result!
64 *
65 * @param {bigint} num
66 * @param {[bigint, bigint][]} mapping
67 */
68export function remapBitfield(num, mapping) {
69 // Create masks for the old and new bits that are set
70 let oldMask = 0n
71 let newMask = 0n
72 for (let [oldBit, newBit] of mapping) {
73 if (num & oldBit) {
74 oldMask = oldMask | oldBit
75 newMask = newMask | newBit
76 }
77 }
78
79 // Remove all old bits
80 // Set all new bits
81 return (num & ~oldMask) | newMask
82}
Note: See TracBrowser for help on using the repository browser.