1 package hexagram
2 3 import (
4 "git.mleku.dev/mleku/dendrite/pkg/permutation"
5 "git.mleku.dev/mleku/dendrite/pkg/state"
6 )
7 8 // variantTables holds 6 lookup tables, one per S_3 permutation.
9 // variantTables[Identity] is identical to the canonical table.
10 //
11 // To look up a rule for hexagram h under permutation p: the hexagram
12 // bits encode state in p's frame, so we apply p^-1 to map back to the
13 // canonical frame, then look up the canonical rule.
14 var variantTables [permutation.Count][64]Rule
15 16 func init() {
17 for _, p := range permutation.All() {
18 inv := p.Inverse()
19 for h := range uint8(64) {
20 canonical := inv.ApplyHexagram(state.Hexagram(h))
21 variantTables[p][h] = table[uint8(canonical)]
22 }
23 }
24 }
25 26 // LookupVariant returns the rule for hexagram h under permutation p.
27 // When p is Identity, this is equivalent to Lookup(h).
28 func LookupVariant(h state.Hexagram, p permutation.Perm) Rule {
29 return variantTables[p][uint8(h)]
30 }
31 32 // keyToPerm maps a 3-bit projection key (0-7) to an S_3 permutation.
33 // Keys 6 and 7 are collapse points that alias to existing permutations.
34 var keyToPerm = [8]permutation.Perm{
35 permutation.Identity, // 000: face XY
36 permutation.Swap12, // 001: face XZ
37 permutation.Swap02, // 010: face YZ
38 permutation.Swap01, // 011: edge bias
39 permutation.Cycle012, // 100: vertex A
40 permutation.Cycle021, // 101: vertex B
41 permutation.Identity, // 110: collapse → Identity
42 permutation.Swap12, // 111: collapse → Swap12
43 }
44 45 // LookupProjected returns the rule for hexagram h given a 3-bit projection
46 // key. The key determines the S_3 permutation applied to the hexagram
47 // before rule lookup. Collapse keys (6, 7) reduce to their parent
48 // permutations, which is the geometric meaning of projection collapse:
49 // the rule table simplifies.
50 func LookupProjected(h state.Hexagram, projKey uint8) Rule {
51 p := keyToPerm[projKey&0b111]
52 return variantTables[p][uint8(h)]
53 }
54 55 // LookupFull returns the rule for a hexagram given the full 6-bit
56 // projection encoding (vertex in low 3 bits, key in high 3 bits).
57 // The vertex contributes to the hexagram's inner trigram (it IS the
58 // inner trigram). The key determines the projection permutation.
59 func LookupFull(h state.Hexagram, proj6bit uint8) Rule {
60 key := (proj6bit >> 3) & 0b111
61 return LookupProjected(h, key)
62 }
63