variants.go raw

   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