1 /*
2 This is files.hpp
3
4 Coxeter version 3.0 Copyright (C) 2002 Fokko du Cloux
5 See file main.cpp for full copyright notice
6 */
7
8 #include "cells.h"
9
10 /****************************************************************************
11
12 This file contains the definition of the following function templates,
13 declared in files.hpp :
14
15 - appendCoefficient(str,c,traits) : append a polynomial-coefficient to str;
16 - appendHeckeMonomial(str,m,p,I,pTraits,hTraits,l) : appends a Hecke-
17 monomial to str;
18 - appendMonomial(str,c,e,traits,d,m) : appends a (possibly shifted)
19 monomial to str; part of appendPolynomial;
20 - appendMuMark(str,m,p,l,traits) : appends the marking for non-zero
21 mu-coefficients;
22 - appendPolynomial(str,p,traits,d,m) : appends a (possibly shifted)
23 polynomial to str;
24 - printAsBasisElt(file,h,p,I,G,traits) : prints the Hecke element
25 h, assumed to contain an element of the k-l basis, according to the
26 given output traits;
27 - printCoefficient(file,c,traits) : like appendCoefficient;
28 - printHeckeElt(file,h,p,I,a,hTraits,pTraits,l) : same as preceding one,
29 but data is sorted using the permutation a;
30 - printHeckeMonomial(file,m,p,I,pTraits,hTraits,l) : like
31 appendHeckeMonomial;
32 - printLCOrder(file,kl,I,G,traits) : outputs the left cell ordering as
33 an abstract poset;
34 - printLRCOrder(file,kl,I,G,traits) : outputs the two-sided cell
35 ordering as an abstract poset;
36 - printMonomial(file,c,e,traits,d,m) : like appendMonomial;
37 - printMuMark(file,m,p,l,traits) : like appendMuMark;
38 - printPolynomial(file,p,traits,d,m) : like appendPolynomial;
39 - printRCOrder(file,kl,I,G,traits) : outputs the right cell ordering as
40 an abstract poset;
41 - setTwoSided(h,p,I,a,hTraits,pTraits,l) : same as preceding one, with
42 the data in h permuted by a;
43
44 *****************************************************************************/
45
46 namespace files {
47
48 template <class C>
appendCoefficient(String & str,const C & c,PolynomialTraits & traits)49 void appendCoefficient(String& str, const C& c, PolynomialTraits& traits)
50
51 {
52 io::append(str,c);
53 return;
54 }
55
56 template <class E>
appendExponent(String & str,const E & e,PolynomialTraits & traits)57 void appendExponent(String& str, const E& e, PolynomialTraits& traits)
58
59 /*
60 Appends the exponent e*d+m according to the traits.
61 */
62
63 {
64 if (!traits.printExponent)
65 return;
66
67 io::append(str,traits.exponent);
68 io::append(str,traits.expPrefix);
69 io::append(str,static_cast<long>(e));
70 io::append(str,traits.expPostfix);
71
72 return;
73 }
74
75 template <class M>
appendHeckeMonomial(String & str,const M & m,const SchubertContext & p,const Interface & I,HeckeTraits & hTraits,PolynomialTraits & pTraits,const Length & l)76 void appendHeckeMonomial(String& str, const M& m, const SchubertContext& p,
77 const Interface& I, HeckeTraits& hTraits,
78 PolynomialTraits& pTraits, const Length& l)
79 {
80 using namespace klsupport;
81
82 typedef typename M::PolType P;
83 PolynomialType ptype = P::polType();
84 Length lx = p.length(m.x());
85
86 Ulong d = 1;
87 long q = 0;
88 String indeterminate = pTraits.indeterminate; // back up
89
90 if ((l != undef_length) && hTraits.doShift) { // set shift parameters
91 d = 2;
92 q = lx-l;
93 pTraits.indeterminate = pTraits.sqrtIndeterminate;
94 }
95
96 io::append(str,hTraits.monomialPrefix);
97
98 if (hTraits.reversePrint) {
99 appendPolynomial(str,m.pol(),pTraits,d,q);
100 io::append(str,hTraits.monomialSeparator);
101 p.append(str,m.x(),I);
102 }
103 else {
104 p.append(str,m.x(),I);
105 io::append(str,hTraits.monomialSeparator);
106 appendPolynomial(str,m.pol(),pTraits,d,q);
107 }
108
109 io::append(str,hTraits.monomialPostfix);
110
111 if ((ptype == KLPOL) && (l != undef_length))
112 appendMuMark(str,m,p,l,hTraits);
113
114 pTraits.indeterminate = indeterminate;
115
116 return;
117 }
118
119 template <class C>
appendMonomial(String & str,const C & c,const Ulong & e,PolynomialTraits & traits,const Ulong & d,const long & m)120 void appendMonomial(String& str, const C& c, const Ulong& e,
121 PolynomialTraits& traits, const Ulong& d,
122 const long& m)
123
124 /*
125 We append a monomial of the form c.q^{e*d+m}.
126 */
127
128 {
129 long e_s = e*d+m;
130
131 if (e_s == 0)
132 appendCoefficient(str,c,traits);
133 else {
134 if (c == 1)
135 io::append(str,traits.one);
136 else if (-c == 1)
137 io::append(str,traits.negOne);
138 else {
139 appendCoefficient(str,c,traits);
140 io::append(str,traits.product);
141 }
142 io::append(str,traits.indeterminate);
143 if (e_s != 1) {
144 appendExponent(str,e_s,traits);
145 }
146 }
147
148 return;
149 }
150
151 template <class M>
appendMuMark(String & str,const M & m,const SchubertContext & p,const Length & l,HeckeTraits & traits)152 void appendMuMark(String& str, const M& m, const SchubertContext& p,
153 const Length& l, HeckeTraits& traits)
154
155 /*
156 Appends a marker if the degree of the polynomial is as big as it can
157 be. Here l is the lenth of the y-element of the basis.
158 */
159
160 {
161 Length lx = p.length(m.x());
162
163 if (static_cast<long>(2*m.pol().deg()) == static_cast<long>(l-lx-1))
164 io::append(str,traits.muMark);
165
166 return;
167 }
168
169 template <class P>
appendPolynomial(String & str,const P & p,PolynomialTraits & traits,const Ulong & d,const long & m)170 void appendPolynomial(String& str, const P& p, PolynomialTraits& traits,
171 const Ulong& d, const long& m)
172
173 {
174 if (p.isZero()) {
175 io::append(str,traits.zeroPol);
176 return;
177 }
178
179 if (traits.printModifier)
180 appendModifier(str,d,m,traits);
181
182 io::append(str,traits.prefix);
183
184 bool firstTerm = true;
185
186 for (Ulong j = 0; j <= p.deg(); ++j) {
187 if (p[j] == 0)
188 continue;
189 if (firstTerm) // first term
190 firstTerm = false;
191 else { // append separator
192 if (p[j] > 0)
193 io::append(str,traits.posSeparator);
194 else
195 io::append(str,traits.negSeparator);
196 }
197 appendMonomial(str,p[j],j,traits,d,m);
198 }
199
200 io::append(str,traits.postfix);
201
202 return;
203 }
204
205 template <class KL>
makeWGraph(WGraph & X,const List<CoxNbr> & c,const LFlags & f,KL & kl)206 void makeWGraph(WGraph& X, const List<CoxNbr>& c, const LFlags& f, KL& kl)
207
208 /*
209 Puts in X the W-graph for the part of the context contained in c. The flags
210 in f are either all left, all right or all two-sided generators.
211 */
212
213 {
214 SubSet q(kl.size());
215
216 for (Ulong j = 0; j < c.size(); ++j)
217 q.add(c[j]);
218
219 if (!(f&1)) // left descents
220 cells::lWGraph(X,q,kl);
221 else if (!(f >> kl.rank())) // right descents
222 cells::rWGraph(X,q,kl);
223 else // two-sided descents
224 cells::lrWGraph(X,q,kl);
225
226 return;
227 }
228
229 template <class H>
printAsBasisElt(FILE * file,const H & h,const SchubertContext & p,Interface & I,OutputTraits & traits)230 void printAsBasisElt(FILE* file, const H& h, const SchubertContext& p,
231 Interface& I, OutputTraits& traits)
232
233 /*
234 This function prints one element of the k-l basis, according to the
235 given output traits.
236 */
237
238 {
239 // sorting of the element
240
241 typedef typename H::eltType::PolType P;
242 hecke::NFCompare<P> nfc(p,I.order());
243
244 // printing of the basis element proper
245
246 GroupEltInterface GI(I.outInterface());
247 I.setOut(*traits.addHeckeTraits.eltTraits);
248
249 HeckeTraits& hTraits = traits.addHeckeTraits;
250 PolynomialTraits& pTraits = traits.polTraits;
251
252 CoxNbr y = h[h.size()-1].x();
253
254 Permutation a(0);
255 sortI(h,nfc,a);
256
257 io::print(file,traits.prefix[basisH]);
258 printHeckeElt(file,h,a,p,I,hTraits,pTraits,p.length(y));
259 io::print(file,traits.postfix[basisH]);
260
261 io::print(file,"\n");
262
263 I.setOut(GI);
264
265 return;
266 }
267
268 template <class KL>
printClosure(FILE * file,const CoxNbr & y,KL & kl,const Interface & I,OutputTraits & traits)269 void printClosure(FILE* file, const CoxNbr& y, KL& kl, const Interface& I,
270 OutputTraits& traits)
271
272 /*
273 Assuming that h contains the extremal pairs for a given element y of
274 the group, and the corresponding k-l polynomials, this prints out all
275 the data : it combines coatoms, extremals, singular locus, singular
276 stratification, betti numbers and IH betti numbers.
277 */
278
279 {
280 const SchubertContext& p = kl.schubert();
281
282 // print out y and the descent sets
283
284 if (traits.printEltData) { // print data about y
285 printEltData(file,y,p,I,traits);
286 fprintf(file,"\n");
287 }
288
289 // print out the coatoms
290
291 if (traits.printCoatoms) {
292 printCoatoms(file,y,p,I,traits);
293 fprintf(file,"\n");
294 }
295
296 // print out the extremal pairs
297
298 io::print(file,traits.closureSeparator1);
299 printExtremals(file,y,kl,I,traits);
300
301 // print out the singular locus
302
303 kl::HeckeElt h(0);
304 genericSingularities(h,y,kl);
305
306 if (h.size() == 0) { // Schubert variety is smooth
307 io::print(file,traits.closureSeparator2);
308 io::print(file,traits.emptySingularLocus);
309 fprintf(file,"\n");
310 io::print(file,traits.emptySingularStratification);
311 fprintf(file,"\n");
312 }
313 else {
314 io::print(file,traits.closureSeparator3);
315 printSingularLocus(file,y,kl,I,traits);
316
317 // print out the singular stratification
318
319 io::print(file,traits.closureSeparator4);
320 printSingularStratification(file,y,kl,I,traits);
321 }
322
323 // print betti numbers
324
325 io::print(file,traits.closureSeparator5);
326 printBetti(file,y,p,traits);
327
328 // print IH betti numbers
329
330 io::print(file,traits.closureSeparator6);
331 printIHBetti(file,y,kl,traits);
332
333 return;
334 }
335
336 template <class C>
printCoefficient(FILE * file,const C & c,PolynomialTraits & traits)337 void printCoefficient(FILE* file, const C& c, PolynomialTraits& traits)
338
339 {
340 fprintf(file,"%ld",static_cast<long>(c));
341 return;
342 }
343
344 template <class KL>
printDuflo(FILE * file,const List<CoxNbr> & dl,const Partition & pi,KL & kl,const Interface & I,OutputTraits & traits)345 void printDuflo(FILE* file, const List<CoxNbr>& dl, const Partition& pi,
346 KL& kl, const Interface& I, OutputTraits& traits)
347
348 /*
349 This function prints out the Duflo involutions on the file. The list
350 d is the list of Duflo involutions; the partition pi is the partition
351 of the group into left cells. We print out the Duflo involutions in
352 the usual ordering in which we print out the left cells, viz. order
353 the cells by shortlex ordering of their shortlex-smallest elements.
354 */
355
356 {
357 const SchubertContext& p = kl.schubert();
358
359 // print duflo involutions
360
361 List<CoxNbr> min(0);
362 schubert::NFCompare nfc(p,I.order());
363 minReps(min,pi,nfc);
364 Permutation a(0);
365 sortI(min,nfc,a);
366
367 int d = digits(dl.size()-1,10);
368
369 io::print(file,traits.prefix[dufloH]);
370 io::print(file,traits.dufloListPrefix);
371
372 for (Ulong j = 0; j < dl.size(); ++j) {
373 if (traits.printDufloNumber) {
374 io::print(file,traits.dufloNumberPrefix);
375 fprintf(file,"%*lu",d,j);
376 io::print(file,traits.dufloNumberPostfix);
377 }
378 const kl::KLPol& pol = kl.klPol(0,dl[a[j]]);
379 io::print(file,traits.dufloPrefix);
380 p.print(file,dl[a[j]],I);
381 io::print(file,traits.dufloSeparator);
382 printPolynomial(file,pol,traits.polTraits);
383 io::print(file,traits.dufloPostfix);
384 if (j+1 < dl.size()) // there is more to come
385 io::print(file,traits.dufloListSeparator);
386 }
387
388 io::print(file,traits.dufloListPostfix);
389 io::print(file,traits.postfix[dufloH]);
390 fprintf(file,"\n");
391
392 return;
393 }
394
395 template <class E>
printExponent(FILE * file,const E & e,PolynomialTraits & traits)396 void printExponent(FILE* file, const E& e, PolynomialTraits& traits)
397
398 /*
399 Prints the exponent d*e+m to the file.
400 */
401
402 {
403 if (!traits.printExponent)
404 return;
405
406 io::print(file,traits.exponent);
407 io::print(file,traits.expPrefix);
408 fprintf(file,"%ld",static_cast<long>(e));
409 io::print(file,traits.expPostfix);
410
411 return;
412 }
413
414 template <class KL>
printExtremals(FILE * file,const CoxNbr & y,KL & kl,const Interface & I,OutputTraits & traits)415 void printExtremals(FILE* file, const CoxNbr& y, KL& kl, const Interface& I,
416 OutputTraits& traits)
417
418 {
419 kl::HeckeElt h(0);
420
421 kl.row(h,y);
422 if (ERRNO) {
423 Error(ERRNO);
424 return;
425 }
426
427 const SchubertContext& p = kl.schubert();
428 Length ly = p.length(y);
429
430 io::print(file,traits.prefix[extremalsH]);
431 printHeckeElt(file,h,p,I,traits,ly);
432 io::print(file,traits.postfix[extremalsH]);
433 fprintf(file,"\n");
434
435 return;
436 }
437
438 template <class H>
printHeckeElt(FILE * file,const H & h,const SchubertContext & p,const Interface & I,OutputTraits & traits,const Length & l)439 void printHeckeElt(FILE* file, const H& h, const SchubertContext& p,
440 const Interface& I, OutputTraits& traits, const Length& l)
441
442 /*
443 Does the printing of the sorted Hecke algebra element.
444 */
445
446 {
447 typedef typename H::eltType::PolType P;
448 hecke::NFCompare<P> nfc(p,I.order());
449
450 Permutation a(0);
451 sortI(h,nfc,a);
452
453 printHeckeElt(file,h,a,p,I,traits.heckeTraits,traits.polTraits,l);
454
455 return;
456 }
457
458 template <class H>
printHeckeElt(FILE * file,const H & h,const Permutation & a,const SchubertContext & p,const Interface & I,HeckeTraits & hTraits,PolynomialTraits & pTraits,const Length & l)459 void printHeckeElt(FILE* file, const H& h, const Permutation& a,
460 const SchubertContext& p, const Interface& I,
461 HeckeTraits& hTraits,
462 PolynomialTraits& pTraits, const Length& l)
463 /*
464 Prints out the Hecke algebra element h, permuted according to the
465 permutation a, following the given traits.
466 */
467
468 {
469 String buf(0);
470
471 bool oldTS = setTwoSided(h,a,p,I,hTraits,pTraits,l);
472
473 io::print(file,hTraits.prefix);
474
475 for (Ulong j = 0; j < h.size(); ++j) {
476 appendHeckeMonomial(buf,h[a[j]],p,I,hTraits,pTraits,l);
477 if (j < h.size()-1) // there is more to come
478 appendSeparator(buf,j,hTraits);
479 pad(buf,j,hTraits);
480 if (hTraits.lineSize)
481 foldLine(file,buf,hTraits.lineSize,hTraits.indent,hTraits.hyphens.ptr());
482 else
483 io::print(file,buf);
484 reset(buf);
485 }
486
487 io::print(file,hTraits.postfix);
488
489 hTraits.twoSided = oldTS;
490
491 return;
492 }
493
494 template <class KL>
printIHBetti(FILE * file,const CoxNbr & y,KL & kl,OutputTraits & traits)495 void printIHBetti(FILE* file, const CoxNbr& y, KL& kl, OutputTraits& traits)
496
497 {
498 Homology h(0);
499 ihBetti(h,y,kl);
500
501 io::print(file,traits.prefix[ihBettiH]);
502 printHomology(file,h,traits);
503 io::print(file,traits.postfix[ihBettiH]);
504 fprintf(file,"\n");
505
506 return;
507 }
508
509 template <class KL>
printLCOrder(FILE * file,KL & kl,const Interface & I,OutputTraits & traits)510 void printLCOrder(FILE* file, KL& kl, const Interface& I, OutputTraits& traits)
511
512 {
513 // make graph
514
515 OrientedGraph X(0);
516 cells::lGraph(X,kl);
517
518 // printout data
519
520 io::print(file,traits.prefix[lCOrderH]);
521 printCellOrder(file,X,kl.schubert(),I,traits.posetTraits);
522 io::print(file,traits.postfix[lCOrderH]);
523 io::print(file,"\n");
524
525 return;
526 }
527
528 template <class KL>
printLCells(FILE * file,const Partition & lp,KL & kl,const Interface & I,OutputTraits & traits)529 void printLCells(FILE* file, const Partition& lp, KL& kl, const Interface& I,
530 OutputTraits& traits)
531
532 {
533 // print out cells
534
535 io::print(file,traits.prefix[lCellsH]);
536 printPartition(file,lp,kl.schubert(),I,traits.partitionTraits);
537 io::print(file,traits.postfix[lCellsH]);
538 io::print(file,"\n");
539
540 return;
541
542 }
543
544 template <class KL>
printLCellWGraphs(FILE * file,const Partition & lp,KL & kl,const Interface & I,OutputTraits & traits)545 void printLCellWGraphs(FILE* file, const Partition& lp, KL& kl,
546 const Interface& I, OutputTraits& traits)
547
548 {
549 // set flag parameter
550
551 LFlags f = leqmask[kl.rank()-1] << kl.rank();
552
553 // print W-graphs
554
555 io::print(file,traits.prefix[lCellWGraphsH]);
556 printWGraphList(file,lp,f,kl,I,traits);
557 io::print(file,traits.postfix[lCellWGraphsH]);
558 fprintf(file,"\n");
559
560 return;
561 }
562
563 template <class KL>
printLRCOrder(FILE * file,KL & kl,const Interface & I,OutputTraits & traits)564 void printLRCOrder(FILE* file, KL& kl, const Interface& I,
565 OutputTraits& traits)
566
567 {
568 // make graph
569
570 OrientedGraph X(0);
571 cells::lrGraph(X,kl);
572
573 // printout data
574
575 io::print(file,traits.prefix[lrCOrderH]);
576 printCellOrder(file,X,kl.schubert(),I,traits.posetTraits);
577 io::print(file,traits.postfix[lrCOrderH]);
578 io::print(file,"\n");
579
580 return;
581 }
582
583 template <class KL>
printLRCells(FILE * file,const Partition & lp,KL & kl,const Interface & I,OutputTraits & traits)584 void printLRCells(FILE* file, const Partition& lp, KL& kl, const Interface& I,
585 OutputTraits& traits)
586
587 {
588 // print out cells
589
590 io::print(file,traits.prefix[lrCellsH]);
591 printPartition(file,lp,kl.schubert(),I,traits.partitionTraits);
592 io::print(file,traits.postfix[lrCellsH]);
593 io::print(file,"\n");
594
595 return;
596
597 }
598
599 template <class KL>
printLRCellWGraphs(FILE * file,const Partition & lp,KL & kl,const Interface & I,OutputTraits & traits)600 void printLRCellWGraphs(FILE* file, const Partition& lp, KL& kl,
601 const Interface& I, OutputTraits& traits)
602
603 {
604 // set flag parameter
605
606 LFlags f = leqmask[2*kl.rank()-1];
607
608 // print graphs
609
610 io::print(file,traits.prefix[lrCellWGraphsH]);
611 printWGraphList(file,lp,f,kl,I,traits);
612 io::print(file,traits.postfix[lrCellWGraphsH]);
613 fprintf(file,"\n");
614
615 return;
616 }
617
618 template <class KL>
printLRWGraph(FILE * file,KL & kl,const Interface & I,OutputTraits & traits)619 void printLRWGraph(FILE* file, KL& kl, const Interface& I,
620 OutputTraits& traits)
621
622 /*
623 This function prints out the W-graph data for the full context; the
624 output contains only the edges of the graph which lie within the
625 current context, but it is guaranteed to contain all those edges.
626 */
627
628 {
629 // print element list
630
631 int d = digits(kl.size()-1,10);
632
633 io::print(file,traits.eltList);
634 io::print(file,traits.eltListPrefix);
635
636 for (Ulong j = 0; j < kl.size(); ++j) {
637 if (traits.printEltNumber) {
638 io::print(file,traits.eltNumberPrefix);
639 fprintf(file,"%*lu",d,j);
640 io::print(file,traits.eltNumberPostfix);
641 }
642 kl.schubert().print(file,j,I);
643 if (j+1 < kl.size()) // there is more to come
644 io::print(file,traits.eltListSeparator);
645 }
646
647 io::print(file,traits.eltListPostfix);
648 io::print(file,traits.closeString);
649 fprintf(file,"\n");
650
651 // print graph
652
653 io::print(file,traits.prefix[lrWGraphH]);
654
655 WGraph X(0);
656 cells::lrWGraph(X,kl);
657 LFlags f = leqmask[2*kl.rank()-1];
658 printWGraph(file,X,f,I,traits.wgraphTraits);
659
660 io::print(file,traits.postfix[lrWGraphH]);
661
662 fprintf(file,"\n");
663
664 return;
665 }
666
667 template <class KL>
printLWGraph(FILE * file,KL & kl,const Interface & I,OutputTraits & traits)668 void printLWGraph(FILE* file, KL& kl, const Interface& I,
669 OutputTraits& traits)
670
671 /*
672 This function prints out the W-graph data for the full context; the
673 output contains only the edges of the graph which lie within the
674 current context, but it is guaranteed to contain all those edges.
675 */
676
677 {
678 // print element list
679
680 int d = digits(kl.size()-1,10);
681
682 io::print(file,traits.eltList);
683 io::print(file,traits.eltListPrefix);
684
685 for (Ulong j = 0; j < kl.size(); ++j) {
686 if (traits.printEltNumber) {
687 io::print(file,traits.eltNumberPrefix);
688 fprintf(file,"%*lu",d,j);
689 io::print(file,traits.eltNumberPostfix);
690 }
691 kl.schubert().print(file,j,I);
692 if (j+1 < kl.size()) // there is more to come
693 io::print(file,traits.eltListSeparator);
694 }
695
696 io::print(file,traits.eltListPostfix);
697 io::print(file,traits.closeString);
698 fprintf(file,"\n");
699
700 // print graph
701
702 io::print(file,traits.prefix[lWGraphH]);
703
704 WGraph X(0);
705 cells::lWGraph(X,kl);
706 LFlags f = leqmask[kl.rank()-1] << kl.rank();
707 printWGraph(file,X,f,I,traits.wgraphTraits);
708
709 io::print(file,traits.postfix[lWGraphH]);
710
711 fprintf(file,"\n");
712
713 return;
714 }
715
716 template <class C>
printMonomial(FILE * file,const C & c,const Ulong & e,PolynomialTraits & traits,const Ulong & d,const long & m)717 void printMonomial(FILE* file, const C& c, const Ulong& e,
718 PolynomialTraits& traits, const Ulong& d,
719 const long& m)
720
721 /*
722 We print a monomial of the form c.q^e, where it is guaranteed that c is
723 > 0. It is assumed that c can be printed out as a long integer; this
724 should probably also be a parameter.
725 */
726 {
727 long e_s = e*d+m;
728
729 if (e_s == 0)
730 printCoefficient(file,c,traits);
731 else {
732 if (c == 1)
733 io::print(file,traits.one);
734 else if (-c == 1)
735 io::print(file,traits.negOne);
736 else {
737 printCoefficient(file,c,traits);
738 io::print(file,traits.product);
739 }
740 io::print(file,traits.indeterminate);
741 if (e_s != 1) {
742 printExponent(file,e_s,traits);
743 }
744 }
745
746 return;
747 }
748
749 template <class M>
printMuMark(FILE * file,const M & m,const SchubertContext & p,const Length & l,HeckeTraits & traits)750 void printMuMark(FILE* file, const M& m, const SchubertContext& p,
751 const Length& l, HeckeTraits& traits)
752
753 /*
754 Prints a marker if the degree of the polynomial is as big as it can
755 be. Here l is the length of the y-element of the basis.
756 */
757
758 {
759 Length lx = p.length(m.x());
760
761 if (static_cast<long>(2*m.pol().deg()) == static_cast<long>(l-lx-1))
762 io::print(file,traits.muMark);
763
764 return;
765 }
766
767 template <class P>
printPolynomial(FILE * file,const P & p,PolynomialTraits & traits,const Ulong & d,const long & m)768 void printPolynomial(FILE* file, const P& p, PolynomialTraits& traits,
769 const Ulong& d, const long& m)
770
771 {
772 if (p.isZero()) {
773 io::print(file,traits.zeroPol);
774 return;
775 }
776
777 if (traits.printModifier)
778 printModifier(file,d,m,traits);
779
780 io::print(file,traits.prefix);
781
782 bool firstTerm = true;
783
784 for (Ulong j = 0; j <= p.deg(); ++j) {
785 if (p[j] == 0)
786 continue;
787 if (firstTerm) // first term
788 firstTerm = false;
789 else { // print separator
790 if (p[j] > 0)
791 io::print(file,traits.posSeparator);
792 else
793 io::print(file,traits.negSeparator);
794 }
795 printMonomial(file,p[j],j,traits,d,m);
796 }
797
798 io::print(file,traits.postfix);
799
800 return;
801 }
802
803 template <class KL>
printRCOrder(FILE * file,KL & kl,const Interface & I,OutputTraits & traits)804 void printRCOrder(FILE* file, KL& kl, const Interface& I, OutputTraits& traits)
805
806 {
807 // make graph
808
809 OrientedGraph X(0);
810 cells::rGraph(X,kl);
811
812 // printout data
813
814 io::print(file,traits.prefix[rCOrderH]);
815 printCellOrder(file,X,kl.schubert(),I,traits.posetTraits);
816 io::print(file,traits.postfix[rCOrderH]);
817 io::print(file,"\n");
818
819 return;
820 }
821
822 template <class KL>
printRCells(FILE * file,const Partition & lp,KL & kl,const Interface & I,OutputTraits & traits)823 void printRCells(FILE* file, const Partition& lp, KL& kl, const Interface& I,
824 OutputTraits& traits)
825
826 {
827 // print out cells
828
829 io::print(file,traits.prefix[rCellsH]);
830 printPartition(file,lp,kl.schubert(),I,traits.partitionTraits);
831 io::print(file,traits.postfix[rCellsH]);
832 io::print(file,"\n");
833
834 return;
835
836 }
837
838 template <class KL>
printRCellWGraphs(FILE * file,const Partition & lp,KL & kl,const Interface & I,OutputTraits & traits)839 void printRCellWGraphs(FILE* file, const Partition& lp, KL& kl,
840 const Interface& I, OutputTraits& traits)
841
842 {
843 LFlags f = leqmask[kl.rank()-1];
844
845 io::print(file,traits.prefix[rCellWGraphsH]);
846 printWGraphList(file,lp,f,kl,I,traits);
847 io::print(file,traits.postfix[rCellWGraphsH]);
848 fprintf(file,"\n");
849
850 return;
851 }
852
853 template <class KL>
printRWGraph(FILE * file,KL & kl,const Interface & I,OutputTraits & traits)854 void printRWGraph(FILE* file, KL& kl, const Interface& I,
855 OutputTraits& traits)
856
857 /*
858 This function prints out the W-graph data for the full context; the
859 output contains only the edges of the graph which lie within the
860 current context, but it is guaranteed to contain all those edges.
861 */
862
863 {
864 // print element list
865
866 int d = digits(kl.size()-1,10);
867
868 io::print(file,traits.eltList);
869 io::print(file,traits.eltListPrefix);
870
871 for (Ulong j = 0; j < kl.size(); ++j) {
872 if (traits.printEltNumber) {
873 io::print(file,traits.eltNumberPrefix);
874 fprintf(file,"%*lu",d,j);
875 io::print(file,traits.eltNumberPostfix);
876 }
877 kl.schubert().print(file,j,I);
878 if (j+1 < kl.size()) // there is more to come
879 io::print(file,traits.eltListSeparator);
880 }
881
882 io::print(file,traits.eltListPostfix);
883 io::print(file,traits.closeString);
884 fprintf(file,"\n");
885
886 // print graph
887
888 io::print(file,traits.prefix[rWGraphH]);
889
890 WGraph X(0);
891 cells::rWGraph(X,kl);
892 LFlags f = leqmask[kl.rank()-1];
893 printWGraph(file,X,f,I,traits.wgraphTraits);
894
895 io::print(file,traits.postfix[rWGraphH]);
896
897 fprintf(file,"\n");
898
899 return;
900 }
901
902 template <class KL>
printSingularLocus(FILE * file,const CoxNbr & y,KL & kl,const Interface & I,OutputTraits & traits)903 void printSingularLocus(FILE* file, const CoxNbr& y, KL& kl,
904 const Interface& I, OutputTraits& traits)
905
906 {
907 const SchubertContext& p = kl.schubert();
908
909 kl::HeckeElt hs(0);
910 genericSingularities(hs,y,kl);
911
912 if (hs.size() == 0) { // singular locus is empty
913 io::print(file,traits.emptySingularLocus);
914 fprintf(file,"\n");
915 return;
916 }
917
918 Length ly = p.length(y);
919
920 io::print(file,traits.prefix[slocusH]);
921 printHeckeElt(file,hs,p,I,traits,ly);
922 io::print(file,traits.postfix[slocusH]);
923 fprintf(file,"\n");
924 if (traits.printCompCount) {
925 io::print(file,traits.compCountPrefix);
926 fprintf(file,"%lu",hs.size());
927 io::print(file,traits.compCountPostfix);
928 io::print(file,traits.closeString);
929 fprintf(file,"\n");
930 }
931
932 return;
933 }
934
935 template <class KL>
printSingularStratification(FILE * file,const CoxNbr & y,KL & kl,const Interface & I,OutputTraits & traits)936 void printSingularStratification(FILE* file, const CoxNbr& y, KL& kl,
937 const Interface& I, OutputTraits& traits)
938
939 {
940 const SchubertContext& p = kl.schubert();
941
942 kl::HeckeElt h(0);
943 kl.row(h,y);
944 if (ERRNO) {
945 Error(ERRNO);
946 return;
947 }
948 kl::HeckeElt hs(0);
949 hecke::singularStratification(hs,h,p);
950
951 if (hs.size() == 0) { // singular locus is empty
952 io::print(file,traits.emptySingularStratification);
953 fprintf(file,"\n");
954 return;
955 }
956
957 Length ly = p.length(y);
958
959 io::print(file,traits.prefix[sstratificationH]);
960 printHeckeElt(file,hs,p,I,traits,ly);
961 io::print(file,traits.postfix[sstratificationH]);
962 fprintf(file,"\n");
963 if (traits.printCompCount) {
964 io::print(file,traits.compCountPrefix);
965 fprintf(file,"%lu",hs.size());
966 io::print(file,traits.compCountPostfix);
967 io::print(file,traits.closeString);
968 fprintf(file,"\n");
969 }
970
971 return;
972 }
973
974 template <class KL>
printWGraphList(FILE * file,const Partition & pi,const LFlags & f,KL & kl,const Interface & I,OutputTraits & traits)975 void printWGraphList(FILE* file, const Partition& pi, const LFlags& f, KL& kl,
976 const Interface& I, OutputTraits& traits)
977
978 /*
979 This function prints out the W-graphs of the classes of the partition pi.
980 The bitset f flags either all left, all right or all generators; it is
981 assumed that the classes of f are actually W-graphs (they could for
982 instance be intervals in the poset of cells).
983
984 The order of the cells, ant the ordering within each cell, are as for
985 printPartition.
986 */
987
988 {
989 const SchubertContext& p = kl.schubert();
990
991 // write out cells
992
993 List<List<CoxNbr> > lc(0);
994 writeClasses(lc,pi);
995
996 // sort cells
997
998 schubert::NFCompare nfc(p,I.order());
999 Permutation a(0);
1000 sortLists(lc,nfc,a);
1001
1002 int d = digits(lc.size()-1,10);
1003 WgraphTraits& wTraits = traits.wgraphTraits;
1004 Ulong oldPadSize = wTraits.padSize;
1005 wTraits.padSize = d + traits.cellNumberPrefix.length() +
1006 traits.cellNumberPostfix.length();
1007
1008 // print out graphs
1009
1010 io::print(file,traits.graphListPrefix);
1011
1012 for (Ulong j = 0; j < lc.size(); ++j) {
1013 if (traits.printCellNumber) {
1014 io::print(file,traits.cellNumberPrefix);
1015 fprintf(file,"%*lu",d,j);
1016 io::print(file,traits.cellNumberPostfix);
1017 }
1018 WGraph X(0);
1019 makeWGraph(X,lc[a[j]],f,kl);
1020 printWGraph(file,X,f,I,wTraits);
1021 if (j+1 < lc.size())
1022 io::print(file,traits.graphListSeparator);
1023 }
1024
1025 io::print(file,traits.graphListPostfix);
1026
1027 wTraits.padSize = oldPadSize;
1028
1029 return;
1030 }
1031
1032 template <class H>
setTwoSided(const H & h,const Permutation & a,const SchubertContext & p,const Interface & I,HeckeTraits & hTraits,PolynomialTraits & pTraits,const Length & l)1033 bool setTwoSided(const H& h, const Permutation& a, const SchubertContext& p,
1034 const Interface& I, HeckeTraits& hTraits,
1035 PolynomialTraits& pTraits, const Length& l)
1036
1037 /*
1038 This function decides between one- and two-sided output. Currently it is
1039 used only in pretty mode. It works by setting the value of *traits.twoSided
1040 to 0 or 1.
1041
1042 What the function does is go through the list of entries in h, and check
1043 if each entry fits in the odd- or even width set by the traits. If yes,
1044 we do a two-sided printout.
1045
1046 Return value is the previous value of *traits.twoSided, so that it can
1047 be restored afterward.
1048 */
1049
1050 {
1051 if (!hTraits.twoSided) // never do twosided output
1052 return false;
1053
1054 // if we get here, *traits.twoSided is true
1055
1056 String buf(0);
1057
1058 for (Ulong j = 0; j < h.size(); ++j) {
1059 appendHeckeMonomial(buf,h[a[j]],p,I,hTraits,pTraits,l);
1060 if (j < h.size()-1) // there is more to come
1061 appendSeparator(buf,j,hTraits);
1062 if (j%2 && hTraits.oddWidth) { // look at odd side
1063 if (buf.length() >= hTraits.oddWidth) { // not fit or fit tight
1064 hTraits.twoSided = false;
1065 break;
1066 }
1067 }
1068 if (!(j%2) && hTraits.evenWidth) { // look at even side
1069 if (buf.length() >= hTraits.evenWidth) { // not fit or fit tight
1070 hTraits.twoSided = false;
1071 break;
1072 }
1073 }
1074 reset(buf);
1075 }
1076
1077 return true;
1078 }
1079
1080 };
1081