// NewD returns a fiber of type D_n, with n >= 4. func NewD(n int) *Fiber { //TODO(fs) should check d >= 4 i := strconv.Itoa(n) contr := make([]*nt.Frac, 3) // no contr[3] as the two far components are symmetric contr[0] = nt.NewFrac(0, 1) contr[1] = nt.NewFrac(1, 1) contr[2] = nt.NewFrac(n, 4) return &Fiber{n + 2, n, 4, "D_" + i, contr} }
// NewE returns a fiber of type E_n, with n=6,7 or 8. func NewE(n int) *Fiber { i := strconv.Itoa(n) var contr []*nt.Frac switch n { case 6: contr = []*nt.Frac{nt.NewFrac(0, 1), nt.NewFrac(4, 3)} case 7: contr = []*nt.Frac{nt.NewFrac(0, 1), nt.NewFrac(3, 2)} case 8: contr = []*nt.Frac{nt.NewFrac(0, 1)} } return &Fiber{2 + n, n, 9 - n, "E_" + i, contr} }
func (c Config) walkHeightsIter(contr *nt.Frac, rest Config, inter []int, goal *nt.Frac) { if len(rest) == 0 { height := nt.NewFrac(4, 1) height.Add(height, nt.NewFrac(2*zeroIntersection, 1)) // possible intersection with the zero-section height.Sub(height, contr) disc := nt.NewFrac(0, 1) disc.Mul(height, nt.NewFrac(c.Disc(), 1)) if disc.Equal(goal) { fmt.Println(c, "with inter=", inter, "contr=", contr, "d_T=", c.Disc(), "d_NS=", disc) } } else { for i, v := range rest[0].Contrib() { c.walkHeightsIter(nt.NewFrac(0, 1).Add(contr, v), rest[1:], append(inter, i), goal) } } }
// NewA returns a fiber of type A_n. func NewA(n int) *Fiber { i := strconv.Itoa(n) contr := make([]*nt.Frac, (n+1)/2+1) // A_n fibers are symmetric for i := range contr { contr[i] = nt.NewFrac(i*((n+1)-i), n+1) } return &Fiber{n + 1, n, n + 1, "A_" + i, contr} }
// WalkHeights prints all possible ways a section may meet the given configuration // to produce a lattice with discriminant d. func (c Config) WalkHeights(d int) { c.walkHeightsIter(nt.NewFrac(0, 1), c, []int{}, nt.NewFrac(d, 1)) }