1 //   Copyright (c)  2013-2015  Mario Albert
2 
3 //   This file is part of the source of CoCoALib, the CoCoA Library.
4 
5 //   CoCoALib is free software: you can redistribute it and/or modify
6 //   it under the terms of the GNU General Public License as published by
7 //   the Free Software Foundation, either version 3 of the License, or
8 //   (at your option) any later version.
9 
10 //   CoCoALib is distributed in the hope that it will be useful,
11 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //   GNU General Public License for more details.
14 
15 //   You should have received a copy of the GNU General Public License
16 //   along with CoCoALib.  If not, see <http://www.gnu.org/licenses/>.
17 
18 
19 #include "CoCoA/BuildInfo.H"
20 #include "CoCoA/GlobalManager.H"
21 #include "CoCoA/TmpPBMill.H"
22 #include "CoCoA/TmpMorseElement.H"
23 #include "CoCoA/RingQQ.H"
24 #include "CoCoA/error.H"
25 
26 using namespace std;
27 using namespace CoCoA;
28 using namespace CoCoA::Involutive;
29 
30 
DynamicBitsetToBool(const DynamicBitset & DynBitset)31 std::vector<bool> DynamicBitsetToBool(const DynamicBitset& DynBitset)
32 {
33   std::vector<bool> result;
34   long length(len(DynBitset));
35   for (long i = 0; i < length; ++i)
36   {
37     result.push_back(DynBitset.Iam1At(i));
38   }
39   return result;
40 }
41 
VectorBoolToDynamicBitset(const std::vector<bool> & bools)42 DynamicBitset VectorBoolToDynamicBitset(const std::vector<bool>& bools)
43 {
44   DynamicBitset result(bools.size());
45   long counter(0);
46   for (std::vector<bool>::const_iterator i = bools.begin(); i != bools.end(); ++i)
47   {
48     result.mySet(counter, *i);
49     ++counter;
50   }
51   return result;
52 }
53 
54 
55 
test_myDynamicBitsetToLong()56 void test_myDynamicBitsetToLong()
57 {
58   DynamicBitset bitset(5);
59   std::vector<long> output;
60 
61   output = myDynamicBitsetToLong(bitset);
62   CoCoA_ASSERT_ALWAYS(len(output) == 0);
63 
64   bitset.mySet(0);
65   output = myDynamicBitsetToLong(bitset);
66   CoCoA_ASSERT_ALWAYS(len(output) == 1);
67   CoCoA_ASSERT_ALWAYS(output[0] == 0);
68 
69   bitset.mySet(3);
70   output = myDynamicBitsetToLong(bitset);
71   CoCoA_ASSERT_ALWAYS(len(output) == 2);
72   CoCoA_ASSERT_ALWAYS(output[0] == 0);
73   CoCoA_ASSERT_ALWAYS(output[1] == 3);
74 
75   bitset.mySet(1);
76   bitset.mySet(2);
77   bitset.mySet(4);
78   output = myDynamicBitsetToLong(bitset);
79   CoCoA_ASSERT_ALWAYS(len(output) == 5);
80   CoCoA_ASSERT_ALWAYS(output[0] == 0);
81   CoCoA_ASSERT_ALWAYS(output[1] == 1);
82   CoCoA_ASSERT_ALWAYS(output[2] == 2);
83   CoCoA_ASSERT_ALWAYS(output[3] == 3);
84   CoCoA_ASSERT_ALWAYS(output[4] == 4);
85 }
86 
87 
test_myVectorLongToDynamicBitset()88 void test_myVectorLongToDynamicBitset()
89 {
90   long ArrayLongs1[] = {2};
91   std::vector<long> longs1 (ArrayLongs1, ArrayLongs1 + sizeof(ArrayLongs1) / sizeof(long) );
92   DynamicBitset bitset = myVectorLongToDynamicBitset(longs1, 5);
93   CoCoA_ASSERT_ALWAYS(len(bitset) == 5);
94   CoCoA_ASSERT_ALWAYS(Is1At(bitset,0) == false);
95   CoCoA_ASSERT_ALWAYS(Is1At(bitset,1) == false);
96   CoCoA_ASSERT_ALWAYS(Is1At(bitset,2) == true);
97   CoCoA_ASSERT_ALWAYS(Is1At(bitset,3) == false);
98   CoCoA_ASSERT_ALWAYS(Is1At(bitset,4) == false);
99 
100   long ArrayLongs2[] = {0, 2};
101   std::vector<long> longs2 (ArrayLongs2, ArrayLongs2 + sizeof(ArrayLongs2) / sizeof(long) );
102   bitset = myVectorLongToDynamicBitset(longs2, 5);
103   CoCoA_ASSERT_ALWAYS(len(bitset) == 5);
104   CoCoA_ASSERT_ALWAYS(Is1At(bitset,0) == true);
105   CoCoA_ASSERT_ALWAYS(Is1At(bitset,1) == false);
106   CoCoA_ASSERT_ALWAYS(Is1At(bitset,2) == true);
107   CoCoA_ASSERT_ALWAYS(Is1At(bitset,3) == false);
108   CoCoA_ASSERT_ALWAYS(Is1At(bitset,4) == false);
109 
110   long ArrayLongs3[] = {0,1,2,3,4};
111   std::vector<long> longs3 (ArrayLongs3, ArrayLongs3 + sizeof(ArrayLongs3) / sizeof(long) );
112   bitset = myVectorLongToDynamicBitset(longs3, 5);
113   CoCoA_ASSERT_ALWAYS(len(bitset) == 5);
114   CoCoA_ASSERT_ALWAYS(Is1At(bitset,0) == true);
115   CoCoA_ASSERT_ALWAYS(Is1At(bitset,1) == true);
116   CoCoA_ASSERT_ALWAYS(Is1At(bitset,2) == true);
117   CoCoA_ASSERT_ALWAYS(Is1At(bitset,3) == true);
118   CoCoA_ASSERT_ALWAYS(Is1At(bitset,4) == true);
119 
120   std::vector<long> longs4;
121   bitset = myVectorLongToDynamicBitset(longs4, 5);
122   CoCoA_ASSERT_ALWAYS(len(bitset) == 5);
123   CoCoA_ASSERT_ALWAYS(Is1At(bitset,0) == false);
124   CoCoA_ASSERT_ALWAYS(Is1At(bitset,1) == false);
125   CoCoA_ASSERT_ALWAYS(Is1At(bitset,2) == false);
126   CoCoA_ASSERT_ALWAYS(Is1At(bitset,3) == false);
127   CoCoA_ASSERT_ALWAYS(Is1At(bitset,4) == false);
128 }
129 
130 
test_operators()131 void test_operators()
132 {
133   ring QQ = RingQQ();
134   SparsePolyRing PolyRing = NewPolyRing(QQ, SymbolRange("x",0,4), StdDegLex);
135   const vector<RingElem> x = indets(PolyRing);
136   vector<RingElem>input;
137   DynamicBitset wedge(5);
138   PPMonoidElem RightFactor(one(PPM(PolyRing)));
139 
140   RingElem BasisElement1(x[1] * x[2] * x[0]);
141   DynamicBitset ncrit1(5);
142   long lexpos1(1);
143   RingElem BasisElement2(x[1] * x[2] * x[0]);
144   DynamicBitset ncrit2(5);
145   long lexpos2(1);
146   std::vector<MorseElement::JBElem> TestBasis;
147   TestBasis.push_back(MorseElement::JBElem(BasisElement1, ncrit1, lexpos1));
148   TestBasis.push_back(MorseElement::JBElem(BasisElement2, ncrit2, lexpos2));
149   std::vector<MorseElement::JBElem>::iterator TBIter1(TestBasis.begin());
150   std::vector<MorseElement::JBElem>::iterator TBIter2(TestBasis.begin());
151   ++TBIter2;
152 
153   MorseElement m1(wedge, RightFactor, TBIter1);
154   MorseElement m2(wedge, RightFactor, TBIter2);
155   //first test
156 
157   CoCoA_ASSERT_ALWAYS(m1 == m2);
158   CoCoA_ASSERT_ALWAYS(m1 <= m2);
159   CoCoA_ASSERT_ALWAYS(m1 >= m2);
160 
161   //second test
162   wedge.mySet(0);
163   m2.mySetWedgeProduct(wedge);
164   //number of true in wedge: 0 < 1
165   CoCoA_ASSERT_ALWAYS(m1 < m2);
166 
167   //third test
168   wedge.mySet(0, false);
169   wedge.mySet(1);
170   m1.mySetWedgeProduct(wedge);
171   // number of trues in wedge: 1 == 1, but x0 * x1^2 * x2 < x0^2 * x1 * x2
172   CoCoA_ASSERT_ALWAYS(m1 < m2);
173 
174   //fourth test
175 
176   TBIter1->elem   = x[0] * x[2];
177   TBIter1->lexPos = 1;
178   TBIter2->elem   = x[1] * x[2];
179   TBIter2->lexPos = 2;
180   // number of trues in wedge: 1 == 1
181   // x1 * 1 * (x0 * x2) == x0 * 1 * (x1 * x2)
182   // m1.ncrit == m2.ncrit
183   // m1.wedgeProduct = (0,1,0,0,0), m2.wedgeProduct = (1,0,0,0,0) => m1 < m2
184   CoCoA_ASSERT_ALWAYS(m1 < m2);
185 
186   //fifth test
187   ncrit1.mySet(4);
188   ncrit1.mySet(3);
189   ncrit1.mySet(2);
190   TBIter1->multVars = ncrit1;
191   // number of trues in wedge: 1 == 1
192   // x1 * 1 * (x0 * x2) == x0 * 1 * (x1 * x2)
193   // m1.ncrit == (0,0,1,1,1) > (0,0,0,0,0) == m2.ncrit => m1 < m2
194   CoCoA_ASSERT_ALWAYS(m1 < m2);
195   CoCoA_ASSERT_ALWAYS(m2 > m1);
196 }
197 
test_myEpsilon()198 void test_myEpsilon()
199 {
200   ring QQ = RingQQ();
201   SparsePolyRing PolyRing = NewPolyRing(QQ, SymbolRange("x",0,4), StdDegLex);
202   const vector<RingElem> x = indets(PolyRing);
203   vector<RingElem>input;
204   RingElem LeftFactor(x[0]+x[1]+x[2]+x[3]+x[4]);
205   DynamicBitset wedge(5);
206   PPMonoidElem RightFactor(one(PPM(PolyRing)));
207   RingElem BasisElement(x[1] * x[2] * x[0]);
208   DynamicBitset ncrit(5);
209   std::vector<MorseElement::JBElem> TestBasis;
210   TestBasis.push_back(MorseElement::JBElem(BasisElement, ncrit, 1));
211 
212   //first test
213   MorseElement m1(wedge, RightFactor, TestBasis.begin());
214 
215   DynamicBitset bitset(5);
216   m1.mySetWedgeProduct(bitset);
217   CoCoA_ASSERT_ALWAYS( 1 == m1.myEpsilon(3, 4));
218 
219   bitset.mySet(3, true);
220   bitset.mySet(2, true);
221   m1.mySetWedgeProduct(bitset);
222   CoCoA_ASSERT_ALWAYS( -1 == m1.myEpsilon(3, 4));
223   CoCoA_ASSERT_ALWAYS( 1 == m1.myEpsilon(4, 4));
224   CoCoA_ASSERT_ALWAYS( 1 == m1.myEpsilon(2, 4));
225   CoCoA_ASSERT_ALWAYS( 1 == m1.myEpsilon(0, 4));
226   CoCoA_ASSERT_ALWAYS( 1 == m1.myEpsilon(0, 0));
227 }
228 
test_myMaxTypeOne()229 void test_myMaxTypeOne()
230 {
231   ring QQ = RingQQ();
232   SparsePolyRing PolyRing = NewPolyRing(QQ, SymbolRange("x",0,4), StdDegLex);
233   const vector<RingElem> x = indets(PolyRing);
234   vector<RingElem>input;
235   RingElem LeftFactor(x[0]);
236   DynamicBitset wedge(5);
237   PPMonoidElem RightFactor(one(PPM(PolyRing)));
238   RingElem BasisElement(x[1] * x[2] * x[0]);
239   DynamicBitset ncrit(5);
240   std::vector<MorseElement::JBElem> TestBasis;
241   TestBasis.push_back(MorseElement::JBElem(BasisElement, ncrit, 1));
242   std::vector<MorseElement::JBElem>::iterator TBIter1(TestBasis.begin());
243   //first test
244   MorseElement m1(wedge, RightFactor, TestBasis.begin());
245   CoCoA_ASSERT_ALWAYS(-1 == m1.myMaxTypeOne());
246 
247   wedge.mySet(0, true);
248   wedge.mySet(1, true);
249   wedge.mySet(2, false);
250   wedge.mySet(3, false);
251   wedge.mySet(4, false);
252   m1.mySetWedgeProduct(wedge);
253   m1.mySetRightFactor(LPP(x[0] * x[1]));
254   ncrit.mySet(0, true);
255   ncrit.mySet(1, true);
256   ncrit.mySet(2, true);
257   ncrit.mySet(3, true);
258   ncrit.mySet(4, true);
259   TBIter1->multVars = ncrit;
260   CoCoA_ASSERT_ALWAYS(-1 == m1.myMaxTypeOne());
261 
262   wedge.mySet(1, false);
263   m1.mySetWedgeProduct(wedge);
264   CoCoA_ASSERT_ALWAYS(1 == m1.myMaxTypeOne());
265 
266   m1.mySetRightFactor(LPP(x[0] * x[1] * x[3]));
267   CoCoA_ASSERT_ALWAYS(3 == m1.myMaxTypeOne());
268 }
269 
270 
test_myMaxTypeTwo()271 void test_myMaxTypeTwo()
272 {
273   ring QQ = RingQQ();
274   SparsePolyRing PolyRing = NewPolyRing(QQ, SymbolRange("x",0,4), StdDegLex);
275   const vector<RingElem> x = indets(PolyRing);
276   RingElem LeftFactor(x[0]);
277   DynamicBitset wedge(5);
278   PPMonoidElem RightFactor(one(PPM(PolyRing)));
279   RingElem BasisElement(x[1] * x[2] * x[0]);
280   DynamicBitset ncrit(5);
281   std::vector<MorseElement::JBElem> TestBasis;
282   TestBasis.push_back(MorseElement::JBElem(BasisElement, ncrit, 1));
283   std::vector<MorseElement::JBElem>::iterator TBIter1(TestBasis.begin());
284 
285   //first test
286   MorseElement m1(wedge, RightFactor, TestBasis.begin());
287   CoCoA_ASSERT_ALWAYS(-1 == m1.myMaxTypeTwo());
288 
289   wedge.mySet(0, true);
290   wedge.mySet(1, true);
291   wedge.mySet(2, false);
292   wedge.mySet(3, false);
293   wedge.mySet(4, false);
294   m1.mySetWedgeProduct(wedge);
295   m1.mySetRightFactor(LPP(x[0] * x[1]));
296   ncrit.mySet(0, true);
297   ncrit.mySet(1, true);
298   ncrit.mySet(2, true);
299   ncrit.mySet(3, true);
300   ncrit.mySet(4, true);
301   TBIter1->multVars = ncrit;
302   CoCoA_ASSERT_ALWAYS(1 == m1.myMaxTypeTwo());
303 
304   wedge.mySet(1, false);
305   m1.mySetWedgeProduct(wedge);
306   CoCoA_ASSERT_ALWAYS(1 == m1.myMaxTypeTwo());
307 
308   m1.mySetRightFactor(LPP(x[0] * x[1] * x[3]));
309   CoCoA_ASSERT_ALWAYS(3 == m1.myMaxTypeTwo());
310 }
311 
312 
test_myComputeBasicMaps()313 void test_myComputeBasicMaps()
314 {
315   ring QQ = RingQQ();
316   SparsePolyRing PolyRing = NewPolyRing(QQ, SymbolRange("x",0,4), StdDegLex);
317   const vector<RingElem> x = indets(PolyRing);
318   vector<RingElem>input;
319   input.push_back(x[0]);
320   input.push_back(x[1]);
321   input.push_back(x[2]);
322   input.push_back(x[3]);
323   input.push_back(x[4]);
324   JBMill mill(JBMill::Builder().setInput(input));
325 
326   //if there is no wedge product there should not be a map
327   DynamicBitset wedge(5);
328   PPMonoidElem RightFactor(one(PPM(PolyRing)));
329   RingElem BasisElement(x[1] * x[2] * x[0]);
330   DynamicBitset ncrit(5);
331   StandardRepresentationContainer container(mill);
332   std::map<PPMonoidElem, std::vector<bool> > NonMultVars(mill.myNonMultVars());
333   std::vector<MorseElement::JBElem> TestBasis;
334   TestBasis.push_back(MorseElement::JBElem(BasisElement, ncrit, 1));
335   MorseElement m1(wedge, RightFactor, TestBasis.begin());
336   std::pair<vector<MorseElement::JBElem>::const_iterator, vector<MorseElement::JBElem>::const_iterator> pair(TestBasis.begin(), TestBasis.end());
337   CoCoA_ASSERT_ALWAYS(m1.myComputeBasicMaps(pair, container).size() == 0);
338 
339 
340   //maps of 0/\1 * (1) * (x4) with respect to pommaret basis (x0, x1, x2, x3, x4)
341   wedge.mySet(0, true);
342   wedge.mySet(1, true);
343 
344   TestBasis.clear();
345   TestBasis.push_back(MorseElement::JBElem(x[4], flip(VectorBoolToDynamicBitset(mill.myNonMultVarsOf(x[4]))), 1));
346   TestBasis.push_back(MorseElement::JBElem(x[3], flip(VectorBoolToDynamicBitset(mill.myNonMultVarsOf(x[3]))), 2));
347   TestBasis.push_back(MorseElement::JBElem(x[2], flip(VectorBoolToDynamicBitset(mill.myNonMultVarsOf(x[2]))), 3));
348   TestBasis.push_back(MorseElement::JBElem(x[1], flip(VectorBoolToDynamicBitset(mill.myNonMultVarsOf(x[1]))), 4));
349   TestBasis.push_back(MorseElement::JBElem(x[0], flip(VectorBoolToDynamicBitset(mill.myNonMultVarsOf(x[0]))), 5));
350   std::vector<MorseElement::JBElem>::iterator TBIter(TestBasis.begin());
351   MorseElement m2(wedge, RightFactor, TBIter);
352   pair.first = TestBasis.begin();
353   pair.second = TestBasis.end();
354   std::vector<std::pair<MorseElement, RingElem> > maps(m2.myComputeBasicMaps(pair, container));
355   CoCoA_ASSERT_ALWAYS(maps.size() == 3);
356 
357 
358   MorseElement MorseMap1 = maps[0].first;
359   RingElem map1 = maps[0].second;
360 
361   DynamicBitset ExpectedWedge1(5);
362   ExpectedWedge1.mySet(1, true);
363   DynamicBitset ExpectedNCrit1(5);
364   ExpectedNCrit1.mySet(4, true);
365 
366   CoCoA_ASSERT_ALWAYS(ExpectedWedge1 == MorseMap1.myGetWedgeProduct());
367   CoCoA_ASSERT_ALWAYS(RightFactor == MorseMap1.myGetRightFactor());
368   CoCoA_ASSERT_ALWAYS(x[4] == MorseMap1.myGetBasisElement());
369   CoCoA_ASSERT_ALWAYS(ExpectedNCrit1 == MorseMap1.myGetNCrit());
370   CoCoA_ASSERT_ALWAYS(map1 == x[0]);
371 
372 
373   // MorseElement MorseMap2 = maps[1].first;
374   // RingElem map2 = maps[1].second;
375 
376   // DynamicBitset ExpectedWedge2(ExpectedWedge1);
377   // DynamicBitset ExpectedNCrit2(5);
378   // ExpectedNCrit2 = flip(ExpectedNCrit2);
379 
380   // CoCoA_ASSERT_ALWAYS(ExpectedWedge2 == MorseMap2.myGetWedgeProduct());
381   // CoCoA_ASSERT_ALWAYS(LPP(x[4]) == MorseMap2.myGetRightFactor());
382   // CoCoA_ASSERT_ALWAYS(x[0] == MorseMap2.myGetBasisElement());
383   // CoCoA_ASSERT_ALWAYS(ExpectedNCrit2 == MorseMap2.myGetNCrit());
384   // CoCoA_ASSERT_ALWAYS(IsOne(map2 * (-1)));
385 
386 
387   MorseElement MorseMap3 = maps[1].first;
388   RingElem map3 = maps[1].second;
389 
390   DynamicBitset ExpectedWedge3(5);
391   ExpectedWedge3.mySet(0, true);
392   DynamicBitset ExpectedNCrit3(ExpectedNCrit1);
393 
394   CoCoA_ASSERT_ALWAYS(ExpectedWedge3 == MorseMap3.myGetWedgeProduct());
395   CoCoA_ASSERT_ALWAYS(RightFactor == MorseMap3.myGetRightFactor());
396   CoCoA_ASSERT_ALWAYS(x[4] == MorseMap3.myGetBasisElement());
397   CoCoA_ASSERT_ALWAYS(ExpectedNCrit3 == MorseMap3.myGetNCrit());
398   CoCoA_ASSERT_ALWAYS(map3 == -x[1]);
399 
400 
401   MorseElement MorseMap4 = maps[2].first;
402   RingElem map4 = maps[2].second;
403 
404   DynamicBitset ExpectedWedge4(ExpectedWedge3);
405   DynamicBitset ExpectedNCrit4(5);
406   ExpectedNCrit4 = flip(ExpectedNCrit4);
407   ExpectedNCrit4.mySet(0, false);
408 
409   CoCoA_ASSERT_ALWAYS(ExpectedWedge4 == MorseMap4.myGetWedgeProduct());
410   CoCoA_ASSERT_ALWAYS(LPP(x[4]) == MorseMap4.myGetRightFactor());
411   CoCoA_ASSERT_ALWAYS(x[1] == MorseMap4.myGetBasisElement());
412   CoCoA_ASSERT_ALWAYS(ExpectedNCrit4 == MorseMap4.myGetNCrit());
413   CoCoA_ASSERT_ALWAYS(IsOne(map4));
414 }
415 
test_StandardRepresentationContainer()416 void test_StandardRepresentationContainer()
417 {
418   ring QQ = RingQQ();
419   SparsePolyRing polyRing = NewPolyRing(QQ, SymbolRange("x",0,2));
420   vector<RingElem> x = indets(polyRing);
421   vector<RingElem> input;
422   input.push_back(power(x[0],2)+ 4*power(x[1],2) - 4);
423   input.push_back(- x[0]+2*power(x[1],2));
424   JBMill mill(JBMill::Builder().setInput(input));
425   StandardRepresentationContainer container(mill);
426 
427   RingElem t1 = x[0] * x[0] * x[0] + x[1] * x[0] + 10;
428   RingElem t2 = x[0] * x[0] * x[0] + x[2] * x[0] + 10;
429   RingElem t3 = x[0] * x[0] * x[0] + x[2] * x[2] + 10;
430 
431 
432   std::vector<RingElem> ResContainer(container.myComputeStandardRepresentation(t1));
433   std::vector<std::pair<RingElem, RingElem> > ResMill(mill.myStandardRepresentationWithoutRest(t1));
434   std::vector<std::pair<RingElem, RingElem> >::iterator i2(ResMill.begin());
435   for (std::vector<RingElem>::iterator i = ResContainer.begin(); i != ResContainer.end(); ++i)
436   {
437     CoCoA_ASSERT_ALWAYS((*i) == i2->second);
438     ++i2;
439   }
440   ResContainer = container.myComputeStandardRepresentation(t2);
441   ResMill = mill.myStandardRepresentationWithoutRest(t2);
442   i2 = ResMill.begin();
443   for (std::vector<RingElem>::iterator i = ResContainer.begin(); i != ResContainer.end(); ++i)
444   {
445     CoCoA_ASSERT_ALWAYS((*i) == i2->second);
446     ++i2;
447   }
448   ResContainer = container.myComputeStandardRepresentation(t3);
449   ResMill = mill.myStandardRepresentationWithoutRest(t3);
450   i2 = ResMill.begin();
451   for (std::vector<RingElem>::iterator i = ResContainer.begin(); i != ResContainer.end(); ++i)
452   {
453     CoCoA_ASSERT_ALWAYS((*i) == i2->second);
454     ++i2;
455   }
456 }
457 
program()458 void program()
459 {
460   GlobalManager CoCoAFoundations;
461   test_myDynamicBitsetToLong();
462   test_myVectorLongToDynamicBitset();
463   test_operators();
464   test_myEpsilon();
465   test_myMaxTypeOne();
466   test_myMaxTypeTwo();
467   test_myComputeBasicMaps();
468   test_StandardRepresentationContainer();
469 }
470 
471 
472 // Use main() to handle any uncaught exceptions and warn the user about them.
main()473 int main()
474 {
475   try
476   {
477     program();
478     return 0;
479   }
480   catch (const CoCoA::ErrorInfo& err)
481   {
482     cerr << "***ERROR***  UNCAUGHT CoCoA Error";
483     ANNOUNCE(cerr, err);
484   }
485   catch (const std::exception& exc)
486   {
487     cerr << "***ERROR***  UNCAUGHT std::exception: " << exc.what() << endl;
488   }
489   catch(...)
490   {
491     cerr << "***ERROR***  UNCAUGHT UNKNOWN EXCEPTION" << endl;
492   }
493 
494   BuildInfo::PrintAll(cerr);
495   return 1;
496 }
497