Put reference to arXiv preprint in README.
[fgc-section-5.git] / verification.myr
blob2e2a3fceea475edf284f41c68c1544f703c92ce1
1 use std
3 use quiver
4 use t
5 use yakmo
7 use "factorization-coords"
8 use "kc"
9 use "mutations"
10 use "mkQ"
11 use "M"
12 use "roots"
13 use "types"
14 use "util"
15 use "zzz"
17 pkg =
18         const numerically_test_rotate : (kc : KC_type, seed : uint32, fast : bool -> std.result(void, byte[:]))
19         const numerically_test_flip : (kc : KC_type, seed : uint32, fast : bool -> std.result(void, byte[:]))
21         pkglocal const assign_TQ_to_quiver : (kc : KC_type, TQ : T_Q#, q : quiver.quiver# -> void)
22         pkglocal const assign_quiver_to_TQ : (kc : KC_type, q : quiver.quiver#, TQ : T_Q# -> void)
23         pkglocal const assign_quiver_to_TQ02 : (kc : KC_type, q : quiver.quiver#, TQ : T_Q02# -> void)
24         pkglocal const assign_quiver_to_TQ13 : (kc : KC_type, q : quiver.quiver#, TQ : T_Q13# -> void)
25         pkglocal const assign_TQ02_to_quiver : (kc : KC_type, TQ : T_Q02#, q : quiver.quiver# -> void)
26         pkglocal const assign_TQ13_to_quiver : (kc : KC_type, TQ : T_Q13#, q : quiver.quiver# -> void)
27         pkglocal const random_minor : (rng : std.rng# -> yakmo.ratfunc#)
30 type subscript = int
32 const __init__ = {
33         var s : subscript = 1
34         std.fmtinstall(std.typeof(s), subscriptfmt)
37 const subscripts = [ '₀', '₁', '₂', '₃', '₄', '₅', '₆', '₇', '₈', '₉' ][:]
39 const subscriptfmt = {sb, ap, opts
40         var ss : subscript = std.vanext(ap)
41         var s = (ss : int)
42         if s < 0
43                 std.sbputc(sb, '₋')
44                 s *= -1
45         ;;
47         if s == 0
48                 std.sbputc(sb, subscripts[0])
49         ;;
51         var l = [][:]
53         while s != 0
54                 std.slpush(&l, subscripts[s % 10])
55                 s = s / 10
56         ;;
58         for var k = l.len - 1; k >= 0; --k
59                 std.sbputc(sb, l[k])
60         ;;
63 const random_minor = {rng
64         var a : int = std.rngrand(rng, 2, 29)
65         if std.rngrand(rng, 0, 2) == 1
66                 /*
67                    Commenting out this line makes all minors displayed
68                    in tests positive. This useful for verifying in other
69                    software that is unable to handle negative
70                    coordinates.
71                  */
72                 a *= -1
73         ;;
74         var b : int = std.rngrand(rng, 1, 29)
75         var aq : yakmo.Q# = auto yakmo.QfromZ(a)
76         var bq : yakmo.Q# = auto yakmo.QfromZ(b)
77         var ap : yakmo.polynomial# = yakmo.polynomialfromQ(aq)
78         var bp : yakmo.polynomial# = yakmo.polynomialfromQ(bq)
79         var base : yakmo.ratfunc = [ .num = ap, .den = bp, .reduced = false ]
80         yakmo.reduceratfunc(&base)
82         -> std.mk(base)
85 const numerically_test_rotate = {kc, seed, fast
86         var rng : std.rng# = std.mksrng(seed)
87         std.put("seed = {}\n", seed)
88         var rank : int = get_n(kc)
89         var w0 : weyl_reflection[:] = get_w0(kc)
90         var c : weyl_reflection[:] = [][:]
91         match get_coxeter_elt(kc)
92         | `std.Ok cc: c = cc
93         | `std.Err e: -> `std.Err std.fmt("get_coxeter_elt({}): {}", kc, e)
94         ;;
95         var h1 : minor_coordinate[:] = [][:]
96         var h2 : minor_coordinate[:] = [][:]
97         var h3 : minor_coordinate[:] = [][:]
98         var u : minor_coordinate[:] = [][:]
99         var perm_class : Dynkin_automorphism_class = get_trivial_Dynkin_automorphism(kc)
101         /* Recall that hi[k] = χ_{ω_{i_k}}(hi) */
102         for var j = 1; j <= rank; ++j
103                 std.slpush(&h1, [ .k = j, .c = random_minor(rng) ])
104                 std.slpush(&h2, [ .k = j, .c = random_minor(rng) ])
105                 std.slpush(&h3, [ .k = j, .c = random_minor(rng) ])
106         ;;
108         for var j = rank + 1; j <= w0.len; ++j
109                 std.slpush(&u, [ .k = j, .c = random_minor(rng) ])
110         ;;
112         var alpha : conf_3_star = [ .h1 = h1, .h2 = h2, .h3 = h3, .u = u ]
113         match fill_in_alpha(kc, &alpha)
114         | `std.Err e:
115                 auto (e : t.doomed_str)
116                 -> `std.Err std.fmt("fill_in_alpha: {}", e)
117         | `std.Ok void:
118         ;;
120         // match interior_fc_from_mc_and_undo_psi_phi_psi(kc, alpha.u)
121         // | `std.Err e:
122         //         auto (e : t.doomed_str)
123         //         -> `std.Err std.fmt("whatever: {}", e)
124         // | `std.Ok f:
125         //         std.put("DXJ 01\n")
126         //         for var j = 0; j < f.len; ++j
127         //                 std.put("{}\n", f[j])
128         //         ;;
129         //         std.put("\n\n")
130         // ;;
132         /* via Lusztig's calculus */
133         var via_lusztig
134         match rotate(kc, &alpha)
135         | `std.Err e: -> `std.Err std.fmt("rotate(): {}", e)
136         | `std.Ok a: via_lusztig = a
137         ;;
138         // match interior_fc_from_mc_and_undo_psi_phi_psi(kc, via_lusztig.u)
139         // | `std.Err e:
140         //         auto (e : t.doomed_str)
141         //         -> `std.Err std.fmt("whatever: {}", e)
142         // | `std.Ok f:
143         //         std.put("DXJ 02\n")
144         //         for var j = 0; j < f.len; ++j
145         //                 std.put("{}\n", f[j])
146         //         ;;
147         //         std.put("\n\n")
148         // ;;
150         /* via section 5 */
151         var mures
152         if fast
153                 mures = get_mutwistingrot(kc)
154         else
155                 mures = get_murot(kc)
156         ;;
158         var via_section_5
159         match (mures, mk_Q(kc), apply_M(kc, &alpha, perm_class))
160         | (`std.Err e, _, _): -> `std.Err std.fmt("murot({}): {}", kc, e)
161         | (_, `std.Err e, _): -> `std.Err std.fmt("mk_Q({}): {}", kc, e)
162         | (_, _, `std.Err e): -> `std.Err std.fmt("apply_M({}, α): {}", kc, e)
163         | (`std.Ok mu, `std.Ok q, `std.Ok (TQ, perm_class_prime)):
164                 /* Assign coordinates to q from TQ */
165                 assign_TQ_to_quiver(kc, TQ, q)
166                 perm_class = perm_class_prime
168                 // std.put("DXJ 03\n")
169                 // for var j = 0; j < q.v.len; ++j
170                 //         std.put("{} : {}\n", q.v[j].name, q.v[j].acoord)
171                 // ;;
173                 /* Apply murot */
174                 var q_dup : quiver.quiver# = t.dup(q)
175                 auto q_dup
176                 match quiver.mutateseq_ip(q, mu)
177                 | `std.Ok void:
178                 | `std.Err e: -> `std.Err std.fmt("applying murot: {}", e)
179                 ;;
180                 perm_class = apply_sigmaG(perm_class)
182                 /* Rename according to mutation */
183                 if fast
184                         perm_class = apply_sigmaG(perm_class)
186                         match rename_according_to_twistingrot(kc, q_dup, q)
187                         | `std.Ok void:
188                         | `std.Err e: -> `std.Err std.fmt("rename_according_to_twistingrot: {}", e)
189                         ;;
190                 else
191                         match rename_according_to_rot(kc, q_dup, q)
192                         | `std.Ok void:
193                         | `std.Err e: -> `std.Err std.fmt("rename_according_to_murot: {}", e)
194                         ;;
195                 ;;
197                 // std.put("DXJ 04\n")
198                 // for var j = 0; j < q.v.len; ++j
199                 //         std.put("{} : {}\n", q.v[j].name, q.v[j].acoord)
200                 // ;;
202                 /* Get coordinates back from q to TQ */
203                 assign_quiver_to_TQ(kc, q, TQ)
205                 match unapply_M(kc, TQ, perm_class)
206                 | `std.Err e: -> `std.Err std.fmt("unapply_M({}, μrot(T_Q)): {}", kc, e)
207                 | `std.Ok (a, perm_class_primeprime):
208                         (via_section_5, perm_class) = (a, perm_class_primeprime)
209                 ;;
211                 -> display_seed_tori(kc, &alpha, via_lusztig, via_section_5, "rot")
212         ;;
215 const numerically_test_flip = {kc, seed, fast
216         var rng : std.rng# = std.mksrng(seed)
217         std.put("seed = {}\n", seed)
218         var rank : int = get_n(kc)
219         var w0 : weyl_reflection[:] = get_w0(kc)
220         var c : weyl_reflection[:] = [][:]
221         match get_coxeter_elt(kc)
222         | `std.Ok cc: c = cc
223         | `std.Err e: -> `std.Err std.fmt("get_coxeter_elt({}): {}", kc, e)
224         ;;
226         /*
227            Canonical form of α = (g₀N, g₁N, g₂N, g₃N) as
229            (N, w₀(h₀₂) w₀(h₁₂)⁻¹ u⁻¹ N, w₀ h₀₂ N, Φ⁻¹(v) w₀ h₀₃ N)
230          */
231         var h01_sG : minor_coordinate[:] = [][:]
232         var h12 : minor_coordinate[:] = [][:]
233         var h02 : minor_coordinate[:] = [][:]
234         var h23 : minor_coordinate[:] = [][:]
235         var h03_sG : minor_coordinate[:] = [][:]
236         var u : minor_coordinate[:] = [][:]
237         var v : minor_coordinate[:] = [][:]
239         for var j = 1; j <= rank; ++j
240                 std.slpush(&h01_sG, [ .k = j, .c = random_minor(rng) ])
241                 std.slpush(&h12, [ .k = j, .c = random_minor(rng) ])
242                 std.slpush(&h02, [ .k = j, .c = random_minor(rng) ])
243                 std.slpush(&h23, [ .k = j, .c = random_minor(rng) ])
244                 std.slpush(&h03_sG, [ .k = j, .c = random_minor(rng) ])
245         ;;
246         for var j = rank + 1; j <= w0.len; ++j
247                 std.slpush(&u, [ .k = j, .c = random_minor(rng) ])
248                 std.slpush(&v, [ .k = j, .c = random_minor(rng) ])
249         ;;
251         var h03
252         match multiply_h_mc_by_sG(kc, h03_sG)
253         | `std.Err e: -> `std.Err std.fmt("w₀(h₀₃⁻¹): {}", e)
254         | `std.Ok h: h03 = h
255         ;;
256         auto h03_sG
258         var h01
259         match multiply_h_mc_by_sG(kc, h01_sG)
260         | `std.Err e: -> `std.Err std.fmt("w₀(h₀₁⁻¹): {}", e)
261         | `std.Ok h: h01 = h
262         ;;
263         auto h01_sG
265         /* u is the N_{-} component of alpha_120 = (g1, g2, g0 sG). */
266         var wo_h02_inv
267         match apply_wo_of_inv(kc, h02)
268         | `std.Err e: -> `std.Err std.fmt("w₀(h₀₂⁻¹): {}", e)
269         | `std.Ok h: wo_h02_inv = h
270         ;;
271         auto wo_h02_inv
273         fill_in_u_from_h01_h12_h20(kc, &u, h12, wo_h02_inv, h01_sG)
275         /* v is the N_{-} component of alpha_023 */
276         var w0_h03i
277         match apply_wo_of_inv(kc, h03)
278         | `std.Err e: -> `std.Err std.fmt("w₀(h₀₃⁻¹): {}", e)
279         | `std.Ok h: w0_h03i = h
280         ;;
281         auto w0_h03i
283         var h30
284         match multiply_h_mc_by_sG(kc, w0_h03i)
285         | `std.Err e: -> `std.Err std.fmt("w₀(h₀₃⁻¹): {}", e)
286         | `std.Ok h: h30 = h
287         ;;
288         auto h30
290         fill_in_u_from_h01_h12_h20(kc, &v, h02, h23, h30)
292         var alpha : conf_4_star = [
293                 .h01 = h01,
294                 .h12 = h12,
295                 .h02 = h02,
296                 .h23 = h23,
297                 .h03 = h03,
298                 .u = u,
299                 .v = v,
300         ]
302         var psi_02_alpha : (conf_3_star#, conf_3_star#)
303         match psi_02(kc, &alpha)
304         | `std.Err e: -> `std.Err std.fmt("Ψ₀₂(α): {}", e)
305         | `std.Ok aa: psi_02_alpha = aa
306         ;;
308         // match interior_fc_from_mc_and_undo_psi_phi_psi(kc, psi_02_alpha.0.u)
309         // | `std.Err e:
310         //         auto (e : t.doomed_str)
311         //         -> `std.Err std.fmt("whatever: {}", e)
312         // | `std.Ok f:
313         //         std.put("DXJ 01: u = \n")
314         //         for var j = 0; j < f.len; ++j
315         //                 std.put("            {}\n", f[j])
316         //         ;;
317         //         std.put("\n\n")
318         // ;;
319         // match interior_fc_from_mc_and_undo_psi_phi_psi(kc, psi_02_alpha.1.u)
320         // | `std.Err e:
321         //         auto (e : t.doomed_str)
322         //         -> `std.Err std.fmt("whatever: {}", e)
323         // | `std.Ok f:
324         //         std.put("DXJ 02: v = \n")
325         //         for var j = 0; j < f.len; ++j
326         //                 std.put("            {}\n", f[j])
327         //         ;;
328         //         std.put("\n\n")
329         // ;;
332         /* via Zickert + Lusztig */
333         var psi_13_alpha : (conf_3_star#, conf_3_star#)
334         match psi_13(kc, &alpha)
335         | `std.Err e: -> `std.Err std.fmt("Ψ₁₃(α): {}", e)
336         | `std.Ok aa: psi_13_alpha = aa
337         ;;
339         // match interior_fc_from_mc_and_undo_psi_phi_psi(kc, psi_13_alpha.0.u)
340         // | `std.Err e:
341         //         auto (e : t.doomed_str)
342         //         -> `std.Err std.fmt("whatever: {}", e)
343         // | `std.Ok f:
344         //         std.put("DXJ 03: u~ = \n")
345         //         for var j = 0; j < f.len; ++j
346         //                 std.put("            {}\n", f[j])
347         //         ;;
348         //         std.put("\n\n")
349         // ;;
350         // match interior_fc_from_mc_and_undo_psi_phi_psi(kc, psi_13_alpha.1.u)
351         // | `std.Err e:
352         //         auto (e : t.doomed_str)
353         //         -> `std.Err std.fmt("whatever: {}", e)
354         // | `std.Ok f:
355         //         std.put("DXJ 04: v~ = \n")
356         //         for var j = 0; j < f.len; ++j
357         //                 std.put("            {}\n", f[j])
358         //         ;;
359         //         std.put("\n\n")
360         // ;;
362         /* via section 5 */
363         var mures
364         if fast
365                 mures = get_mutwistingflip(kc)
366         else
367                 mures = get_muflip(kc)
368         ;;
370         var via_section_5
371         match (mures, mk_Qdv(kc), apply_Mdv(kc, psi_02_alpha))
372         | (`std.Err e, _, _): -> `std.Err std.fmt("muflip({}): {}", kc, e)
373         | (_, `std.Err e, _): -> `std.Err std.fmt("mk_Qdv({}): {}", kc, e)
374         | (_, _, `std.Err e): -> `std.Err std.fmt("apply_Mdv({}, α): {}", kc, e)
375         | (`std.Ok mu, `std.Ok qdv, `std.Ok T02):
376                 /* Assign coordinates to qdv from TQ02 */
377                 assign_TQ02_to_quiver(kc, T02, qdv)
379                 // std.put("DXJ 03: Qdv:\n")
380                 // for var j = 0; j < qdv.v.len; ++j
381                 //         std.put("    {}: {}\n", qdv.v[j].name, qdv.v[j].acoord)
382                 // ;;
384                 /* Apply muflip */
385                 var q_dup : quiver.quiver# = t.dup(qdv)
386                 auto q_dup
387                 match quiver.mutateseq_ip(qdv, mu)
388                 | `std.Ok void:
389                 | `std.Err e: -> `std.Err std.fmt("applying muflip: {}", e)
390                 ;;
392                 /* Rename according to mutation */
393                 if fast
394                         match rename_according_to_twistingflip(kc, q_dup, qdv)
395                         | `std.Ok void:
396                         | `std.Err e: -> `std.Err std.fmt("rename_according_to_muflip: {}", e)
397                         ;;
398                 else
399                         match rename_according_to_flip(kc, q_dup, qdv)
400                         | `std.Ok void:
401                         | `std.Err e: -> `std.Err std.fmt("rename_according_to_muflip: {}", e)
402                         ;;
403                 ;;
405                 /* Construct empty TQ13 */
406                 var T13 : T_Q13 = [
407                         .D = std.slalloc(T02.D.len),
408                         .E = std.slalloc(T02.E.len),
409                         .F = std.slalloc(T02.F.len),
410                         .G = std.slalloc(T02.G.len),
411                         .w = std.slalloc(T02.w.len),
412                 ]
413                 for var j = 0; j < T13.D.len; ++j
414                         T13.D[j] = yakmo.rid()
415                 ;;
416                 for var j = 0; j < T13.E.len; ++j
417                         T13.E[j] = yakmo.rid()
418                 ;;
419                 for var j = 0; j < T13.F.len; ++j
420                         T13.F[j] = yakmo.rid()
421                 ;;
422                 for var j = 0; j < T13.G.len; ++j
423                         T13.G[j] = yakmo.rid()
424                 ;;
425                 for var j = 0; j < T13.w.len; ++j
426                         T13.w[j] = std.slalloc(T02.w[j].len)
427                         for var k = 0; k < T13.w[j].len; ++k
428                                 T13.w[j][k] = yakmo.rid()
429                         ;;
430                 ;;
432                 /* Get coordinates back from qdv (which now should be isomorphic to qdh) */
433                 assign_quiver_to_TQ13(kc, qdv, &T13)
435                 match unapply_Mdh(kc, &T13)
436                 | `std.Err e: -> `std.Err std.fmt("unapply_Mdh({}, μflip(T_Q)): {}", kc, e)
437                 | `std.Ok a: via_section_5 = a
438                 ;;
440                 std.put("Top (displayed α is coordinates for Left):\n")
441                 match display_seed_tori(kc, psi_02_alpha.0, psi_13_alpha.0, via_section_5.0, "flip")
442                 | `std.Err e: -> `std.Err e
443                 | `std.Ok void:
444                 ;;
446                 std.put("\nBottom (displayed α is coordinates for Right):\n")
447                 match display_seed_tori(kc, psi_02_alpha.1, psi_13_alpha.1, via_section_5.1, "flip")
448                 | `std.Err e: -> `std.Err e
449                 | `std.Ok void:
450                 ;;
452                 -> `std.Ok void
453         ;;
456 const display_seed_tori = {kc : KC_type, alpha : conf_3_star#, via_lusztig : conf_3_star#, via_section_5 : conf_3_star#, function_name : byte[:]
457         var rank : int = get_n(kc)
458         var w0 : weyl_reflection[:] = get_w0(kc)
459         var c : weyl_reflection[:] = [][:]
460         match get_coxeter_elt(kc)
461         | `std.Ok cc: c = cc
462         | `std.Err e: -> `std.Err std.fmt("get_coxeter_elt({}): {}", kc, e)
463         ;;
464         var all_good = true
465         var fake_label_1 = std.fmt("X_w{}(h3)", rank)
466         var fake_label_2 = std.fmt("D^y_{}(u)", w0.len)
467         var lw = std.max(fake_label_1.len, fake_label_2.len)
468         std.slfree(fake_label_1)
469         std.slfree(fake_label_2)
471         var cw = 9
472         for aa : [ alpha, via_lusztig, via_section_5 ][:]
473                 for hh : [ aa.h1, aa.h2, aa.h3 ][:]
474                         for var j = 0 ; j < hh.len; ++j
475                                 var temp = std.fmt("{}", hh[j].c)
476                                 cw = std.max(cw, temp.len)
477                                 std.slfree(temp)
478                         ;;
479                 ;;
480                 for var j = 0; j < aa.u.len; ++j
481                         var temp = std.fmt("{}", aa.u[j].c)
482                         cw = std.max(cw, temp.len)
483                         std.slfree(temp)
484                 ;;
485         ;;
487         var good_color = "\u{001b}[48;2;12;55;55m"
488         var bad_color = "\u{001b}[48;2;85;12;12m"
489         var end_color = "\u{001b}[0m"
491         std.put("+-{w=?,p=-}-+-{w=?,p=-}-+-{w=?,p=-}-+-{w=?,p=-}-+\n", "", lw, "", cw, "", cw, "", cw)
492         std.put("| {w=?} | {w=?}α{w=?} | {w=?}{}(α){w=?} |\n", "", lw, "", (cw-0)/2, "", (cw-1)/2, "", cw-2, function_name, "", cw + 2 - function_name.len)
493         std.put("| {w=?} | {w=?} | {w=?}Lusztig{w=?} | {w=?}Section 5{w=?} |\n", "", lw, "", cw, "", (cw-6)/2, "", (cw-7)/2, "", (cw-8)/2, "", (cw-9)/2)
494         std.put("+-{w=?,p=-}-+-{w=?,p=-}-+-{w=?,p=-}-+-{w=?,p=-}-+\n", "", lw, "", cw, "", cw, "", cw)
496         for (sn, ah, lh, s5h) : [
497                 ('₁', alpha.h1, via_lusztig.h1, via_section_5.h1),
498                 ('₂', alpha.h2, via_lusztig.h2, via_section_5.h2),
499                 ('₃', alpha.h3, via_lusztig.h3, via_section_5.h3),
500         ][:]
501                 for var j = 0; j < rank; j++
502                         var label = std.fmt("Δ^w{}(h{})", (c[j] : subscript), sn)
503                         var label_width = std.strcellwidth(label)
504                         var in_alpha = std.fmt("{}", ah[j].c)
505                         var in_lusztig = std.fmt("{}", lh[j].c)
506                         var in_section_5 = std.fmt("{}", s5h[j].c)
507                         var color = good_color
508                         if !std.eq(lh[j].c, s5h[j].c)
509                                 color = bad_color
510                                 all_good = false
511                         ;;
513                         std.put("| {}{w=?} | {w=?} |{} {w=?} {}|{} {w=?} {}|\n", label, "", lw - label_width, in_alpha, cw, color, in_lusztig, cw, end_color, color, in_section_5, cw, end_color)
514                         std.slfree(label)
515                         std.slfree(in_alpha)
516                         std.slfree(in_lusztig)
517                         std.slfree(in_section_5)
518                 ;;
519                 std.put("+-{w=?,p=-}-+-{w=?,p=-}-+-{w=?,p=-}-+-{w=?,p=-}-+\n", "", lw, "", cw, "", cw, "", cw)
520         ;;
522         for var j = 0; j < w0.len; ++j
523                 var label = std.fmt("Δ^γ{}(u)", (j + 1 : subscript))
524                 var label_width = std.strcellwidth(label)
525                 var in_alpha = std.fmt("{}", alpha.u[j].c)
526                 var in_lusztig = std.fmt("{}", via_lusztig.u[j].c)
527                 var in_section_5 = std.fmt("{}", via_section_5.u[j].c)
528                 var color = good_color
529                 if !std.eq(via_lusztig.u[j].c, via_section_5.u[j].c)
530                         color = bad_color
531                         all_good = false
532                 ;;
533                 std.put("| {}{w=?} | {w=?} |{} {w=?} {}|{} {w=?} {}|\n", label, "", lw - label_width, in_alpha, cw, color, in_lusztig, cw, end_color, color, in_section_5, cw, end_color)
534                 std.slfree(label)
535                 std.slfree(in_alpha)
536                 std.slfree(in_lusztig)
537                 std.slfree(in_section_5)
538         ;;
539         std.put("+-{w=?,p=-}-+-{w=?,p=-}-+-{w=?,p=-}-+-{w=?,p=-}-+\n", "", lw, "", cw, "", cw, "", cw)
540         if all_good
541                 std.put("\n    {}All ok{}\n\n", good_color, end_color)
542         else
543                 std.put("\n    {}There were mismatches{}\n\n", bad_color, end_color)
544         ;;
546         -> `std.Ok void
549 const assign_TQ_to_quiver = {kc : KC_type, TQ : T_Q#, q : quiver.quiver#
550         var rank = get_n(kc)
551         var l = coxeter_num(kc) / 2 - 1
553         for var i = 1; i <= rank; ++i
554                 var name = std.fmt("A{}", i)
555                 match quiver.find_vertex(q, name)
556                 | `std.Some(_, vp):
557                         match vp.acoord
558                         | `std.None:
559                         | `std.Some a:
560                                 __dispose__(a)
561                                 vp.acoord = `std.None
562                         ;;
563                         vp.acoord = `std.Some std.get(yakmo.polynomialfromratfunc(TQ.A[i]))
564                 | _:
565                 ;;
567                 name[0] = ('B' : byte)
568                 match quiver.find_vertex(q, name)
569                 | `std.Some(_, vp):
570                         match vp.acoord
571                         | `std.None:
572                         | `std.Some a:
573                                 __dispose__(a)
574                                 vp.acoord = `std.None
575                         ;;
576                         vp.acoord = `std.Some std.get(yakmo.polynomialfromratfunc(TQ.B[i]))
577                 | _:
578                 ;;
580                 name[0] = ('C' : byte)
581                 match quiver.find_vertex(q, name)
582                 | `std.Some(_, vp):
583                         match vp.acoord
584                         | `std.None:
585                         | `std.Some a:
586                                 __dispose__(a)
587                                 vp.acoord = `std.None
588                         ;;
589                         vp.acoord = `std.Some std.get(yakmo.polynomialfromratfunc(TQ.C[i]))
590                 | _:
591                 ;;
593                 std.slfree(name)
595                 for var j = 1; j <= l; ++j
596                         name = vname(i,j)
597                         match quiver.find_vertex(q, name)
598                         | `std.Some(_, vp):
599                                 match vp.acoord
600                                 | `std.None:
601                                 | `std.Some a:
602                                         __dispose__(a)
603                                         vp.acoord = `std.None
604                                 ;;
605                                 vp.acoord = `std.Some std.get(yakmo.polynomialfromratfunc(TQ.v[i][j]))
606                         | _:
607                         ;;
608                         std.slfree(name)
609                 ;;
610         ;;
613 const assign_quiver_to_TQ = {kc : KC_type, q : quiver.quiver#, TQ : T_Q#
614         var rank = get_n(kc)
615         var l = coxeter_num(kc) / 2 - 1
617         for var i = 1; i <= rank; ++i
618                 var name = std.fmt("A{}", i)
619                 match quiver.find_vertex(q, name)
620                 | `std.Some(_, vp):
621                         __dispose__(TQ.A[i])
622                         TQ.A[i] = yakmo.ratfuncfrompoly(std.get(vp.acoord))
623                 | _:
624                 ;;
626                 name[0] = ('B' : byte)
627                 match quiver.find_vertex(q, name)
628                 | `std.Some(_, vp):
629                         __dispose__(TQ.B[i])
630                         TQ.B[i] = yakmo.ratfuncfrompoly(std.get(vp.acoord))
631                 | _:
632                 ;;
634                 name[0] = ('C' : byte)
635                 match quiver.find_vertex(q, name)
636                 | `std.Some(_, vp):
637                         __dispose__(TQ.C[i])
638                         TQ.C[i] = yakmo.ratfuncfrompoly(std.get(vp.acoord))
639                 | _:
640                 ;;
642                 std.slfree(name)
644                 for var j = 1; j <= l; ++j
645                         name = vname(i,j)
646                         match quiver.find_vertex(q, name)
647                         | `std.Some(_, vp):
648                                 __dispose__(TQ.v[i][j])
649                                 TQ.v[i][j] = yakmo.ratfuncfrompoly(std.get(vp.acoord))
650                         | _:
651                         ;;
652                         std.slfree(name)
653                 ;;
654         ;;
657 const assign_TQ02_to_quiver = {kc : KC_type, TQ : T_Q02#, q : quiver.quiver#
658         var rank = get_n(kc)
659         var l = coxeter_num(kc) / 2 - 1
660         var L = 2 * l + 1
662         for var i = 1; i <= rank; ++i
663                 var name = std.fmt("X{}", i)
665                 for (letter, list) : [ ('D', TQ.D), ('E', TQ.E), ('F', TQ.F), ('G', TQ.G) ][:]
666                         name[0] = (letter : byte)
667                         match quiver.find_vertex(q, name)
668                         | `std.Some(_, vp):
669                                 match vp.acoord
670                                 | `std.None:
671                                 | `std.Some a:
672                                         __dispose__(a)
673                                         vp.acoord = `std.None
674                                 ;;
675                                 vp.acoord = `std.Some std.get(yakmo.polynomialfromratfunc(list[i]))
676                         | _:
677                         ;;
678                 ;;
680                 std.slfree(name)
682                 for var j = 1; j <= L; ++j
683                         name = wname(i,j)
685                         match quiver.find_vertex(q, name)
686                         | `std.Some(_, vp):
687                                 match vp.acoord
688                                 | `std.None:
689                                 | `std.Some a:
690                                         __dispose__(a)
691                                         vp.acoord = `std.None
692                                 ;;
693                                 vp.acoord = `std.Some std.get(yakmo.polynomialfromratfunc(TQ.w[i][j]))
694                         | _:
695                         ;;
697                         std.slfree(name)
698                 ;;
699         ;;
702 const assign_TQ13_to_quiver = {kc : KC_type, TQ : T_Q13#, q : quiver.quiver#
703         /*
704            Because of the way I've set up the quivers and apply_Md{h,v},
705            the naming should be so that
707                         apply_Mdv                      assign_TQ02_to_quiver
708              conf_4_star# ----> (conf_3_star#, conf_3_star#) -----> quiver
710                         apply_Mdh                      assign_TQ13_to_quiver
711              conf_4_star# ----> (conf_3_star#, conf_3_star#) -----> quiver
713            can use the exact same assignments as the second part:
714            assign_TQ{02,13}_to_quiver may be the same function. For
715            clarity, however, they're called separate names.
716          */
717         var TQ_as_02 = [
718                 .D = TQ.D,
719                 .E = TQ.E,
720                 .F = TQ.F,
721                 .G = TQ.G,
722                 .w = TQ.w
723         ]
724         -> assign_TQ02_to_quiver(kc, &TQ_as_02, q)
727 const assign_quiver_to_TQ02 = {kc : KC_type, q : quiver.quiver#, TQ : T_Q02#
728         var rank = get_n(kc)
729         var l = coxeter_num(kc) / 2 - 1
730         var L = 2 * l + 1
732         for var i = 1; i <= rank; ++i
733                 var name = std.fmt("X{}", i)
735                 for (letter, list) : [ ('D', TQ.D), ('E', TQ.E), ('F', TQ.F), ('G', TQ.G) ][:]
736                         name[0] = (letter : byte)
737                         match quiver.find_vertex(q, name)
738                         | `std.Some(_, vp):
739                                 __dispose__(list[i])
740                                 list[i] = yakmo.ratfuncfrompoly(std.get(vp.acoord))
741                         | _:
742                         ;;
743                 ;;
745                 std.slfree(name)
747                 for var j = 1; j <= L; ++j
748                         name = wname(i,j)
750                         match quiver.find_vertex(q, name)
751                         | `std.Some(_, vp):
752                                 __dispose__(TQ.w[i][j])
753                                 TQ.w[i][j] = yakmo.ratfuncfrompoly(std.get(vp.acoord))
754                         | _:
755                         ;;
757                         std.slfree(name)
758                 ;;
759         ;;
762 const assign_quiver_to_TQ13 = {kc : KC_type, q : quiver.quiver#, TQ : T_Q13#
763         /* See comment in assign_TQ13_to_quiver */
764         var TQ_as_02 : T_Q02 = [
765                 .D = TQ.D,
766                 .E = TQ.E,
767                 .F = TQ.F,
768                 .G = TQ.G,
769                 .w = TQ.w
770         ]
772         assign_quiver_to_TQ02(kc, q, &TQ_as_02)
774         /*
775            I may, someday, carelessly rewrite the above function so that
776            it clobbers the slices, perhaps through slgrow. So copy them
777            back.
778          */
779         TQ.D = TQ_as_02.D
780         TQ.E = TQ_as_02.E
781         TQ.F = TQ_as_02.F
782         TQ.G = TQ_as_02.G
783         TQ.w = TQ_as_02.w