1 /*
2   This is commands.cpp
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 "commands.h"
9 
10 #include "directories.h"
11 #include "error.h"
12 #include "fcoxgroup.h"
13 #include "help.h"
14 #include "interactive.h"
15 #include "special.h"
16 #include "typeA.h"
17 
18 namespace commands {
19   using namespace directories;
20   using namespace error;
21   using namespace fcoxgroup;
22   using namespace help;
23   using namespace interactive;
24 };
25 
26 namespace {
27 
28   using namespace commands;
29   using namespace stack;
30 
31   bool wgraph_warning = true;
32 
33   /* used in the definition of command trees */
34 
35   struct Empty_tag {};
36   struct Interface_tag {};
37   struct Main_tag {};
38   struct Uneq_tag {};
39 
40   Stack<CommandTree *> treeStack;
41   CoxGroup* W = 0;
42 
43   void activate(CommandTree* tree);
44   void ambigAction(CommandTree* tree, const String& str);
45   CommandData* ambigCommand();
46   void cellCompletion(DictCell<CommandData>* cell);
47   void commandCompletion(DictCell<CommandData>* cell);
48   void empty_error(char* str);
49   CommandTree* emptyCommandTree();
50   template<class C> CommandTree* initCommandTree();
51   void printCommandTree(FILE* file, DictCell<CommandData>* cell);
52   void startup();
53 
54   void interface_entry();
55   void interface_exit();
56 
57   void main_entry();
58   void main_exit();
59 
60   void uneq_entry();
61   void uneq_exit();
62 
63   void author_f();
64   void betti_f();
65   void coatoms_f();
66   void compute_f();
67   void descent_f();
68   void duflo_f();
69   void extremals_f();
70   void fullcontext_f();
71   void help_f();
72   void ihbetti_f();
73   void inorder_f();
74   void interface_f();
75   void interval_f();
76   void invpol_f();
77   void klbasis_f();
78   void lcorder_f();
79   void lcells_f();
80   void lcwgraphs_f();
81   void lrcorder_f();
82   void lrcells_f();
83   void lrcwgraphs_f();
84   void lrwgraph_f();
85   void lwgraph_f();
86   void matrix_f();
87   void mu_f();
88   void not_implemented_f();
89   void pol_f();
90   void q_f();
91   void qq_f();
92   void rank_f();
93   void rcorder_f();
94   void rcells_f();
95   void rcwgraphs_f();
96   void rwgraph_f();
97   void schubert_f();
98   void show_f();
99   void showmu_f();
100   void slocus_f();
101   void sstratification_f();
102   void type_f();
103   void uneq_f();
104 
105   const char* author_tag = "prints a message about the author";
106   const char* betti_tag = "prints the ordinary betti numbers";
107   const char* coatoms_tag = "prints out the coatoms of an element";
108   const char* compute_tag = "prints out the normal form of an element";
109   const char* descent_tag = "prints out the descent sets";
110   const char* duflo_tag = "prints out the Duflo involutions";
111   const char* extremals_tag =
112     "prints out the k-l polynomials for the extremal pairs";
113   const char* fullcontext_tag = "sets the context to the full group";
114   const char* help_tag = "enters help mode";
115   const char* ihbetti_tag = "prints the IH betti numbers";
116   const char* input_tag = "(in help mode only) explains the input conventions";
117   const char* interface_tag = "changes the interface";
118   const char* interval_tag = "prints an interval in the Bruhat ordering";
119   const char* intro_tag =
120     "(in help mode only) prints a message for first time users";
121   const char* inorder_tag = "tells whether two elements are in Bruhat order";
122   const char* invpol_tag = "prints a single inverse k-l polynomial";
123   const char* klbasis_tag = "prints an element of the k-l basis";
124   const char* lcorder_tag = "prints the left cell order";
125   const char* lcells_tag = "prints out the left k-l cells";
126   const char* lcwgraphs_tag = "prints out the W-graphs of the left k-l cells";
127   const char* lrcorder_tag = "prints the two-sided cell order";
128   const char* lrcells_tag = "prints out the tow-sided k-l cells";
129   const char* lrcwgraphs_tag =
130     "prints out the W-graphs of the two-sided k-l cells";
131   const char* lrwgraph_tag = "prints out the two-sided W-graph";
132   const char* lwgraph_tag = "prints out the left W-graph";
133   const char* matrix_tag = "prints the current Coxeter matrix";
134   const char* mu_tag = "prints a single mu-coefficient";
135   const char* pol_tag = "prints a single k-l polynomial";
136   const char* q_tag = "exits the current mode";
137   const char* qq_tag = "exits the program";
138   const char* rank_tag = "resets the rank";
139   const char* rcorder_tag = "prints the right cell order";
140   const char* rcells_tag = "prints out the right k-l cells";
141   const char* rcwgraphs_tag = "prints out the W-graphs of the right k-l cells";
142   const char* rwgraph_tag = "prints out the right W-graph";
143   const char* schubert_tag = "prints out the kl data for a schubert variety";
144   const char* show_tag = "maps out the computation of a k-l polynomial";
145   const char* showmu_tag = "maps out the computation of a mu coefficient";
146   const char* slocus_tag =
147     "prints the rational singular locus of the Schubert variety";
148   const char* sstratification_tag =
149     "prints the rational singular stratification of the Schubert variety";
150   const char* type_tag =
151     "resets the type and rank (hence restarts the program)";
152   const char* uneq_tag = "puts the program in unequal-parameter mode";
153 
154   namespace uneq {
155     void klbasis_f();
156     void lcorder_f();
157     void lrcorder_f();
158     void lcells_f();
159     void lrcells_f();
160     void mu_f();
161     void pol_f();
162     void rcells_f();
163     void rcorder_f();
164 
165     const char* lcorder_tag = "prints the left cell order";
166     const char* lrcorder_tag = "prints the two-sided cell order";
167     const char* lcells_tag = "prints out the left k-l cells";
168     const char* lrcells_tag = "prints out the two-sided k-l cells";
169     const char* mu_tag = "prints out a mu-coefficient";
170     const char* pol_tag = "prints out a single k-l polynomial";
171     const char* rcells_tag = "prints out the right k-l cells";
172     const char* rcorder_tag = "prints the right cell order";
173   };
174 };
175 
176 namespace commands {
177   void (*default_help)() = &help::default_h;
178 };
179 
180 namespace commands {
181 
182   namespace interface {
183 
184     GroupEltInterface* in_buf = 0;
185 
186     struct In_tag {};
187     struct Out_tag {};
188 
189     void in_entry();
190     void in_exit();
191     void out_entry();
192     void out_exit();
193 
194     void abort_f();
195     void alphabetic_f();
196     void bourbaki_f();
197     void default_f();
198     void decimal_f();
199     void gap_f();
200     void hexadecimal_f();
201     void in_f();
202     void out_f();
203     void permutation_f();
204     void symbol_f();
205     void terse_f();
206     void ordering_f();
207 
208     const char* abort_tag = "leaves without modifying the interface";
209     const char* alphabetic_tag = "sets alphabetic generator symbols";
210     const char* bourbaki_tag = "sets Bourbaki conventions for i/o";
211     const char* decimal_tag = "sets decimal generator symbols";
212     const char* default_tag = "sets i/o to default mode";
213     const char* gap_tag = "sets i/o to GAP mode";
214     const char* hexadecimal_tag = "sets hexadecimal generator symbols";
215     const char* in_tag = "enters reset-input mode";
216     const char* out_tag = "enters reset-output mode";
217     const char* permutation_tag =
218       "sets permutation notation for i/o (in type A only)";
219     const char* ordering_tag = "modifies the ordering of the generators";
220     const char* terse_tag = "sets i/o to terse mode";
221 
222     namespace in {
223       void alphabetic_f();
224       void bourbaki_f();
225       void decimal_f();
226       void default_f();
227       void gap_f();
228       void hexadecimal_f();
229       void permutation_f();
230       void postfix_f();
231       void prefix_f();
232       void separator_f();
233       void terse_f();
234       const char* alphabetic_tag =
235         "sets alphabetic generator symbols for input";
236       const char* bourbaki_tag = "sets Bourbaki conventions for input";
237       const char* decimal_tag = "sets decimal generator symbols for input";
238       const char* default_tag = "sets default conventions for input";
239       const char* gap_tag = "sets GAP conventions for input";
240       const char* hexadecimal_tag =
241         "sets hexadecimal generator symbols for input";
242       const char* permutation_tag =
243         "sets permutation notation for input (in type A only)";
244       const char* postfix_tag = "resets the input postfix";
245       const char* prefix_tag = "resets the input prefix";
246       const char* separator_tag = "resets the input separator";
247       const char* symbol_tag = "resets an input symbol";
248       const char* terse_tag = "sets terse conventions for input";
249     };
250 
251     namespace out {
252       void alphabetic_f();
253       void bourbaki_f();
254       void decimal_f();
255       void default_f();
256       void gap_f();
257       void hexadecimal_f();
258       void permutation_f();
259       void postfix_f();
260       void prefix_f();
261       void separator_f();
262       void terse_f();
263       const char* alphabetic_tag =
264         "sets alphabetic generator symbols for output";
265       const char* bourbaki_tag = "sets Bourbaki conventions for output";
266       const char* decimal_tag = "sets decimal generator symbols for output";
267       const char* default_tag = "sets default conventions for output";
268       const char* gap_tag = "sets GAP conventions for output";
269       const char* hexadecimal_tag =
270         "sets hexadecimal generator symbols for output";
271       const char* permutation_tag =
272         "sets permutation notation for output (in type A only)";
273       const char* postfix_tag = "resets the output postfix";
274       const char* prefix_tag = "resets the output prefix";
275       const char* separator_tag = "resets the output separator";
276       const char* symbol_tag = "resets an output symbol";
277       const char* terse_tag = "sets terse conventions for output";
278     };
279 };
280 
281 };
282 
283 /*****************************************************************************
284 
285   This module contains the code for the command interface. Although overall
286   I'm happy with the way it works, it suffers from a certain amount of
287   clumsiness.
288 
289   The idea is that at each point in time, there is a certain active CommandTree
290   object. This is basically a dictionary of recognized command names, together
291   with the functions that will executed for them; in other words, something
292   that should be a map in STL parlance. Actually, the active command tree is
293   the top of the command tree stack treeStack; exiting the current mode means
294   popping the stack; entering a new mode means pushing it on the stack.
295 
296   Each mode has an associated entry and exit function, which take care of
297   initialization and clean-up duties. Actually, there is mostly one main mode;
298   the entry function for this is the one which gets type and rank for the user;
299   the exit function destroys the current group. Redefining type or rank means
300   exiting and re-entering the main mode. In addition, there is the "empty"
301   mode, active on startup only, where nothing is defined yet, and some
302   auxiliary modes which temporarily hide the main mode in order to perform
303   certain duties : interface mode to set the i/o preferences of the user,
304   help mode for help, and also unequal-parameter mode which sets unequal
305   parameters for the k-l functions; this is in fact a sort of duplicate
306   main mode.
307 
308   Command completion is implemented to the extend that incomplete commands
309   are recognized when non-ambiguous.
310 
311  *****************************************************************************/
312 
313 /*****************************************************************************
314 
315         Chapter I -- Running the program
316 
317   This section contains the following functions :
318 
319   - ambigAction(str) : what to do with an ambiguous command;
320   - mainCommandTree() : returns a pointer to the initial command tree (and
321     builds it on first call);
322   - relax_f() : does nothing;
323   - run() : runs an interactive session;
324 
325  *****************************************************************************/
326 
327 namespace commands {
328 
relax_f()329 void relax_f()
330 
331 /*
332   Does nothing.
333 */
334 
335 {}
336 
run()337 void run()
338 
339 /*
340   This function runs an interactive session of the program.
341 */
342 
343 {
344   static String name(0);
345 
346   activate(emptyCommandTree());
347 
348   if (ERRNO) {
349     Error (ERRNO);
350     return;
351   }
352 
353   while (1) { /* the only way to exit from this loop is the "qq" command */
354     CommandTree* tree = treeStack.top();
355     tree->prompt();
356     getInput(stdin,name);
357     CommandData* cd = tree->find(name);
358     if (cd == 0) {
359       tree->error(name.ptr());
360       continue;
361     }
362     if (cd == ambigCommand()) {
363       ambigAction(tree,name);
364       continue;
365     }
366     cd->action();
367     if (cd->autorepeat) {
368       tree->setAction("",cd->action);
369       tree->setRepeat("",true);
370     }
371     else {
372       tree->setAction("",&relax_f);
373       tree->setRepeat("",false);
374     }
375   }
376 }
377 
default_error(char * str)378 void default_error(char* str)
379 
380 /*
381   Default response to an unknown command.
382 */
383 
384 {
385   Error(COMMAND_NOT_FOUND,str);
386   return;
387 }
388 
389 };
390 
391 namespace {
392 
activate(CommandTree * tree)393 void activate(CommandTree* tree)
394 
395 /*
396   Puts the tree on top of treeStack, and executes the initialization function.
397 
398 */
399 
400 {
401   treeStack.push(tree);
402   tree->entry();
403 
404   if (ERRNO) { /* an error occured during initialization */
405     Error(ERRNO);
406     treeStack.pop();
407     ERRNO = MODECHANGE_FAIL;
408   }
409 
410   return;
411 }
412 
ambigAction(CommandTree * tree,const String & str)413 void ambigAction(CommandTree* tree, const String& str)
414 
415 /*
416   Response to ambiguous commands. Prints a warning and the list of possible
417   completions in the current tree on stderr.
418 */
419 
420 {
421   static String name(0);
422   bool b = true;
423 
424   print(stderr,str);
425   fprintf(stderr," : ambiguous (");
426   DictCell<CommandData>* cell = tree->findCell(str);
427   new(&name) String(str);
428   printExtensions(stderr,cell->left,name,b);
429   fprintf(stderr,")\n");
430 
431   return;
432 }
433 
empty_error(char * str)434 void empty_error(char* str)
435 
436 {
437   CommandTree* tree = mainCommandTree();
438 
439   CommandData* cd = tree->find(str);
440   if (cd == 0) {
441     default_error(str);
442     return;
443   }
444   if (cd == ambigCommand()) {
445     ambigAction(tree,str);
446     return;
447   }
448   activate(tree);
449   if (ERRNO) { /* something went wrong during initialization */
450     Error(ERRNO);
451     return;
452   }
453   /* type and rank are set at this point */
454   if ((cd != tree->find("type")) && (cd != tree->find("rank")))
455     cd->action();
456   if (cd->autorepeat) {
457     tree->setAction("",cd->action);
458     tree->setRepeat("",true);
459   }
460   else {
461     tree->setAction("",&relax_f);
462     tree->setRepeat("",false);
463   }
464   return;
465 }
466 
startup()467 void startup()
468 
469 /*
470   The response to the first carriage return. Sets the response to "help"
471   to a less verbose version, and starts up the program.
472 */
473 
474 {
475   activate(mainCommandTree());
476 
477   if (ERRNO)
478     Error(ERRNO);
479 
480   return;
481 }
482 
483 };
484 
485 /*****************************************************************************
486 
487         Chapter II -- The CommandTree class.
488 
489   The purpose of a CommandTree is to get a command-name from the user (or
490   perhaps from a file), and execute the corresponding command. For this,
491   it maintains a tree of CommandCell s, one for each initial subword of
492   each recognized command. Each CommandCell knows which command it should
493   execute.
494 
495   Recognizing initial subwords allows for command completion : when the
496   completion is unique, the command is executed as if the full name were
497   typed. When the completion is not unique, the function for ambiguous
498   commands is executed : as defined here, it prints the list of all possible
499   completions in the current tree, and prompts the user again.
500 
501   The case of the empty command is special : either it does nothing, or,
502   for most commands, it repeats the previous command.
503 
504   This setup supports the concept of mode : at all times, there is a current
505   command tree, and in some situations this will change : new commands can
506   become available, commands can change behaviour or can become unavailable.
507   Help mode is an example of this. Another example is the interface command,
508   which loads the interface mode tree, so that the user can set the various
509   i/o parameters.
510 
511   NOTE : even though I like the actual behaviour of the setup, it is all
512   rather clumsy and should be re-done. The command tree could be replaced
513   with some associative container like map. The current behaviour could
514   be pretty much kept as is, until we include the functionalities of
515   readline.
516 
517   The following functions are defined :
518 
519    - constructors and destructors :
520 
521      - CommandTree(prompt,a,entry,error,exit,h) : builds a command tree with
522        the given prompt, action a, help function h, given entry and exit
523        functions, and error function (called when a command is not found);
524      - ~CommandTree();
525 
526    - accessors :
527 
528      - prompt : prints the prompt;
529 
530    - manipulators :
531 
532      - add(name,tag,a,h,rep) : adds a command with the given name, tag (used
533        in the online help), action a, help-action h and repetition flag rep;
534      - setAction(str,a) : resets the action of the command for str;
535      - setRepeat(str,b) : resets the repetition flag of the command for b;
536 
537 ******************************************************************************/
538 
539 namespace commands {
540 
CommandTree(const char * prompt,void (* a)(),void (* entry)(),void (* error)(char *),void (* exit)(),void (* h)())541 CommandTree::CommandTree(const char* prompt,
542 			 void (*a)(),
543 			 void (*entry)(),
544 			 void (*error)(char*),
545 			 void (*exit)(),
546 			 void (*h)())
547   :d_prompt(prompt), d_entry(entry), d_error(error), d_exit(exit)
548 
549 /*
550   Initializes a command tree with the given prompt and action for the
551   empty command.
552 */
553 
554 {
555   d_root->ptr = new CommandData("","",a,&relax_f,false);
556 
557   if (h) { /* add help functionality */
558     d_help = new CommandTree("help",&cr_h,h);
559     d_help->add("q",q_tag,&q_f,0,false);
560     add("help",help_tag,&help_f,&help_h,false);
561   }
562 }
563 
~CommandTree()564 CommandTree::~CommandTree()
565 
566 /*
567   The memory allocated by a CommandTree object is hidden in the dictionary
568   and in the d_help pointer.
569 */
570 
571 {
572   delete d_help;
573 }
574 
575 /******** accessors *********************************************************/
576 
prompt() const577 void CommandTree::prompt() const
578 
579 /*
580   Prints the prompt for the command tree.
581 */
582 
583 {
584   printf("%s : ",d_prompt.ptr());
585 }
586 
587 /******** manipulators ******************************************************/
588 
add(const char * name,const char * tag,void (* a)(),void (* h)(),bool rep)589 void CommandTree::add(const char* name, const char* tag, void (*a)(),
590 		      void (*h)(), bool rep)
591 
592 /*
593   This function adds a new command to the tree, adding new cells as
594   necessary.
595 */
596 
597 {
598   CommandData *cd = new CommandData(name,tag,a,h,rep);
599 
600   insert(name,cd);
601   if (d_help && h) { /* add help functionality */
602     d_help->add(name,tag,h,0,false);
603   }
604 }
605 
setAction(const char * str,void (* a)())606 void CommandTree::setAction(const char* str, void (*a)())
607 
608 /*
609   Assuming that str is a fullname on the command tree, sets the response
610   to str to a.
611 
612   NOTE : is a bit dangerous. Should work also when str is only a prefix.
613 */
614 
615 {
616   CommandData* cd = find(str);
617   cd->action = a;
618 
619   return;
620 }
621 
setRepeat(const char * str,bool b)622 void CommandTree::setRepeat(const char* str, bool b)
623 
624 /*
625   Assuming that str is a fullname on the command tree, sets the autorepeat
626   value of the corresponding command data structure to b.
627 */
628 
629 {
630   CommandData* cd = find(str);
631   cd->autorepeat = b;
632 
633   return;
634 }
635 
636 };
637 
638 /*****************************************************************************
639 
640         Chapter III -- The CommandData class.
641 
642   The CommandData structure collects the data associated to a given command
643   name. The function a defines the action associated with the command; the
644   function h defines the action associated with the command in help mode.
645   The flag b is set if the command should be repeated on a carriage return.
646 
647  *****************************************************************************/
648 
649 namespace commands {
650 
CommandData(const char * const & str,const char * const & t,void (* a)(),void (* h)(),bool rep)651 CommandData::CommandData(const char* const& str, const char* const& t,
652 			 void (*a)(), void (*h)(), bool rep)
653   :name(str), tag(t), action(a), help(h), autorepeat(rep)
654 
655 {}
656 
~CommandData()657 CommandData::~CommandData()
658 
659 /*
660   No memory is allocated directly
661 */
662 
663 {}
664 
665 };
666 
667 /*****************************************************************************
668 
669         Chapter IV -- Building the command tree
670 
671   This section contains the functions used for the construction of the primary
672   command tree, i.e., the initialization of the command module.
673 
674   The following functions are defined :
675 
676   - ambigCommand() : returns a special value flagging ambiguous commands;
677   - cellCompletion(cell) : auxiliary to commandCompletion;
678   - commandCompletion(tree) : finishes off the command tree;
679   - emptyCommandTree() : returns a pointer to the initial command tree;
680   - initCommandTree<Empty_tag> : builds the empty command tree;
681   - initCommandTree<Interface_tag> : builds the interface command tree;
682   - initCommandTree<Main_tag> : builds the main command tree;
683   - initCommandTree<Uneq_tag> : builds the command tree for unequal parameters;
684   - interfaceCommandTree() : returns a pointer to the interface command tree;
685   - mainCommandTree() : returns a pointer to the main command tree;
686   - uneqCommandTree() : returns a pointer to the unequal-parameter command
687     tree;
688 
689  *****************************************************************************/
690 
691 namespace {
692 
ambigCommand()693 CommandData* ambigCommand()
694 
695 /*
696   Returns a dummy command cell which is a placeholder indicating that
697   ambigAction must be executed; this requires knowledge of where we are
698   in the command tree.
699 */
700 
701 {
702   static CommandData cd("","",0,0,false);
703   return &cd;
704 }
705 
cellCompletion(DictCell<CommandData> * cell)706 void cellCompletion(DictCell<CommandData>* cell)
707 
708 /*
709   This function fills in the value fields of the cells which do not
710   correspond to full names. It is assumed that the tree is traversed
711   in infix (?) order, i.e. first visit left child, then cell, the right
712   child, so that all longer names are already visited. This allows to
713   fill in unique completions backwards, making thins easy.
714 */
715 
716 {
717   if (cell->fullname == true)
718     return;
719 
720   if (cell->uniquePrefix == false) { /* ambiguous */
721     cell->ptr = ambigCommand();
722     return;
723   }
724 
725   if (cell->uniquePrefix == true) { /* unique completion */
726     cell->ptr = cell->left->value();
727     return;
728   }
729 }
730 
commandCompletion(DictCell<CommandData> * cell)731 void commandCompletion(DictCell<CommandData>* cell)
732 
733 /*
734   This function finishes up the command tree by implementing command
735   completion. This is done as follows. We traverse the command tree
736   from the root. If node.fullname is true, we do nothing. Otherwise,
737   if node.uniquePrefix is true, we set node.value to be equal to the
738   value of the unique completion of the string recognized by node in
739   the dictionary. If node.uniquePrefix is false, we set node.value
740   to ambigCommand().
741 */
742 
743 {
744   if (cell == 0)
745     return;
746 
747   commandCompletion(cell->left);
748   cellCompletion(cell);
749   commandCompletion(cell->right);
750 }
751 
initCommandTree()752 template<> CommandTree* initCommandTree<Empty_tag>()
753 
754 /*
755   This function builds the initial command tree of the program. The idea
756   is that all commands on the main command tree will be considered entry
757   commands, and so will do the necessary initialization. This is achieved
758   thru the special error function.
759 */
760 
761 {
762   static CommandTree tree("coxeter",&startup,&relax_f,&empty_error,&relax_f,
763 			  &intro_h);
764 
765   tree.add("author","author_tag",&author_f,&relax_f,false);
766   tree.add("qq",qq_tag,&qq_f,&qq_h,false);
767 
768   commandCompletion(tree.root());
769 
770   tree.helpMode()->add("intro",intro_tag,&intro_h,0,false);
771 
772   commandCompletion(tree.helpMode()->root());
773 
774   return &tree;
775 }
776 
emptyCommandTree()777 CommandTree* emptyCommandTree()
778 
779 /*
780   Returns a pointer to the initial command tree of the program, building it on
781   the first call.
782 */
783 
784 {
785   static CommandTree* tree = initCommandTree<Empty_tag>();
786   return tree;
787 }
788 
initCommandTree()789 template<> CommandTree* initCommandTree<Interface_tag>()
790 
791 /*
792   This function builds the interface command tree; this makes available the
793   various little commands that are needed to reset the interface, and that
794   have no reason to be clogging up the main command tree.
795 */
796 
797 {
798   static CommandTree tree("interface",&relax_f,&interface_entry,&default_error,
799 			  &interface_exit,&interface_help);
800 
801   tree.add("alphabetic",commands::interface::alphabetic_tag,
802 	   &commands::interface::alphabetic_f,&help::interface::alphabetic_h);
803   tree.add("bourbaki",commands::interface::bourbaki_tag,
804 	   &commands::interface::bourbaki_f,&help::interface::bourbaki_h);
805   tree.add("decimal",commands::interface::decimal_tag,
806 	   &commands::interface::decimal_f,&help::interface::decimal_h);
807   tree.add("default",commands::interface::default_tag,
808 	   &commands::interface::default_f,&help::interface::default_h);
809   tree.add("gap",commands::interface::out::gap_tag,
810 	   &commands::interface::out::gap_f, &help::interface::gap_h);
811   tree.add("hexadecimal",commands::interface::hexadecimal_tag,
812 	   &commands::interface::hexadecimal_f,
813 	   &help::interface::hexadecimal_h);
814   tree.add("in",commands::interface::in_tag,&commands::interface::in_f,
815 	   help::interface::in_h,false);
816   tree.add("ordering",commands::interface::ordering_tag,
817 	   &commands::interface::ordering_f,help::interface::ordering_h,false);
818   tree.add("out",commands::interface::out_tag,&commands::interface::out_f,
819 	   help::interface::out_h,false);
820   tree.add("permutation",commands::interface::permutation_tag,
821 	   &commands::interface::permutation_f,
822 	   &help::interface::permutation_h);
823   tree.add("q",q_tag,&q_f,0,false);
824   tree.add("terse",commands::interface::out::terse_tag,
825 	   &commands::interface::out::terse_f, &help::interface::out::terse_h);
826 
827   commandCompletion(tree.root());
828   commandCompletion(tree.helpMode()->root());
829 
830   return &tree;
831 }
832 
initCommandTree()833 template<> CommandTree* initCommandTree<commands::interface::In_tag>()
834 
835 /*
836   This function builds the command tree for the input-modification mode.
837 */
838 
839 {
840   using namespace commands::interface;
841 
842   static CommandTree tree("in",&relax_f,&in_entry,&default_error,
843 			  &in_exit,&help::interface::in_help);
844 
845   tree.add("q",q_tag,&q_f,0,false);
846 
847   tree.add("abort",abort_tag,&abort_f,&help::interface::abort_h);
848   tree.add("alphabetic",in::alphabetic_tag,&in::alphabetic_f,
849 	   &help::interface::in::alphabetic_h,false);
850   tree.add("bourbaki",in::bourbaki_tag,&in::bourbaki_f,
851 	   &help::interface::in::bourbaki_h);
852   tree.add("decimal",in::decimal_tag,&in::decimal_f,
853 	   &help::interface::in::decimal_h,false);
854   tree.add("default",in::default_tag,&in::default_f,
855 	   &help::interface::in::default_h);
856   tree.add("gap",in::gap_tag,&in::gap_f,&help::interface::in::gap_h);
857   tree.add("hexadecimal",in::hexadecimal_tag,&in::hexadecimal_f,
858 	   &help::interface::in::hexadecimal_h,false);
859   tree.add("permutation",in::permutation_tag,&in::permutation_f,
860 	   &help::interface::in::permutation_h,false);
861   tree.add("postfix",in::postfix_tag,&in::postfix_f,
862 	   &help::interface::in::postfix_h);
863   tree.add("prefix",in::prefix_tag,&in::prefix_f,
864 	   &help::interface::in::prefix_h);
865   tree.add("separator",in::separator_tag,
866 	   &in::separator_f,&help::interface::in::separator_h);
867   tree.add("symbol",in::symbol_tag,&symbol_f,
868 	   &help::interface::in::symbol_h);
869   tree.add("terse",in::terse_tag,&in::terse_f,&help::interface::in::terse_h);
870 
871   commandCompletion(tree.root());
872   commandCompletion(tree.helpMode()->root());
873 
874   return &tree;
875 }
876 
initCommandTree()877 template<> CommandTree* initCommandTree<commands::interface::Out_tag>()
878 
879 /*
880   This function builds the command tree for the output-modification mode.
881 */
882 
883 {
884   using namespace commands::interface;
885 
886   static CommandTree tree("out",&relax_f,&out_entry,&default_error,
887 			  &out_exit,&help::interface::out_help);
888 
889   tree.add("q",q_tag,&q_f,0,false);
890 
891   tree.add("alphabetic",out::alphabetic_tag,&out::alphabetic_f,
892 	   &help::interface::out::alphabetic_h,false);
893   tree.add("bourbaki",out::bourbaki_tag,&out::bourbaki_f,
894 	   &help::interface::out::bourbaki_h);
895   tree.add("decimal",out::decimal_tag,&out::decimal_f,
896 	   &help::interface::out::decimal_h,false);
897   tree.add("default",out::default_tag,&out::default_f,
898 	   &help::interface::out::default_h);
899   tree.add("gap",out::gap_tag,&out::gap_f,
900 	   &help::interface::out::gap_h);
901   tree.add("hexadecimal",out::hexadecimal_tag,&out::hexadecimal_f,
902 	   &help::interface::out::hexadecimal_h,false);
903   tree.add("permutation",out::permutation_tag,&out::permutation_f,
904 	   &help::interface::out::permutation_h,false);
905   tree.add("postfix",out::postfix_tag,&out::postfix_f,
906 	   &help::interface::out::postfix_h);
907   tree.add("prefix",out::prefix_tag,&out::prefix_f,
908 	   &help::interface::out::prefix_h);
909   tree.add("separator",out::separator_tag,
910 	   &out::separator_f,&help::interface::out::separator_h);
911   tree.add("symbol",out::symbol_tag,&symbol_f,
912 	   &help::interface::out::symbol_h);
913   tree.add("terse",out::terse_tag,&out::terse_f,
914 	   &help::interface::out::terse_h);
915 
916   commandCompletion(tree.root());
917   commandCompletion(tree.helpMode()->root());
918 
919   return &tree;
920 }
921 
922 };
923 
924 namespace commands {
925 
inCommandTree()926 CommandTree* interface::inCommandTree()
927 
928 {
929   static CommandTree* tree = initCommandTree<In_tag>();
930   return tree;
931 }
932 
outCommandTree()933 CommandTree* interface::outCommandTree()
934 
935 {
936   static CommandTree* tree = initCommandTree<Out_tag>();
937   return tree;
938 }
939 
interfaceCommandTree()940 CommandTree* interfaceCommandTree()
941 
942 /*
943   Returns a pointer to the interface command tree, building it on the first
944   call.
945 */
946 
947 {
948   static CommandTree* tree = initCommandTree<Interface_tag>();
949   return tree;
950 }
951 
952 };
953 
954 namespace {
955 
initCommandTree()956 template<> CommandTree* initCommandTree<Main_tag>()
957 
958 /*
959   This function builds the main command tree, the one that is being run on
960   startup. Auxiliary trees may be grafted onto this one (thru the pushdown
961   stack treeStack) by some functions needing to be in special modes.
962 */
963 
964 {
965   static CommandTree tree("coxeter",&relax_f,&main_entry,&default_error,
966 			  &main_exit,&main_help);
967 
968   tree.add("author",author_tag,&author_f,&relax_f,false);
969   tree.add("betti",betti_tag,&betti_f,&betti_h,false);
970   tree.add("coatoms",coatoms_tag,&coatoms_f,&coatoms_h);
971   tree.add("compute",compute_tag,&compute_f,&compute_h);
972   tree.add("descent",descent_tag,&descent_f,&descent_h);
973   tree.add("duflo",duflo_tag,&duflo_f,&duflo_h);
974   tree.add("extremals",extremals_tag,&extremals_f,&extremals_h);
975   tree.add("fullcontext",fullcontext_tag,&fullcontext_f,&fullcontext_h);
976   tree.add("ihbetti",ihbetti_tag,&ihbetti_f,&ihbetti_h,false);
977   tree.add("interface",interface_tag,&interface_f,&interface_h,false);
978   tree.add("interval",interval_tag,&interval_f,&interval_h,false);
979   tree.add("inorder",inorder_tag,&inorder_f,&inorder_h);
980   tree.add("invpol",invpol_tag,&invpol_f,&invpol_h);
981   tree.add("lcorder",lcorder_tag,&lcorder_f,&lcorder_h,false);
982   tree.add("lcells",lcells_tag,&lcells_f,&lcells_h,false);
983   tree.add("lcwgraphs",lcwgraphs_tag,&lcwgraphs_f,&lcwgraphs_h,false);
984   tree.add("lrcorder",lrcorder_tag,&lrcorder_f,&lrcorder_h,false);
985   tree.add("lrcells",lrcells_tag,&lrcells_f,&lrcells_h,false);
986   tree.add("lrcwgraphs",lrcwgraphs_tag,&lrcwgraphs_f,&lrcwgraphs_h,false);
987   tree.add("lrwgraph",lrwgraph_tag,&lrwgraph_f,&lrwgraph_h,false);
988   tree.add("lwgraph",lwgraph_tag,&lwgraph_f,&lwgraph_h,false);
989   tree.add("klbasis",klbasis_tag,&klbasis_f,&klbasis_h,true);
990   tree.add("matrix",matrix_tag,&matrix_f,&matrix_h);
991   tree.add("mu",mu_tag,&mu_f,&mu_h);
992   tree.add("pol",pol_tag,&pol_f,&pol_h);
993   tree.add("q",q_tag,&q_f,0,false);
994   tree.add("qq",qq_tag,&qq_f,&qq_h,false);
995   tree.add("rank",rank_tag,&rank_f,&rank_h,false);
996   tree.add("rcorder",rcorder_tag,&rcorder_f,&rcorder_h,false);
997   tree.add("rcells",rcells_tag,&rcells_f,&rcells_h,false);
998   tree.add("rcwgraphs",rcwgraphs_tag,&rcwgraphs_f,&rcwgraphs_h,false);
999   tree.add("rwgraph",rwgraph_tag,&rwgraph_f,&rwgraph_h,false);
1000   tree.add("schubert",schubert_tag,&schubert_f,&schubert_h);
1001   tree.add("show",show_tag,&show_f,&show_h);
1002   tree.add("showmu",showmu_tag,&showmu_f,&showmu_h);
1003   tree.add("slocus",slocus_tag,&slocus_f,&slocus_h);
1004   tree.add("sstratification",sstratification_tag,&sstratification_f,
1005 	   &sstratification_h);
1006   tree.add("type",type_tag,&type_f,&type_h,false);
1007   tree.add("uneq",uneq_tag,&uneq_f,&uneq_h,false);
1008 
1009   special::addSpecialCommands(&tree);
1010 
1011   commandCompletion(tree.root());
1012 
1013   tree.helpMode()->add("intro",intro_tag,&intro_h,0,false);
1014   tree.helpMode()->add("input",input_tag,&input_h,0,false);
1015 
1016   commandCompletion(tree.helpMode()->root());
1017 
1018   return &tree;
1019 }
1020 
1021 };
1022 
1023 namespace commands {
1024 
mainCommandTree()1025 CommandTree* mainCommandTree()
1026 
1027 /*
1028   Returns a pointer to the main command tree of the program, building it on
1029   the first call.
1030 */
1031 
1032 {
1033   static CommandTree* tree = initCommandTree<Main_tag>();
1034   return tree;
1035 }
1036 
1037 };
1038 
1039 namespace {
1040 
initCommandTree()1041 template<> CommandTree* initCommandTree<Uneq_tag>()
1042 
1043 /*
1044   This function builds the unequal-parameter command tree. It contains
1045   essentially the same functions as the main command tree, except that the
1046   unequal-parameter versions have been substituted for the k-l functions.
1047 */
1048 
1049 {
1050   static CommandTree tree("uneq",&relax_f,&uneq_entry,&default_error,
1051 			  &uneq_exit,&uneq_help);
1052 
1053   tree.add("author",author_tag,&author_f,&relax_f,false);
1054   tree.add("coatoms",coatoms_tag,&coatoms_f,&coatoms_h);
1055   tree.add("compute",compute_tag,&compute_f,&compute_h);
1056   tree.add("descent",descent_tag,&descent_f,&descent_h);
1057   tree.add("fullcontext",fullcontext_tag,&fullcontext_f,&fullcontext_h);
1058   tree.add("interface",interface_tag,&interface_f,&interface_h,false);
1059   tree.add("klbasis",klbasis_tag,&uneq::klbasis_f,&help::uneq::klbasis_h,true);
1060   tree.add("lcorder",uneq::lcorder_tag,&uneq::lcorder_f,
1061 	   &help::uneq::lcorder_h,false);
1062   tree.add("lrcorder",uneq::lrcorder_tag,&uneq::lrcorder_f,
1063 	   &help::uneq::lrcorder_h,false);
1064   tree.add("lcells",uneq::lcells_tag,&uneq::lcells_f,&help::uneq::lcells_h,
1065 	   false);
1066   tree.add("lrcells",uneq::lrcells_tag,&uneq::lrcells_f,&help::uneq::lrcells_h,
1067 	   false);
1068   tree.add("matrix",matrix_tag,&matrix_f,&matrix_h);
1069   tree.add("mu",uneq::mu_tag,&uneq::mu_f,&help::uneq::mu_h);
1070   tree.add("pol",uneq::pol_tag,&uneq::pol_f,&help::uneq::pol_h);
1071   tree.add("rcells",uneq::rcells_tag,&uneq::rcells_f,&help::uneq::rcells_h,
1072 	   false);
1073   tree.add("rcorder",uneq::rcorder_tag,&uneq::rcorder_f,
1074 	   &help::uneq::rcorder_h,false);
1075   tree.add("q",q_tag,&q_f,0,false);
1076   tree.add("qq",qq_tag,&qq_f,&qq_h,false);
1077 
1078   commandCompletion(tree.root());
1079   commandCompletion(tree.helpMode()->root());
1080 
1081   return &tree;
1082 }
1083 
1084 };
1085 
1086 namespace commands {
1087 
uneqCommandTree()1088 CommandTree* uneqCommandTree()
1089 
1090 /*
1091   Returns a pointer to the uneq command tree, building it on the first call.
1092 */
1093 
1094 {
1095   static CommandTree* tree = initCommandTree<Uneq_tag>();
1096   return tree;
1097 }
1098 
1099 };
1100 
1101 /*****************************************************************************
1102 
1103         Chapter V -- Functions for the predefined commands.
1104 
1105   This section contains the functions defining the responses to the various
1106   commands which are provided by the program. The functions are placed in
1107   the unnamed namespace defined in this file.
1108 
1109   The following functions are defined :
1110 
1111   - author_f() : response to "author";
1112   - betti_f() : response to "betti";
1113   - coatoms_f() : response to "coatoms";
1114   - compute_f() : response to "compute";
1115   - descent_f() : response to "descent";
1116   - duflo_f() : response to "duflo";
1117   - extremals_f() : response to "extremals";
1118   - fullcontext_f() : response to "fullcontext";
1119   - ihbetti_f() : response to "ihbetti";
1120   - inorder_f() : response to "inorder";
1121   - interface_f() : response to "interface";
1122   - help_f() : repsonse to "help";
1123   - klbasis_f() : response to "klbasis";
1124   - lcorder_f() : response to "lcorder";
1125   - lcells_f() : response to "lcells";
1126   - lcwgraphs_f() : response to "lcwgraphs";
1127   - lrcorder_f() : response to "lrcorder";
1128   - lrcells_f() : response to "lrcells";
1129   - lrcwgraphs_f() : response to "lrcwgraphs";
1130   - lrwgraph_f() : response to "lrwgraph";
1131   - lwgraph_f() : response to "lwgraph";
1132   - matrix_f() : response to "matrix";
1133   - mu_f() : response to "mu";
1134   - not_implemented_f() : response for not (yet) implemented features;
1135   - q_f() : response to "q";
1136   - qq_f() : response to "qq";
1137   - rank_f() : response to "rank";
1138   - rcorder_f() : response to "rcorder";
1139   - rcells_f() : response to "rcells";
1140   - rcwgraphs_f() : response to "rcwgraphs";
1141   - rwgraph_f() : response to "rwgraph";
1142   - relax_f() : does nothing;
1143   - schubert_f() : response to "schubert";
1144   - show_f() : response to "show";
1145   - showmu_f() : response to "showmu";
1146   - slocus_f() : response to "slocus";
1147   - sstratification_f() : response to "sstratification";
1148   - type_f() : response to "type";
1149   - uneq_f() : response to "uneq";
1150 
1151   In uneq mode :
1152 
1153   - klbasis_f() : response to "klbasis";
1154   - lcorder_f() : response to "lcorder";
1155   - lcells_f() : response to "lcells";
1156   - lrcorder_f() : response to "lrcorder";
1157   - lrcells_f() : response to "lrcells";
1158   - mu_f() : response to "mu";
1159   - pol_f() : response to "pol";
1160   - rcells_f() : response to "rcells";
1161   - rcorder_f() : response to "rcorder";
1162 
1163   In interface mode :
1164 
1165   - abort_f() : aborts input interface modification;
1166   - alphabetic_f() : sets alphabetic generator symbols;
1167   - bourbaki_f() : sets bourbaki conventions;
1168   - decimal_f() : sets decimal generator symbols;
1169   - default_f() : sets default i/o;
1170   - gap_f() : sets GAP-style i/o;
1171   - hexadecimal_f() : sets hexadecimal generator symbols;
1172   - ordering_f() : changes the ordering of the generators;
1173   - symbol_f() : resets generator symbol;
1174   - terse_f() : sets terse style i/o;
1175   - in::alphabetic_f() : sets alphabetic generator symbols;
1176   - in::bourbaki_f() : sets bourbaki conventions;
1177   - in::decimal_f() : sets decimal generator symbols;
1178   - in::default_f() : sets default-style input;
1179   - in::gap_f() : sets GAP-style input;
1180   - in::hexadecimal_f() : sets hexadecimal generator symbols;
1181   - in::permutation_f() : sets permutation input;
1182   - in::postfix_f() : resets input postfix;
1183   - in::prefix_f() : resets input prefix;
1184   - in::separator_f() : resets input separator;
1185   - in::terse_f() : sets terse-style input;
1186   - out::alphabetic_f() : sets alphabetic generator symbols;
1187   - out::bourbaki_f() : sets bourbaki conventions;
1188   - out::decimal_f() : sets decimal generator symbols;
1189   - out::default_f() : sets default-style output;
1190   - out::gap_f() : sets GAP-style output;
1191   - out::hexadecimal_f() : sets hexadecimal generator symbols;
1192   - out::permutation_f() : sets permutation output;
1193   - out::postfix_f() : resets output postfix;
1194   - out::prefix_f() : resets output prefix;
1195   - out::separator_f() : resest output separator;
1196   - out::terse_f() : sets terse-style output;
1197 
1198  *****************************************************************************/
1199 
1200 namespace {
1201 
author_f()1202 void author_f()
1203 
1204 /*
1205   Prints a message about the author.
1206 */
1207 
1208 {
1209   printFile(stderr,"author.mess",MESSAGE_DIR);
1210   return;
1211 }
1212 
betti_f()1213 void betti_f()
1214 
1215 /*
1216   Prints out the ordinary betti numbers of [e,y].
1217 
1218   NOTE : could be *much* improved! In particular, we would want to have
1219   betti(x,y) for x <= y.
1220 */
1221 
1222 {
1223   static CoxWord g(0);
1224 
1225   printf("enter your element (finish with a carriage return) :\n");
1226   g = interactive::getCoxWord(W);
1227   if (ERRNO) {
1228     Error(ERRNO);
1229     return;
1230   }
1231 
1232   CoxNbr y = W->extendContext(g);
1233   if (ERRNO) {
1234     Error(ERRNO);
1235     return;
1236   }
1237 
1238   OutputTraits& traits = W->outputTraits();
1239   printBetti(stdout,y,W->schubert(),traits);
1240 
1241   return;
1242 }
1243 
coatoms_f()1244 void coatoms_f()
1245 
1246 /*
1247   Prints out the coatoms of a given element, computing them in elementary
1248   fashion.
1249 */
1250 
1251 {
1252   static CoxWord g(0);
1253 
1254   printf("enter your element (finish with a carriage return) :\n");
1255   g = interactive::getCoxWord(W);
1256   if (ERRNO) {
1257     Error(ERRNO);
1258     return;
1259   }
1260 
1261   List<CoxWord> c(0);
1262   W->coatoms(c,g);
1263 
1264   for (Ulong j = 0; j < c.size(); ++j) {
1265     W->print(stdout,c[j]);
1266     printf("\n");
1267   }
1268 
1269   return;
1270 }
1271 
compute_f()1272 void compute_f()
1273 
1274 /*
1275   Gets an element from the user, and prints out its normal form.
1276 */
1277 
1278 {
1279   static CoxWord g(0);
1280 
1281   printf("enter your element (finish with a carriage return) :\n");
1282   g = interactive::getCoxWord(W);
1283   if (ERRNO) {
1284     Error(ERRNO);
1285     return;
1286   }
1287   W->normalForm(g);
1288   W->print(stdout,g);
1289   if (SmallCoxGroup* Ws = dynamic_cast<SmallCoxGroup*> (W)) {
1290     CoxNbr x = 0;
1291     Ws->prodD(x,g);
1292     printf(" (#%lu)",static_cast<Ulong>(x));
1293   }
1294   CoxNbr x = W->contextNumber(g);
1295   if (x != undef_coxnbr)
1296     printf(" (%s%lu)","%",static_cast<Ulong>(x));
1297   printf("\n");
1298 
1299   return;
1300 }
1301 
descent_f()1302 void descent_f()
1303 
1304 /*
1305   Prints the left and right descent sets.
1306 */
1307 
1308 {
1309   static CoxWord g(0);
1310 
1311   printf("enter your element (finish with a carriage return) :\n");
1312   g = interactive::getCoxWord(W);
1313   if (ERRNO) {
1314     Error(ERRNO);
1315     return;
1316   }
1317 
1318   LFlags f = W->ldescent(g);
1319   printf("L:");
1320   W->printFlags(stdout,f);
1321   printf("; R:");
1322   f = W->rdescent(g);
1323   W->printFlags(stdout,f);
1324   printf("\n");
1325 
1326   return;
1327 }
1328 
duflo_f()1329 void duflo_f()
1330 
1331 /*
1332   Prints the Duflo involutions. Works for finite groups only.
1333 */
1334 
1335 {
1336   if (!isFiniteType(W)) {
1337     printFile(stderr,"duflo.mess",MESSAGE_DIR);
1338     return;
1339   }
1340 
1341   FiniteCoxGroup* Wf = dynamic_cast<FiniteCoxGroup*> (W);
1342 
1343   Wf->fullContext();
1344   if (ERRNO) {
1345     Error(ERRNO);
1346     return;
1347   }
1348 
1349   Wf->fillMu();
1350   if (ERRNO) {
1351     Error(ERRNO);
1352     return;
1353   }
1354 
1355   OutputFile file;
1356   OutputTraits& traits = Wf->outputTraits();
1357 
1358   printHeader(file.f(),dufloH,traits);
1359   printDuflo(file.f(),Wf->duflo(),Wf->lCell(),Wf->kl(),W->interface(),traits);
1360 
1361   return;
1362 }
1363 
extremals_f()1364 void extremals_f()
1365 
1366 /*
1367   Prints out the list of extremal elements x <= y (this is part of the schubert
1368   command.
1369 */
1370 
1371 {
1372   static CoxWord g(0);
1373 
1374   printf("Enter your element (finish with a carriage-return) :\n");
1375   g = interactive::getCoxWord(W);
1376   if (ERRNO) {
1377     Error(ERRNO);
1378     return;
1379   }
1380 
1381   CoxNbr y = W->extendContext(g);
1382   if (ERRNO) {
1383     Error(ERRNO);
1384     return;
1385   }
1386 
1387   interactive::OutputFile file;
1388   OutputTraits& traits = W->outputTraits();
1389 
1390   printHeader(file.f(),extremalsH,traits);
1391   printExtremals(file.f(),y,W->kl(),W->interface(),traits);
1392 
1393   return;
1394 }
1395 
fullcontext_f()1396 void fullcontext_f()
1397 
1398 /*
1399   Response to the fullcontext command. This sets the context to the full
1400   group. Of course, it works only for finite groups.
1401 */
1402 
1403 {
1404   if (!isFiniteType(W)) {
1405     printFile(stderr,"fullcontext.mess",MESSAGE_DIR);
1406     return;
1407   }
1408 
1409   FiniteCoxGroup* Wf = dynamic_cast<FiniteCoxGroup*> (W);
1410 
1411   Wf->fullContext();
1412   if (ERRNO) {
1413     Error(ERRNO);
1414   }
1415 
1416   return;
1417 }
1418 
help_f()1419 void help_f()
1420 
1421 /*
1422   Response to the help command.
1423 */
1424 
1425 {
1426   activate(treeStack.top()->helpMode());
1427   return;
1428 }
1429 
ihbetti_f()1430 void ihbetti_f()
1431 
1432 /*
1433   Prints out the IH betti numbers of [e,y].
1434 */
1435 
1436 {
1437   static CoxWord g(0);
1438 
1439   printf("enter your element (finish with a carriage return) :\n");
1440   g = interactive::getCoxWord(W);
1441   if (ERRNO) {
1442     Error(ERRNO);
1443     return;
1444   }
1445 
1446   CoxNbr y = W->extendContext(g);
1447   if (ERRNO) {
1448     Error(ERRNO);
1449     return;
1450   }
1451 
1452   OutputTraits& traits = W->outputTraits();
1453   printIHBetti(stdout,y,W->kl(),traits);
1454 
1455   return;
1456 }
1457 
interface_f()1458 void interface_f()
1459 
1460 /*
1461   Response to the interface command.
1462 */
1463 
1464 {
1465   activate(interfaceCommandTree());
1466   return;
1467 }
1468 
interval_f()1469 void interval_f()
1470 
1471 /*
1472   Response to the interval command.
1473 */
1474 
1475 {
1476   CoxWord g(0);
1477   CoxWord h(0);
1478 
1479   fprintf(stdout,"first : ");
1480   g = interactive::getCoxWord(W);
1481   if (ERRNO) {
1482     Error(ERRNO);
1483     return;
1484   }
1485   fprintf(stdout,"second : ");
1486   h = interactive::getCoxWord(W);
1487   if (ERRNO) {
1488     Error(ERRNO);
1489     return;
1490   }
1491 
1492   if (not W->inOrder(g,h)) {
1493     fprintf(stderr,"the two elements are not in order\n");
1494     return;
1495   }
1496 
1497   W->extendContext(h);
1498 
1499   CoxNbr x = W->contextNumber(g);
1500   CoxNbr y = W->contextNumber(h);
1501 
1502   OutputFile file;
1503 
1504   BitMap b(W->contextSize());
1505   W->extractClosure(b,y);
1506 
1507   BitMap::ReverseIterator b_rend = b.rend();
1508   List<CoxNbr> res(0);
1509 
1510   for (BitMap::ReverseIterator i = b.rbegin(); i != b_rend; ++i)
1511     if (not W->inOrder(x,*i)) {
1512       BitMap bi(W->contextSize());
1513       W->extractClosure(bi,*i);
1514       CoxNbr z = *i; // andnot will invalidate iterator
1515       b.andnot(bi);
1516       b.setBit(z);   // otherwise the decrement will not be correct
1517     } else
1518       res.append(*i);
1519 
1520   schubert::NFCompare nfc(W->schubert(),W->ordering());
1521   Permutation a(res.size());
1522   sortI(res,nfc,a);
1523 
1524   for (size_t j = 0; j < res.size(); ++j) {
1525     W->print(file.f(),res[a[j]]);
1526     fprintf(file.f(),"\n");
1527   }
1528 
1529   return;
1530 }
1531 
inorder_f()1532 void inorder_f()
1533 
1534 /*
1535   Response to the inorder command. This will tell whether two elements
1536   are comparable in Bruhat order, using only the elementary string operations
1537   (and hence not consuming any memory.)
1538 */
1539 
1540 {
1541   CoxWord g(0);
1542   CoxWord h(0);
1543   List<Length> a(0);
1544 
1545   fprintf(stdout,"first : ");
1546   g = interactive::getCoxWord(W);
1547   if (ERRNO) {
1548     Error(ERRNO);
1549     return;
1550   }
1551   fprintf(stdout,"second : ");
1552   h = interactive::getCoxWord(W);
1553   if (ERRNO) {
1554     Error(ERRNO);
1555     return;
1556   }
1557 
1558   if (W->inOrder(a,g,h)) {
1559     fprintf(stdout,"true :   ");
1560     Ulong i = 0;
1561     for (Ulong j = 0; j < a.size(); ++j) {
1562       while (i < a[j]) {
1563 	W->printSymbol(stdout,h[i]-1);
1564 	++i;
1565       }
1566       fprintf(stdout,".");
1567       ++i;
1568     }
1569     while (i < h.length()) {
1570       W->printSymbol(stdout,h[i]-1);
1571       ++i;
1572     }
1573     fprintf(stdout,"\n");
1574   }
1575   else
1576     fprintf(stdout,"false\n");
1577 }
1578 
invpol_f()1579 void invpol_f()
1580 
1581 /*
1582   Response to the invpol command. This prints out a single inverse k-l
1583   polynomial, without details.
1584 */
1585 
1586 {
1587   CoxWord g(0);
1588 
1589   fprintf(stdout,"first : ");
1590   g = interactive::getCoxWord(W);
1591   if (ERRNO) {
1592     Error(ERRNO);
1593     return;
1594   }
1595   CoxNbr x = W->extendContext(g);
1596   if (ERRNO) {
1597     Error(ERRNO);
1598     return;
1599   }
1600 
1601   fprintf(stdout,"second : ");
1602   g = interactive::getCoxWord(W);
1603   if (ERRNO) {
1604     Error(ERRNO);
1605     return;
1606   }
1607   CoxNbr y = W->extendContext(g);
1608   if (ERRNO) {
1609     Error(ERRNO);
1610     return;
1611   }
1612 
1613   if (!W->inOrder(x,y)) {
1614     fprintf(stderr,"the two elements are not in Bruhat order\n");
1615     return;
1616   }
1617 
1618   const invkl::KLPol& pol = W->invklPol(x,y);
1619   if (ERRNO) {
1620     Error(ERRNO,x,y);
1621     return;
1622   }
1623 
1624   print(stdout,pol,"q");
1625   printf("\n");
1626 
1627   return;
1628 }
1629 
klbasis_f()1630 void klbasis_f()
1631 
1632 /*
1633   Prints out one element in the k-l basis of the group, in the format
1634   defined by the current output mode.
1635 */
1636 
1637 {
1638   CoxWord g(0);
1639 
1640   printf("enter your element (finish with a carriage return) :\n");
1641   g = interactive::getCoxWord(W);
1642   if (ERRNO) {
1643     Error(ERRNO);
1644     return;
1645   }
1646 
1647   CoxNbr y = W->extendContext(g);
1648   if (ERRNO) {
1649     Error(ERRNO);
1650     return;
1651   }
1652 
1653   kl::HeckeElt h(0);
1654 
1655   W->cBasis(h,y);
1656   if (ERRNO) {
1657     Error(ERRNO);
1658     return;
1659   }
1660 
1661   interactive::OutputFile file;
1662   OutputTraits& traits = W->outputTraits();
1663 
1664   printHeader(file.f(),basisH,traits);
1665   printAsBasisElt(file.f(),h,W->schubert(),W->interface(),traits);
1666 
1667   return;
1668 }
1669 
lcorder_f()1670 void lcorder_f()
1671 
1672 /*
1673   Prints the left cell order of the current group in a file. Works only for
1674   finite groups.
1675 */
1676 
1677 {
1678   if (!isFiniteType(W)) {
1679     printFile(stderr,"lcorder.mess",MESSAGE_DIR);
1680     return;
1681   }
1682 
1683   FiniteCoxGroup* Wf = dynamic_cast<FiniteCoxGroup*> (W);
1684 
1685   Wf->fullContext();
1686   if (ERRNO) {
1687     Error(ERRNO);
1688     return;
1689   }
1690 
1691   Wf->fillMu();
1692   if (ERRNO) {
1693     Error(ERRNO);
1694     return;
1695   }
1696 
1697   OutputFile file;
1698   OutputTraits& traits = Wf->outputTraits();
1699 
1700   printHeader(file.f(),lCOrderH,traits);
1701   printLCOrder(file.f(),Wf->kl(),Wf->interface(),traits);
1702 
1703   return;
1704 }
1705 
lcells_f()1706 void lcells_f()
1707 
1708 /*
1709   This function prints out the left cells in the group.
1710 */
1711 
1712 {
1713   if (!isFiniteType(W)) {
1714     printFile(stderr,"lcells.mess",MESSAGE_DIR);
1715     return;
1716   }
1717 
1718   FiniteCoxGroup* Wf = dynamic_cast<FiniteCoxGroup*> (W);
1719 
1720   OutputFile file;
1721   OutputTraits& traits = Wf->outputTraits();
1722 
1723   printHeader(file.f(),lCellsH,traits);
1724   printLCells(file.f(),Wf->lCell(),Wf->kl(),Wf->interface(),traits);
1725 
1726   return;
1727 }
1728 
lcwgraphs_f()1729 void lcwgraphs_f()
1730 
1731 /*
1732   This function prints out the W-graphs of the left cells in the group.
1733   It works only for finite groups currently.
1734 */
1735 
1736 {
1737   if (!isFiniteType(W)) {
1738     printFile(stderr,"lcells.mess",MESSAGE_DIR);
1739     return;
1740   }
1741 
1742   FiniteCoxGroup* Wf = dynamic_cast<FiniteCoxGroup*> (W);
1743 
1744   OutputFile file;
1745   OutputTraits& traits = Wf->outputTraits();
1746 
1747   printHeader(file.f(),lCellWGraphsH,traits);
1748   printLCellWGraphs(file.f(),Wf->lCell(),Wf->kl(),W->interface(),traits);
1749 
1750   return;
1751 }
1752 
lrcorder_f()1753 void lrcorder_f()
1754 
1755 /*
1756   Prints the two-sided cell order of the current group in a file. Works only
1757   for finite groups.
1758 */
1759 
1760 {
1761   if (!isFiniteType(W)) {
1762     printFile(stderr,"lrcorder.mess",MESSAGE_DIR);
1763     return;
1764   }
1765 
1766   FiniteCoxGroup* Wf = dynamic_cast<FiniteCoxGroup*> (W);
1767 
1768   Wf->fullContext();
1769   if (ERRNO) {
1770     Error(ERRNO);
1771     return;
1772   }
1773 
1774   Wf->fillMu();
1775   if (ERRNO) {
1776     Error(ERRNO);
1777     return;
1778   }
1779 
1780   OutputFile file;
1781   OutputTraits& traits = Wf->outputTraits();
1782 
1783   printHeader(file.f(),lrCOrderH,traits);
1784   printLRCOrder(file.f(),Wf->kl(),Wf->interface(),traits);
1785 
1786   return;
1787 }
1788 
lrcells_f()1789 void lrcells_f()
1790 
1791 /*
1792   This function prints out the two-sided cells in the group, together with the
1793   corresponding W-graphs. Works only for finite groups.
1794 */
1795 
1796 {
1797   if (!isFiniteType(W)) {
1798     printFile(stderr,"lrcells.mess",MESSAGE_DIR);
1799     return;
1800   }
1801 
1802   FiniteCoxGroup* Wf = dynamic_cast<FiniteCoxGroup*> (W);
1803 
1804   Wf->fullContext();
1805   if (ERRNO) {
1806     Error(ERRNO);
1807     return;
1808   }
1809 
1810   Wf->fillMu();
1811   if (ERRNO) {
1812     Error(ERRNO);
1813     return;
1814   }
1815 
1816   OutputFile file;
1817   OutputTraits& traits = Wf->outputTraits();
1818 
1819   printHeader(file.f(),lrCellsH,traits);
1820   printLRCells(file.f(),Wf->lrCell(),Wf->kl(),Wf->interface(),traits);
1821 
1822   return;
1823 }
1824 
lrcwgraphs_f()1825 void lrcwgraphs_f()
1826 
1827 /*
1828   This function prints out the W-graphs of the two-sided cells in the group.
1829   It works only for finite groups currently.
1830 */
1831 
1832 {
1833   if (!isFiniteType(W)) {
1834     printFile(stderr,"lcells.mess",MESSAGE_DIR);
1835     return;
1836   }
1837 
1838   FiniteCoxGroup* Wf = dynamic_cast<FiniteCoxGroup*> (W);
1839 
1840   OutputFile file;
1841   OutputTraits& traits = Wf->outputTraits();
1842 
1843   printHeader(file.f(),lrCellWGraphsH,traits);
1844   printLRCellWGraphs(file.f(),Wf->lrCell(),Wf->kl(),W->interface(),traits);
1845 
1846   return;
1847 }
1848 
lrwgraph_f()1849 void lrwgraph_f()
1850 
1851 /*
1852   Prints out the two-sided wgraph of the current context.
1853 */
1854 
1855 {
1856   if (!W->isFullContext() && wgraph_warning) {
1857     printFile(stderr,"wgraph.mess",MESSAGE_DIR);
1858     printf("continue ? y/n\n");
1859     if (!yesNo())
1860       return;
1861     printf("print this message next time ? y/n\n");
1862     if (!yesNo())
1863       wgraph_warning = false;
1864   }
1865 
1866   W->fillMu();
1867   if (ERRNO) {
1868     Error(ERRNO);
1869     return;
1870   }
1871 
1872   OutputFile file;
1873   OutputTraits& traits = W->outputTraits();
1874 
1875   printHeader(file.f(),lrWGraphH,traits);
1876   printLRWGraph(file.f(),W->kl(),W->interface(),traits);
1877 
1878   return;
1879 }
1880 
lwgraph_f()1881 void lwgraph_f()
1882 
1883 /*
1884   Prints out the left wgraph of the current context.
1885 */
1886 
1887 {
1888   if (!W->isFullContext() && wgraph_warning) {
1889     printFile(stderr,"wgraph.mess",MESSAGE_DIR);
1890     printf("continue ? y/n\n");
1891     if (!yesNo())
1892       return;
1893     printf("print this message next time ? y/n\n");
1894     if (!yesNo())
1895       wgraph_warning = false;
1896   }
1897 
1898   W->fillMu();
1899   if (ERRNO) {
1900     Error(ERRNO);
1901     return;
1902   }
1903 
1904   OutputFile file;
1905   OutputTraits& traits = W->outputTraits();
1906 
1907   printHeader(file.f(),lWGraphH,traits);
1908   printLWGraph(file.f(),W->kl(),W->interface(),traits);
1909 
1910   return;
1911 }
1912 
matrix_f()1913 void matrix_f()
1914 
1915 /*
1916   Prints the Coxeter matrix.
1917 */
1918 
1919 {
1920   interactive::printMatrix(stdout,W);
1921 
1922   return;
1923 }
1924 
not_implemented_f()1925 void not_implemented_f()
1926 
1927 /*
1928   Response for not (yet) implemented commands.
1929 */
1930 
1931 {
1932   fprintf(stderr,"Sorry, not implemented yet\n");
1933   return;
1934 
1935 }
1936 
mu_f()1937 void mu_f()
1938 
1939 /*
1940   Response to the mu command. This prints out a single mu-coefficient,
1941   without details.
1942 */
1943 
1944 {
1945   static CoxWord g(0);
1946 
1947   fprintf(stdout,"first : ");
1948   g = interactive::getCoxWord(W);
1949   CoxNbr x = W->extendContext(g);
1950   if (ERRNO) {
1951     Error(ERRNO);
1952     return;
1953   }
1954 
1955   fprintf(stdout,"second : ");
1956   g = interactive::getCoxWord(W);
1957   if (ERRNO) {
1958     Error(ERRNO);
1959     return;
1960   }
1961   CoxNbr y = W->extendContext(g);
1962   if (ERRNO) {
1963     Error(ERRNO);
1964     return;
1965   }
1966 
1967   if (!W->inOrder(x,y)) {
1968     fprintf(stderr,"the two elements are not in Bruhat order\n");
1969     return;
1970   }
1971 
1972   KLCoeff mu = W->mu(x,y);
1973   if (ERRNO) {
1974     Error(ERRNO,x,y);
1975     return;
1976   }
1977 
1978   printf("%lu\n",static_cast<Ulong>(mu));
1979 
1980   return;
1981 }
1982 
pol_f()1983 void pol_f()
1984 
1985 /*
1986   Response to the pol command. This prints out a single polynomial, without
1987   details.
1988 */
1989 
1990 {
1991   static CoxWord g(0);
1992 
1993   fprintf(stdout,"first : ");
1994   g = interactive::getCoxWord(W);
1995   if (ERRNO) {
1996     Error(ERRNO);
1997     return;
1998   }
1999   CoxNbr x = W->extendContext(g);
2000   if (ERRNO) {
2001     Error(ERRNO);
2002     return;
2003   }
2004 
2005   fprintf(stdout,"second : ");
2006   g = interactive::getCoxWord(W);
2007   if (ERRNO) {
2008     Error(ERRNO);
2009     return;
2010   }
2011   CoxNbr y = W->extendContext(g);
2012   if (ERRNO) {
2013     Error(ERRNO);
2014     return;
2015   }
2016 
2017   if (!W->inOrder(x,y)) {
2018     fprintf(stderr,"the two elements are not in Bruhat order\n");
2019     return;
2020   }
2021 
2022   const kl::KLPol& pol = W->klPol(x,y);
2023   if (ERRNO) {
2024     Error(ERRNO,x,y);
2025     return;
2026   }
2027 
2028   print(stdout,pol,"q");
2029   printf("\n");
2030 
2031   return;
2032 }
2033 
q_f()2034 void q_f()
2035 
2036 /*
2037   Exits the current mode. If there is a problem on exit, the exit function
2038   has the option of setting an error, thus preventing the exit.
2039 */
2040 
2041 {
2042   CommandTree* tree = treeStack.top();
2043   tree->exit();
2044 
2045   if (ERRNO) {
2046     Error(ERRNO);
2047     return;
2048   }
2049 
2050   treeStack.pop();
2051 
2052   return;
2053 }
2054 
qq_f()2055 void qq_f()
2056 
2057 /*
2058   Exits the program.
2059 */
2060 
2061 {
2062   while(treeStack.size()) {
2063     CommandTree* tree = treeStack.top();
2064     tree->exit();
2065     treeStack.pop();
2066   }
2067 
2068   exit(0);
2069 }
2070 
rank_f()2071 void rank_f()
2072 
2073 /*
2074   Sets the rank.
2075 */
2076 
2077 {
2078   CoxGroup* Wloc = interactive::allocCoxGroup(W->type());
2079 
2080   if (ERRNO) {
2081     Error(ERRNO);
2082   }
2083   else {
2084     W = Wloc;
2085   }
2086 
2087   return;
2088 }
2089 
rcorder_f()2090 void rcorder_f()
2091 
2092 /*
2093   Prints the right cell order of the current group in a file. Works only for
2094   finite groups.
2095 */
2096 
2097 {
2098   if (!isFiniteType(W)) {
2099     printFile(stderr,"rcorder.mess",MESSAGE_DIR);
2100     return;
2101   }
2102 
2103   FiniteCoxGroup* Wf = dynamic_cast<FiniteCoxGroup*> (W);
2104 
2105   Wf->fullContext();
2106   if (ERRNO) {
2107     Error(ERRNO);
2108     return;
2109   }
2110 
2111   Wf->fillMu();
2112   if (ERRNO) {
2113     Error(ERRNO);
2114     return;
2115   }
2116 
2117   OutputFile file;
2118   OutputTraits& traits = Wf->outputTraits();
2119 
2120   printHeader(file.f(),rCOrderH,traits);
2121   printRCOrder(file.f(),Wf->kl(),Wf->interface(),traits);
2122 
2123   return;
2124 }
2125 
rcells_f()2126 void rcells_f()
2127 
2128 /*
2129   This function prints out the right cells in the group, together with the
2130   corresponding W-graphs.
2131 */
2132 
2133 {
2134   if (!isFiniteType(W)) {
2135     printFile(stderr,"rcells.mess",MESSAGE_DIR);
2136     return;
2137   }
2138 
2139   FiniteCoxGroup* Wf = dynamic_cast<FiniteCoxGroup*> (W);
2140 
2141   Wf->fullContext();
2142   if (ERRNO) {
2143     Error(ERRNO);
2144     return;
2145   }
2146 
2147   Wf->fillMu();
2148   if (ERRNO) {
2149     Error(ERRNO);
2150     return;
2151   }
2152 
2153   OutputFile file;
2154   OutputTraits& traits = Wf->outputTraits();
2155 
2156   printHeader(file.f(),rCellsH,traits);
2157   printRCells(file.f(),Wf->rCell(),Wf->kl(),Wf->interface(),traits);
2158 
2159   return;
2160 }
2161 
rcwgraphs_f()2162 void rcwgraphs_f()
2163 
2164 /*
2165   This function prints out the W-graphs of the right cells in the group.
2166   It works only for finite groups currently.
2167 */
2168 
2169 {
2170   if (!isFiniteType(W)) {
2171     printFile(stderr,"lcells.mess",MESSAGE_DIR);
2172     return;
2173   }
2174 
2175   FiniteCoxGroup* Wf = dynamic_cast<FiniteCoxGroup*> (W);
2176 
2177   OutputFile file;
2178   OutputTraits& traits = Wf->outputTraits();
2179 
2180   printHeader(file.f(),rCellWGraphsH,traits);
2181   printRCellWGraphs(file.f(),Wf->rCell(),Wf->kl(),W->interface(),traits);
2182 
2183   return;
2184 }
2185 
rwgraph_f()2186 void rwgraph_f()
2187 
2188 /*
2189   Prints out the right wgraph of the current context.
2190 */
2191 
2192 {
2193   if (!W->isFullContext() && wgraph_warning) {
2194     printFile(stderr,"wgraph.mess",MESSAGE_DIR);
2195     printf("continue ? y/n\n");
2196     if (!yesNo())
2197       return;
2198     printf("print this message next time ? y/n\n");
2199     if (!yesNo())
2200       wgraph_warning = false;
2201   }
2202 
2203   W->fillMu();
2204   if (ERRNO) {
2205     Error(ERRNO);
2206     return;
2207   }
2208 
2209   OutputFile file;
2210   OutputTraits& traits = W->outputTraits();
2211 
2212   printHeader(file.f(),rWGraphH,traits);
2213   printRWGraph(file.f(),W->kl(),W->interface(),traits);
2214 
2215   return;
2216 }
2217 
schubert_f()2218 void schubert_f()
2219 
2220 /*
2221   Response to the schubert command. This will print out the information
2222   corresponding to one element in the k-l basis, and the information on
2223   the singularities of the corresponding Schubert variety, in the format
2224   popularized by Goresky.
2225 */
2226 
2227 {
2228   static CoxWord g(0);
2229 
2230   printf("Enter your element (finish with a carriage-return) :\n");
2231   g = interactive::getCoxWord(W);
2232   if (ERRNO) {
2233     Error(ERRNO);
2234     return;
2235   }
2236 
2237   CoxNbr y = W->extendContext(g);
2238   if (ERRNO) {
2239     Error(ERRNO);
2240     return;
2241   }
2242 
2243   interactive::OutputFile file;
2244   OutputTraits& traits = W->outputTraits();
2245 
2246   printHeader(file.f(),closureH,traits);
2247   printClosure(file.f(),y,W->kl(),W->interface(),traits);
2248 
2249   return;
2250 }
2251 
show_f()2252 void show_f()
2253 
2254 /*
2255   Response to the show command. This maps out the computation of a Kazhdan-
2256   Lusztig polynomial, letting you choose the descent generator.
2257 
2258   If no generator is given, the default descent generator is used.
2259 */
2260 
2261 {
2262   static CoxWord g(0);
2263 
2264   fprintf(stdout,"first : ");
2265   g = interactive::getCoxWord(W);
2266   if (ERRNO) {
2267     Error(ERRNO);
2268     return;
2269   }
2270   CoxNbr x = W->extendContext(g);
2271   if (ERRNO) {
2272     Error(ERRNO);
2273     return;
2274   }
2275 
2276   fprintf(stdout,"second : ");
2277   g = interactive::getCoxWord(W);
2278   if (ERRNO) {
2279     Error(ERRNO);
2280     return;
2281   }
2282   CoxNbr y = W->extendContext(g);
2283   if (ERRNO) {
2284     Error(ERRNO);
2285     return;
2286   }
2287 
2288   if (!W->inOrder(x,y)) {
2289     fprintf(stderr,"the two elements are not in Bruhat order\n");
2290     return;
2291   }
2292 
2293   fprintf(stdout,"generator (carriage return for default) : ");
2294   LFlags f = W->descent(y);
2295   Generator s = interactive::getGenerator(W,f);
2296   if (ERRNO) {
2297     Error (ERRNO);
2298     return;
2299   }
2300 
2301   interactive::OutputFile file;
2302   showKLPol(file.f(),W->kl(),x,y,W->interface(),s);
2303 
2304   return;
2305 }
2306 
showmu_f()2307 void showmu_f()
2308 
2309 /*
2310   Response to the showmu command. This maps out the computation of a
2311   mu-coefficient, letting you choose the descent generator.
2312 
2313   If no generator is given, the default descent generator is used.
2314 */
2315 
2316 {
2317   static CoxWord g(0);
2318 
2319   fprintf(stdout,"first : ");
2320   g = interactive::getCoxWord(W);
2321   if (ERRNO) {
2322     Error(ERRNO);
2323     return;
2324   }
2325   CoxNbr x = W->extendContext(g);
2326   if (ERRNO) {
2327     Error(ERRNO);
2328     return;
2329   }
2330 
2331   fprintf(stdout,"second : ");
2332   g = interactive::getCoxWord(W);
2333   if (ERRNO) {
2334     Error(ERRNO);
2335     return;
2336   }
2337   CoxNbr y = W->extendContext(g);
2338   if (ERRNO) {
2339     Error(ERRNO);
2340     return;
2341   }
2342 
2343   if (!W->inOrder(x,y)) {
2344     fprintf(stderr,"the two elements are not in Bruhat order\n");
2345     return;
2346   }
2347 
2348   interactive::OutputFile file;
2349   showMu(file.f(),W->kl(),x,y,W->interface());
2350 
2351   return;
2352 }
2353 
slocus_f()2354 void slocus_f ()
2355 
2356 /*
2357   Response to the slocus command. Prints out the singular locus of the
2358   Schubert variety cl(X_y).
2359 */
2360 
2361 {
2362   static CoxWord g(0);
2363 
2364   printf("Enter your element (finish with a carriage-return) :\n");
2365 
2366   g = interactive::getCoxWord(W);
2367   if (ERRNO) {
2368     Error(ERRNO);
2369     return;
2370   }
2371   CoxNbr y = W->extendContext(g);
2372   if (ERRNO) {
2373     Error(ERRNO);
2374     return;
2375   }
2376 
2377   OutputFile file;
2378   OutputTraits& traits = W->outputTraits();
2379 
2380   printHeader(file.f(),slocusH,traits);
2381   printSingularLocus(file.f(),y,W->kl(),W->interface(),traits);
2382 
2383   return;
2384 }
2385 
sstratification_f()2386 void sstratification_f ()
2387 
2388 /*
2389   Response to the slocus command. Prints out the singular locus of the
2390   Schubert variety cl(X_y).
2391 */
2392 
2393 {
2394   static CoxWord g(0);
2395 
2396   printf("Enter your element (finish with a carriage-return) :\n");
2397 
2398   g = interactive::getCoxWord(W);
2399   if (ERRNO) {
2400     Error(ERRNO);
2401     return;
2402   }
2403   CoxNbr y = W->extendContext(g);
2404   if (ERRNO) {
2405     Error(ERRNO);
2406     return;
2407   }
2408 
2409   OutputFile file;
2410   OutputTraits& traits = W->outputTraits();
2411 
2412   printHeader(file.f(),sstratificationH,traits);
2413   printSingularStratification(file.f(),y,W->kl(),W->interface(),traits);
2414 
2415   return;
2416 }
2417 
type_f()2418 void type_f()
2419 
2420 /*
2421   This function sets the type of W, i.e., gets a type and rank from the
2422   user and sets W to a new group of that type and rank.
2423 */
2424 
2425 {
2426   CoxGroup* Wloc = interactive::allocCoxGroup();
2427 
2428   if (ERRNO) {
2429     Error(ERRNO);
2430   }
2431   else {
2432     delete W;
2433     wgraph_warning = true;
2434     W = Wloc;
2435   }
2436 
2437   return;
2438 }
2439 
uneq_f()2440 void uneq_f()
2441 
2442 /*
2443   Response to the uneq command.
2444 */
2445 
2446 {
2447   activate(uneqCommandTree());
2448   return;
2449 }
2450 
2451 namespace uneq {
2452 
klbasis_f()2453 void klbasis_f()
2454 
2455 /*
2456   Prints out one element in the k-l basis of the group, in the format
2457   defined by the current output mode.
2458 */
2459 
2460 {
2461   CoxWord g(0);
2462 
2463   printf("enter your element (finish with a carriage return) :\n");
2464   g = interactive::getCoxWord(W);
2465   if (ERRNO) {
2466     Error(ERRNO);
2467     return;
2468   }
2469 
2470   CoxNbr y = W->extendContext(g);
2471   if (ERRNO) {
2472     Error(ERRNO);
2473     return;
2474   }
2475 
2476   uneqkl::HeckeElt h(0);
2477 
2478   W->uneqcBasis(h,y);
2479   if (ERRNO) {
2480     Error(ERRNO);
2481     return;
2482   }
2483 
2484   interactive::OutputFile file;
2485   OutputTraits& traits = W->outputTraits();
2486 
2487   printHeader(file.f(),basisH,traits);
2488   printAsBasisElt(file.f(),h,W->schubert(),W->interface(),traits);
2489 
2490   return;
2491 }
2492 
lcells_f()2493 void lcells_f()
2494 
2495 /*
2496   This function prints out the left cells in the group.
2497 */
2498 
2499 {
2500   if (!isFiniteType(W)) {
2501     printFile(stderr,"lcells.mess",MESSAGE_DIR);
2502     return;
2503   }
2504 
2505   FiniteCoxGroup* Wf = dynamic_cast<FiniteCoxGroup*> (W);
2506 
2507   Wf->fullContext();
2508   if (ERRNO) {
2509     Error(ERRNO);
2510     return;
2511   }
2512 
2513   Wf->fillUEMu();
2514   if (ERRNO) {
2515     Error(ERRNO);
2516     return;
2517   }
2518 
2519   OutputFile file;
2520   OutputTraits& traits = Wf->outputTraits();
2521 
2522   printHeader(file.f(),lCellsH,traits);
2523   printLCells(file.f(),Wf->lUneqCell(),Wf->uneqkl(),Wf->interface(),traits);
2524 
2525   return;
2526 }
2527 
lcorder_f()2528 void lcorder_f()
2529 
2530 /*
2531   Prints the left cell order of the closure of the current group in a file.
2532   Works only for finite groups.
2533 */
2534 
2535 {
2536   if (!isFiniteType(W)) {
2537     printFile(stderr,"lcorder.mess",MESSAGE_DIR);
2538     return;
2539   }
2540 
2541   FiniteCoxGroup* Wf = dynamic_cast<FiniteCoxGroup*> (W);
2542 
2543   Wf->fullContext();
2544   if (ERRNO) {
2545     Error(ERRNO);
2546     return;
2547   }
2548 
2549   Wf->fillUEMu();
2550   if (ERRNO) {
2551     Error(ERRNO);
2552     return;
2553   }
2554 
2555   OutputFile file;
2556   OutputTraits& traits = Wf->outputTraits();
2557 
2558   printHeader(file.f(),lCOrderH,traits);
2559   printLCOrder(file.f(),Wf->uneqkl(),Wf->interface(),traits);
2560 
2561   return;
2562 }
2563 
lrcorder_f()2564 void lrcorder_f()
2565 
2566 /*
2567   Prints the two-sided cell order of the closure of the current group in a
2568   file. Works only for finite groups.
2569 */
2570 
2571 {
2572   if (!isFiniteType(W)) {
2573     printFile(stderr,"uneq/lrcorder.mess",MESSAGE_DIR);
2574     return;
2575   }
2576 
2577   FiniteCoxGroup* Wf = dynamic_cast<FiniteCoxGroup*> (W);
2578 
2579   Wf->fullContext();
2580   if (ERRNO) {
2581     Error(ERRNO);
2582     return;
2583   }
2584 
2585   Wf->fillUEMu();
2586   if (ERRNO) {
2587     Error(ERRNO);
2588     return;
2589   }
2590 
2591   OutputFile file;
2592   OutputTraits& traits = Wf->outputTraits();
2593 
2594   printHeader(file.f(),lrCOrderH,traits);
2595   printLRCOrder(file.f(),Wf->uneqkl(),Wf->interface(),traits);
2596 
2597   return;
2598 }
2599 
lrcells_f()2600 void lrcells_f()
2601 
2602 /*
2603   This function prints out the two-sided cells in the group. Works only for
2604   finite groups.
2605 */
2606 
2607 {
2608   if (!isFiniteType(W)) {
2609     printFile(stderr,"uneq/lrcells.mess",MESSAGE_DIR);
2610     return;
2611   }
2612 
2613   FiniteCoxGroup* Wf = dynamic_cast<FiniteCoxGroup*> (W);
2614 
2615   Wf->fullContext();
2616   if (ERRNO) {
2617     Error(ERRNO);
2618     return;
2619   }
2620 
2621   Wf->fillUEMu();
2622   if (ERRNO) {
2623     Error(ERRNO);
2624     return;
2625   }
2626 
2627   OutputFile file;
2628   OutputTraits& traits = Wf->outputTraits();
2629 
2630   printHeader(file.f(),lrCellsH,traits);
2631   printLRCells(file.f(),Wf->lrUneqCell(),Wf->uneqkl(),Wf->interface(),traits);
2632 
2633   return;
2634 }
2635 
mu_f()2636 void mu_f()
2637 
2638 /*
2639   Response to the "mu" command. Prints out a single mu-coefficient. When
2640   the generator s act on the left, we use the fact that mu(left_s,x,y) is
2641   equal to mu(right_s,x^{-1},y^{-1}) to go over to the right action. This
2642   is necessary because the mu-tables are kept only for right actions.
2643 */
2644 
2645 {
2646   static CoxWord g(0);
2647   bool leftAction = false;
2648 
2649   fprintf(stdout,"generator : ");
2650   Generator s = getGenerator(W);
2651 
2652   if (s >= W->rank()) { // action is on the left
2653     s -= W->rank();
2654     leftAction = true;
2655   }
2656 
2657   fprintf(stdout,"first : ");
2658   g = interactive::getCoxWord(W);
2659   if (leftAction)
2660     W->inverse(g);
2661   if (!W->isDescent(g,s)) { // mu(s,x,y) is undefined
2662     fprintf(stderr,"xs is greater than x\n");
2663     return;
2664   }
2665   CoxNbr x = W->extendContext(g);
2666   if (ERRNO) {
2667     Error(ERRNO);
2668     return;
2669   }
2670 
2671   fprintf(stdout,"second : ");
2672   g = interactive::getCoxWord(W);
2673   if (leftAction)
2674     W->inverse(g);
2675   if (W->isDescent(g,s)) { // mu(s,x,y) is undefined
2676     fprintf(stderr,"ys is smaller than y\n");
2677     return;
2678   }
2679   if (ERRNO) {
2680     Error(ERRNO);
2681     return;
2682   }
2683   CoxNbr y = W->extendContext(g);
2684   if (ERRNO) {
2685     Error(ERRNO);
2686     return;
2687   }
2688 
2689   if (x == y) {
2690     fprintf(stderr,"the two elements are equal\n");
2691     return;
2692   }
2693 
2694   if (!W->inOrder(x,y)) {
2695     fprintf(stderr,"the two elements are not in Bruhat order\n");
2696     return;
2697   }
2698 
2699   const uneqkl::MuPol& mu = W->uneqmu(s,x,y);
2700   if (ERRNO) {
2701     Error(ERRNO,x,y);
2702     return;
2703   }
2704 
2705   print(stdout,mu,"v");
2706   printf("\n");
2707 
2708   return;
2709 }
2710 
pol_f()2711 void pol_f()
2712 
2713 /*
2714   Response to the "pol" command. Prints out a single polynomial.
2715 */
2716 
2717 {
2718   static CoxWord g(0);
2719 
2720   fprintf(stdout,"first : ");
2721   g = interactive::getCoxWord(W);
2722   if (ERRNO) {
2723     Error(ERRNO);
2724     return;
2725   }
2726   CoxNbr x = W->extendContext(g);
2727   if (ERRNO) {
2728     Error(ERRNO);
2729     return;
2730   }
2731 
2732   fprintf(stdout,"second : ");
2733   g = interactive::getCoxWord(W);
2734   if (ERRNO) {
2735     Error(ERRNO);
2736     return;
2737   }
2738   CoxNbr y = W->extendContext(g);
2739   if (ERRNO) {
2740     Error(ERRNO);
2741     return;
2742   }
2743 
2744   if (!W->inOrder(x,y)) {
2745     fprintf(stderr,"the two elements are not in Bruhat order\n");
2746     return;
2747   }
2748 
2749   const uneqkl::KLPol& pol = W->uneqklPol(x,y);
2750   if (ERRNO) {
2751     Error(ERRNO,x,y);
2752     return;
2753   }
2754 
2755   print(stdout,pol,"q");
2756   printf("\n");
2757 
2758   return;
2759 }
2760 
rcells_f()2761 void rcells_f()
2762 
2763 /*
2764   This function prints out the left cells in the group. Works only for finite
2765   groups.
2766 */
2767 
2768 {
2769   if (!isFiniteType(W)) {
2770     printFile(stderr,"rcells.mess",MESSAGE_DIR);
2771     return;
2772   }
2773 
2774   FiniteCoxGroup* Wf = dynamic_cast<FiniteCoxGroup*> (W);
2775 
2776   Wf->fullContext();
2777   if (ERRNO) {
2778     Error(ERRNO);
2779     return;
2780   }
2781 
2782   Wf->fillUEMu();
2783   if (ERRNO) {
2784     Error(ERRNO);
2785     return;
2786   }
2787 
2788   OutputFile file;
2789   OutputTraits& traits = Wf->outputTraits();
2790 
2791   printHeader(file.f(),rCellsH,traits);
2792   printRCells(file.f(),Wf->rUneqCell(),Wf->uneqkl(),Wf->interface(),traits);
2793 
2794   return;
2795 }
2796 
rcorder_f()2797 void rcorder_f()
2798 
2799 /*
2800   Prints the right cell order of the current group in a file. Works only for
2801   finite groups.
2802 */
2803 
2804 {
2805   if (!isFiniteType(W)) {
2806     printFile(stderr,"rcorder.mess",MESSAGE_DIR);
2807     return;
2808   }
2809 
2810   FiniteCoxGroup* Wf = dynamic_cast<FiniteCoxGroup*> (W);
2811 
2812   Wf->fullContext();
2813   if (ERRNO) {
2814     Error(ERRNO);
2815     return;
2816   }
2817 
2818   Wf->fillUEMu();
2819   if (ERRNO) {
2820     Error(ERRNO);
2821     return;
2822   }
2823 
2824   OutputFile file;
2825   OutputTraits& traits = Wf->outputTraits();
2826 
2827   printHeader(file.f(),rCOrderH,traits);
2828   printRCOrder(file.f(),Wf->uneqkl(),Wf->interface(),traits);
2829 
2830   return;
2831 }
2832 
2833 };
2834 
2835 };
2836 
2837 namespace commands {
2838 
abort_f()2839 void interface::abort_f()
2840 
2841 /*
2842   Aborts the interface modification. Bypasses the exit function,
2843   so that there is no further checking of the abandoned choices.
2844 */
2845 
2846 {
2847   delete in_buf;
2848   in_buf = 0;
2849   treeStack.pop();
2850 
2851   return;
2852 }
2853 
alphabetic_f()2854 void interface::alphabetic_f()
2855 
2856 /*
2857   Sets i/o to the standard alphabetic conventions : the symbols are the
2858   alphabetic sequence, prefix and postfix are empty, and the separator is
2859   "." iff the rank is > 26.
2860 */
2861 
2862 {
2863   delete in_buf;
2864   in_buf = new GroupEltInterface(W->rank(),Alphabetic());
2865   W->interface().setIn(*in_buf);
2866   W->interface().setOut(*in_buf);
2867 
2868   return;
2869 }
2870 
bourbaki_f()2871 void interface::bourbaki_f()
2872 
2873 /*
2874   Sets Bourbaki conventions. This means that the ordering is reverted in
2875   types B and D, and symbols as well.
2876 
2877   NOTE : currently not implemented for affine groups.
2878 */
2879 
2880 {
2881   delete in_buf;
2882   in_buf = new GroupEltInterface(W->interface().inInterface());
2883   in::bourbaki_f();
2884   W->interface().setIn(*in_buf);
2885 
2886   delete in_buf;
2887   in_buf = new GroupEltInterface(W->interface().outInterface());
2888   out::bourbaki_f();
2889   W->interface().setOut(*in_buf);
2890 
2891   return;
2892 }
2893 
decimal_f()2894 void interface::decimal_f()
2895 
2896 /*
2897   Sets i/o to the standard decimal conventions : the symbols are the
2898   decimal sequence, prefix and postfix are empty, and the separator is
2899   "." iff the rank is > 9.
2900 */
2901 
2902 {
2903   delete in_buf;
2904   in_buf = new GroupEltInterface(W->rank(),Decimal());
2905   W->interface().setIn(*in_buf);
2906   W->interface().setOut(*in_buf);
2907 
2908   return;
2909 }
2910 
default_f()2911 void interface::default_f()
2912 
2913 /*
2914   Sets i/o settings to the default style. This means that we use decimal
2915   symbols, no prefix or postfix, and separator "." only when rank is >= 10.
2916   The ordering is the internal default ordering.
2917 */
2918 
2919 {
2920   delete in_buf;
2921   in_buf = new GroupEltInterface(W->rank());
2922 
2923   W->interface().setIn(*in_buf);
2924   W->interface().setOut(*in_buf);
2925 
2926   W->interface().setOrder(identityOrder(W->rank()));
2927   W->interface().setDescent(Default());
2928   W->setOutputTraits(Pretty());
2929 
2930   return;
2931 }
2932 
gap_f()2933 void interface::gap_f()
2934 
2935 /*
2936   Sets i/o settings to GAP style. This means first of all that Bourbaki
2937   conventions are adopted; decimal symbols are used for i/o with prefix
2938   "[", separator "," and postfix "]". Furthermore, output to files is
2939   done in GAP style, which produces files that are directly legible by
2940   GAP3.
2941 */
2942 
2943 {
2944   delete in_buf;
2945   in_buf = new GroupEltInterface(W->rank(),GAP());
2946 
2947   in::bourbaki_f();
2948   W->interface().setIn(*in_buf);
2949 
2950   out::bourbaki_f();
2951   W->interface().setOut(*in_buf);
2952   W->interface().setDescent(GAP());
2953   W->setOutputTraits(GAP());
2954 
2955   return;
2956 }
2957 
hexadecimal_f()2958 void interface::hexadecimal_f()
2959 
2960 /*
2961   Sets i/o to the standard hexadecimal conventions : the symbols are the
2962   hexadecimal sequence, prefix and postfix are empty, and the separator is
2963   "." iff the rank is > 15.
2964 */
2965 
2966 {
2967   delete in_buf;
2968   in_buf = new GroupEltInterface(W->rank(),Hexadecimal());
2969   W->interface().setIn(*in_buf);
2970 
2971   W->interface().setOut(*in_buf);
2972 
2973   return;
2974 }
2975 
in_f()2976 void interface::in_f()
2977 
2978 {
2979   activate(inCommandTree());
2980   return;
2981 }
2982 
ordering_f()2983 void interface::ordering_f()
2984 
2985 /*
2986   Allows the user to change the generator ordering.
2987 */
2988 
2989 {
2990   static Permutation in_order(W->rank());
2991 
2992   changeOrdering(W,in_order);
2993 
2994   if (ERRNO) {
2995     Error(ERRNO);
2996     return;
2997   }
2998 
2999   W->setOrdering(in_order);
3000 
3001   return;
3002 }
3003 
out_f()3004 void interface::out_f()
3005 
3006 {
3007   activate(outCommandTree());
3008   return;
3009 }
3010 
permutation_f()3011 void interface::permutation_f()
3012 
3013 /*
3014   Activates permutation i/o.
3015 */
3016 
3017 {
3018   using namespace coxeter;
3019 
3020   if (!isTypeA(W->type())) {
3021     printFile(stderr,"permutation.mess",MESSAGE_DIR);
3022     return;
3023   }
3024 
3025   TypeACoxGroup* WA = dynamic_cast<TypeACoxGroup*>(W);
3026 
3027   WA->setPermutationInput(true);
3028   WA->setPermutationOutput(true);
3029 
3030   W->interface().setOrder(identityOrder(W->rank()));
3031   W->interface().setDescent(Default());
3032   W->setOutputTraits(Pretty());
3033 
3034   return;
3035 }
3036 
symbol_f()3037 void interface::symbol_f()
3038 
3039 /*
3040   Resets a symbol in in_buf (this will become either an input or an output
3041   symbol).
3042 */
3043 
3044 {
3045   static String buf(0);
3046 
3047   const Interface& I = W->interface();
3048   Generator s = undef_generator;
3049   reset(buf);
3050 
3051   do {
3052     if (ERRNO)
3053       Error(ERRNO);
3054     printf("enter the generator symbol you wish to change, ? to abort:\n");
3055     getInput(stdin,buf,0);
3056     if (buf[0] == '?')
3057       return;
3058     io::skipSpaces(buf,0);
3059     Token tok;
3060     I.symbolTree().find(buf,0,tok);
3061     if (tokenType(tok) != generator_type)/* error */
3062       ERRNO = NOT_GENERATOR;
3063     else
3064       s = tok-1;
3065   } while (ERRNO);
3066 
3067   printf("enter the new symbol (finish with a carriage return):\n");
3068   getInput(stdin,buf,0);
3069   in_buf->setSymbol(s,buf);
3070 
3071   return;
3072 }
3073 
terse_f()3074 void interface::terse_f()
3075 
3076 /*
3077   Sets i/o settings to terse style. This style is meant for outputting files
3078   that are easily parsed by computer. Th ordering of the generators is left
3079   untouched, and can be set independently by the user. Decimal output symbols
3080   are chosen, prefix is set to "[", postfix to "]" and separator to ",".
3081 */
3082 
3083 {
3084   delete in_buf;
3085   in_buf = new GroupEltInterface(W->rank(),GAP());
3086   W->interface().setIn(*in_buf);
3087   W->interface().setOut(*in_buf);
3088 
3089   W->interface().setDescent(Default());
3090   W->setOutputTraits(Terse());
3091 
3092   return;
3093 }
3094 
alphabetic_f()3095 void interface::in::alphabetic_f()
3096 
3097 /*
3098   Sets the input symbols to the alphabetic sequence.
3099 */
3100 
3101 {
3102   const String* alpha = alphabeticSymbols(in_buf->symbol.size());
3103 
3104   for (Ulong j = 0; j < in_buf->symbol.size(); ++j) {
3105     in_buf->symbol[j] = alpha[j];
3106   }
3107 
3108   return;
3109 }
3110 
bourbaki_f()3111 void interface::in::bourbaki_f()
3112 
3113 /*
3114   Sets Bourbaki conventions for input. This means reverting the ordering
3115   of the input symbols in types B and D.
3116 */
3117 
3118 {
3119   const Type& x = W->type();
3120 
3121   if (!isFiniteType(x))
3122     return;
3123   if (!(isTypeB(x) || isTypeD(x)))
3124     return;
3125 
3126   for (Generator s = 0; s < W->rank(); ++s) {
3127     in_buf->symbol[s] = W->interface().inSymbol(W->rank()-s-1);
3128   }
3129 
3130   return;
3131 }
3132 
decimal_f()3133 void interface::in::decimal_f()
3134 
3135 /*
3136   Sets the input symbols to the decimal sequence.
3137 */
3138 
3139 {
3140   const String* dec = decimalSymbols(in_buf->symbol.size());
3141 
3142   for (Ulong j = 0; j < in_buf->symbol.size(); ++j) {
3143     in_buf->symbol[j] = dec[j];
3144   }
3145 
3146   return;
3147 }
3148 
default_f()3149 void interface::in::default_f()
3150 
3151 /*
3152   Sets the input interface to the default style.
3153 */
3154 
3155 {
3156   delete in_buf;
3157   in_buf = new GroupEltInterface(W->rank());
3158 
3159   return;
3160 }
3161 
gap_f()3162 void interface::in::gap_f()
3163 
3164 /*
3165   Sets the input interface to GAP style, and enforces Bourbaki conventions.
3166 */
3167 
3168 {
3169   delete in_buf;
3170   in_buf = new GroupEltInterface(W->rank(),GAP());
3171   in::bourbaki_f();
3172 
3173   return;
3174 }
3175 
hexadecimal_f()3176 void interface::in::hexadecimal_f()
3177 
3178 /*
3179   Sets the input symbols to the hexadecimal sequence.
3180 */
3181 
3182 {
3183   const String* hex = hexSymbols(in_buf->symbol.size());
3184 
3185   for (Ulong j = 0; j < in_buf->symbol.size(); ++j) {
3186     in_buf->symbol[j] = hex[j];
3187   }
3188 
3189   return;
3190 }
3191 
permutation_f()3192 void interface::in::permutation_f()
3193 
3194 /*
3195   Sets input to permutation mode (type A only.)
3196 */
3197 
3198 {
3199   using namespace coxeter;
3200 
3201   if (!isTypeA(W->type())) {
3202     printFile(stderr,"permutation.mess",MESSAGE_DIR);
3203     return;
3204   }
3205 
3206   TypeACoxGroup* WA = dynamic_cast<TypeACoxGroup*>(W);
3207   WA->setPermutationInput(true);
3208 
3209   delete in_buf;
3210   in_buf = 0;
3211 
3212   return;
3213 }
3214 
postfix_f()3215 void interface::in::postfix_f()
3216 
3217 /*
3218   Resets the input postfix.
3219 */
3220 
3221 {
3222   printf("Enter the new input postfix (finish with a carriage return):\n");
3223   String buf(0);
3224   getInput(stdin,buf,0);
3225   in_buf->setPostfix(buf);
3226   return;
3227 }
3228 
prefix_f()3229 void interface::in::prefix_f()
3230 
3231 /*
3232   Resets the input prefix.
3233 */
3234 
3235 {
3236   printf("Enter the new input prefix (finish with a carriage return):\n");
3237   String buf(0);
3238   getInput(stdin,buf,0);
3239   in_buf->setPrefix(buf);
3240   return;
3241 }
3242 
separator_f()3243 void interface::in::separator_f()
3244 
3245 /*
3246   Resets the input separator.
3247 */
3248 
3249 {
3250   printf("Enter the new input separator (finish with a carriage return):\n");
3251   String buf(0);
3252   getInput(stdin,buf,0);
3253   in_buf->setSeparator(buf);
3254   return;
3255 }
3256 
terse_f()3257 void interface::in::terse_f()
3258 
3259 /*
3260   Sets the input interface to terse style (the same as GAP style).
3261 */
3262 
3263 {
3264   delete in_buf;
3265   in_buf = new GroupEltInterface(W->rank(),GAP());
3266 
3267   return;
3268 }
3269 
alphabetic_f()3270 void interface::out::alphabetic_f()
3271 
3272 /*
3273   Changes the output symbols to hexadecimal.
3274 */
3275 
3276 {
3277   const String* alpha = alphabeticSymbols(in_buf->symbol.size());
3278 
3279   for (Ulong j = 0; j < in_buf->symbol.size(); ++j) {
3280     in_buf->symbol[j] = alpha[j];
3281   }
3282 
3283   return;
3284 }
3285 
bourbaki_f()3286 void interface::out::bourbaki_f()
3287 
3288 /*
3289   Sets Bourbaki conventions for input. This means reverting the ordering
3290   of the output symbols in types B and D, and setting the output ordering
3291   to the reverse of the default one.
3292 */
3293 
3294 {
3295   const Type& x = W->type();
3296 
3297   if (!isFiniteType(x))
3298     return;
3299   if (!(isTypeB(x) || isTypeD(x))) {
3300     W->setOrdering(identityOrder(W->rank()));
3301     return;
3302   }
3303 
3304   for (Generator s = 0; s < W->rank(); ++s) {
3305     in_buf->symbol[s] = W->interface().outSymbol(W->rank()-s-1);
3306   }
3307 
3308   Permutation a(W->rank());
3309 
3310   for (Generator s = 0; s < W->rank(); ++s) {
3311     a[s] = W->rank()-1-s;
3312   }
3313 
3314   W->setOrdering(a);
3315 
3316   return;
3317 }
3318 
decimal_f()3319 void interface::out::decimal_f()
3320 
3321 /*
3322   Changes the output symbols to decimal.
3323 */
3324 
3325 {
3326   const String* dec = decimalSymbols(in_buf->symbol.size());
3327 
3328   for (Ulong j = 0; j < in_buf->symbol.size(); ++j) {
3329     in_buf->symbol[j] = dec[j];
3330   }
3331 
3332   return;
3333 }
3334 
default_f()3335 void interface::out::default_f()
3336 
3337 /*
3338   Sets output styles to the default style.
3339 */
3340 
3341 {
3342   delete in_buf;
3343   in_buf = new GroupEltInterface(W->rank());
3344   W->setOrdering(identityOrder(W->rank()));
3345 
3346   W->setOutputTraits(Pretty());
3347 
3348   return;
3349 }
3350 
gap_f()3351 void interface::out::gap_f()
3352 
3353 /*
3354   Sets output styles to GAP style, and enforces Bourbaki conventions.
3355 */
3356 
3357 {
3358   delete in_buf;
3359   in_buf = new GroupEltInterface(W->rank(),GAP());
3360   W->setOrdering(identityOrder(W->rank()));
3361   out::bourbaki_f();
3362 
3363   W->interface().setDescent(GAP());
3364   W->interface().setOut(*in_buf); // has to be done here so that output traits
3365                                   // will be correct.
3366   W->setOutputTraits(GAP());
3367 
3368   return;
3369 }
3370 
hexadecimal_f()3371 void interface::out::hexadecimal_f()
3372 
3373 /*
3374   Changes the output symbols to hexadecimal.
3375 */
3376 
3377 {
3378   const String* hex = hexSymbols(in_buf->symbol.size());
3379 
3380   for (Ulong j = 0; j < in_buf->symbol.size(); ++j) {
3381     in_buf->symbol[j] = hex[j];
3382   }
3383 
3384   return;
3385 }
3386 
permutation_f()3387 void interface::out::permutation_f()
3388 
3389 /*
3390   Sets output to permutation mode (type A only.)
3391 */
3392 
3393 {
3394   using namespace coxeter;
3395 
3396   if (!isTypeA(W->type())) {
3397     printFile(stderr,"permutation.mess",MESSAGE_DIR);
3398     return;
3399   }
3400 
3401   TypeACoxGroup* WA = dynamic_cast<TypeACoxGroup*>(W);
3402 
3403   WA->setPermutationOutput(true);
3404 
3405   W->interface().setOrder(identityOrder(W->rank()));
3406   W->interface().setDescent(Default());
3407   W->setOutputTraits(Pretty());
3408 
3409   delete in_buf;
3410   in_buf = 0;
3411 
3412   return;
3413 }
3414 
postfix_f()3415 void interface::out::postfix_f()
3416 
3417 /*
3418   Resets the output postfix.
3419 */
3420 
3421 {
3422   printf("enter the new output postfix (finish with a carriage return):\n");
3423   String buf(0);
3424   getInput(stdin,buf,0);
3425   in_buf->setPostfix(buf);
3426   return;
3427 }
3428 
prefix_f()3429 void interface::out::prefix_f()
3430 
3431 /*
3432   Resets the output prefix.
3433 */
3434 
3435 {
3436   printf("Enter the new output prefix (finish with a carriage return):\n");
3437   String buf(0);
3438   getInput(stdin,buf,0);
3439   in_buf->setPrefix(buf);
3440   return;
3441 }
3442 
separator_f()3443 void interface::out::separator_f()
3444 
3445 /*
3446   Resets the output separator.
3447 */
3448 
3449 {
3450   printf("Enter the new output separator (finish with a carriage return):\n");
3451   String buf(0);
3452   getInput(stdin,buf,0);
3453   in_buf->setSeparator(buf);
3454   return;
3455 }
3456 
terse_f()3457 void interface::out::terse_f()
3458 
3459 /*
3460   Sets output styles to terse style (the same as GAP style).
3461 */
3462 
3463 {
3464   delete in_buf;
3465   in_buf = new GroupEltInterface(W->rank(),GAP());
3466 
3467   W->interface().setDescent(Default());
3468   W->interface().setOut(*in_buf); // has to be done here so that output
3469                                   // traits will be correct
3470   W->setOutputTraits(Terse());
3471 
3472   return;
3473 }
3474 
3475 };
3476 
3477 /*****************************************************************************
3478 
3479         Chapter VI -- Miscellaneous.
3480 
3481   This section contains some auxiliary functions :
3482 
3483   - printCommands(file,tree) : prints info about the various commands
3484     on the tree;
3485   - printCommandTree(file,cell) : the recursive function doing the actual
3486     work;
3487   - interface_entry() : entry function for the interface mode;
3488   - interface_exit() : exit function for the interface mode;
3489   - interface::in_entry() : entry function for the interface::in mode;
3490   - interface::in_exit() : exit function for the interface::in mode;
3491   - interface::out_entry() : entry function for the interface::out mode;
3492   - interface::out_exit() : exit function for the interface::out mode;
3493   - main_entry() : entry function for the main mode;
3494   - main_exit() : exit function for the main mode;
3495   - uneq_entry() : entry function for the uneq mode;
3496   - uneq_exit() : exit function for the uneq mode;
3497 
3498  *****************************************************************************/
3499 
3500 namespace commands {
3501 
printCommands(FILE * file,CommandTree * tree)3502 void printCommands(FILE* file, CommandTree* tree)
3503 
3504 /*
3505   Prints one line for each command on the tree (sorted in alphabetical order)
3506   with the name of the command and the information contained in the tag field.
3507 */
3508 
3509 {
3510   printCommandTree(file,tree->root()->left);
3511   return;
3512 }
3513 
3514 };
3515 
currentGroup()3516 CoxGroup* commands::currentGroup()
3517 
3518 /*
3519   Returns the "current" Coxeter group.
3520 
3521   NOTE : this will probably have to be refined in the future.
3522 */
3523 
3524 {
3525   return W;
3526 }
3527 
3528 namespace {
3529 
printCommandTree(FILE * file,DictCell<CommandData> * cell)3530 void printCommandTree(FILE* file, DictCell<CommandData>* cell)
3531 
3532 {
3533   if (cell == 0)
3534     return;
3535 
3536   if (cell->fullname) { /* print command info */
3537     CommandData* cd = cell->value();
3538     fprintf(file,"  - %s : %s;\n",cd->name.ptr(),cd->tag.ptr());
3539   };
3540 
3541   printCommandTree(file,cell->left);
3542   printCommandTree(file,cell->right);
3543 
3544   return;
3545 }
3546 
interface_entry()3547 void interface_entry()
3548 
3549 {
3550   commands::interface::in_buf = new GroupEltInterface(W->rank());
3551   return;
3552 }
3553 
interface_exit()3554 void interface_exit()
3555 
3556 {
3557   delete commands::interface::in_buf;
3558   commands::interface::in_buf = 0;
3559   return;
3560 }
3561 
main_entry()3562 void main_entry()
3563 
3564 /*
3565   Sets the type and rank. This is used as entry function for the main mode,
3566   and as the function that restarts the program when we change the type.
3567 
3568   NOTE : error handling should be done by the calling function.
3569 
3570   NOTE : something should be done about deallocating before reallocating!
3571 */
3572 
3573 {
3574   W = interactive::allocCoxGroup();
3575 
3576   /* an error may be set here */
3577 
3578   return;
3579 }
3580 
3581 };
3582 
3583 namespace commands {
3584 
in_entry()3585 void interface::in_entry()
3586 
3587 /*
3588   Entry function to the input interface modification mode. The global variable
3589   in_buf is originally set to value for the current group.
3590 */
3591 
3592 {
3593   Permutation a(W->interface().order());
3594   a.inverse();
3595 
3596   printf("current input symbols are the following :\n\n");
3597   printInterface(stdout,W->interface().inInterface(),a);
3598   printf("\n");
3599 
3600   in_buf = new GroupEltInterface(W->interface().inInterface());
3601 
3602   return;
3603 }
3604 
in_exit()3605 void interface::in_exit()
3606 
3607 /*
3608   Exit function from the input modification mode. It checks if the
3609   modifications made by the user are consistent with the ones that will
3610   remain from the old interface; if yes, it confirms the modifications
3611   and exits peacefully; if not, it prints out the problems and keeps
3612   the user in the mode.
3613 */
3614 
3615 {
3616   if (in_buf == 0) // hack to prevent execution in special cases
3617     return;
3618 
3619   Permutation a(W->interface().order());
3620   a.inverse();
3621 
3622   /* at this point in_buf holds the full putative new interface; we
3623    need to check for reserved or repeated non-empty symbols */
3624 
3625   const String* str = checkLeadingWhite(*in_buf);
3626 
3627   if (str) {
3628     Error(LEADING_WHITESPACE,in_buf,&W->interface().inInterface(),&a,str);
3629     goto error_exit;
3630   }
3631 
3632   str = checkReserved(*in_buf,W->interface());
3633 
3634   if (str) {
3635     Error(RESERVED_SYMBOL,in_buf,&W->interface().inInterface(),&a,str);
3636     goto error_exit;
3637   }
3638 
3639   if (!checkRepeated(*in_buf)) {
3640     Error(REPEATED_SYMBOL,in_buf,&W->interface().inInterface(),&a);
3641     goto error_exit;
3642   }
3643 
3644   /* if we reach this point, the new interface is ok */
3645 
3646   printf("new input symbols:\n\n");
3647   printInterface(stdout,*in_buf,a);
3648   printf("\n");
3649 
3650   W->interface().setIn(*in_buf);
3651 
3652   return;
3653 
3654  error_exit:
3655   ERRNO = ERROR_WARNING;
3656   return;
3657 }
3658 
out_entry()3659 void interface::out_entry()
3660 
3661 /*
3662   Entry function to the output interface modification mode. The global variable
3663   in_buf is originally set to value for the current group.
3664 */
3665 
3666 {
3667   delete in_buf;
3668   in_buf = new GroupEltInterface(W->interface().outInterface());
3669 
3670   Permutation a(W->interface().order());
3671   a.inverse();
3672 
3673   printf("current output symbols are the following :\n\n");
3674   printInterface(stdout,*in_buf,W->interface().inInterface(),a);
3675   printf("\n");
3676 
3677   return;
3678 }
3679 
out_exit()3680 void interface::out_exit()
3681 
3682 /*
3683   Exit function for the output modification mode. No checking is necessary
3684   here.
3685 */
3686 
3687 {
3688   if (in_buf == 0) // hack to prevent execution in special cases
3689     return;
3690 
3691   Permutation a(W->interface().order());
3692   a.inverse();
3693 
3694   printf("new output symbols:\n\n");
3695   printInterface(stdout,*in_buf,W->interface().inInterface(),a);
3696   printf("\n");
3697 
3698   W->interface().setOut(*in_buf);
3699 
3700   return;
3701 }
3702 
3703 };
3704 
3705 namespace {
3706 
main_exit()3707 void main_exit()
3708 
3709 /*
3710   Symmetric function to main_entry. Should undo what main_entry did.
3711 */
3712 
3713 {
3714   delete W;
3715   wgraph_warning = true;
3716   return;
3717 }
3718 
uneq_entry()3719 void uneq_entry()
3720 
3721 {
3722   W->activateUEKL();
3723   return;
3724 }
3725 
uneq_exit()3726 void uneq_exit()
3727 
3728 /*
3729   We keep the unequal-parameter context, because one might want to go back
3730   and forth between the unequal and the ordinary case.
3731 */
3732 
3733 {
3734   return;
3735 }
3736 
3737 };
3738