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