0029825: Foundation Classes, NCollection_Vec4 - workaround gcc optimizer issues with...
[occt.git] / src / QANCollection / QANCollection_Test.cxx
1 // Created on: 2004-03-05
2 // Created by: Mikhail KUZMITCHEV
3 // Copyright (c) 2004-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <QANCollection.hxx>
17 #include <QANCollection_Common.hxx>
18
19 #include <Draw.hxx>
20 #include <Draw_Interpretor.hxx>
21
22 #include <gp_Pnt.hxx>
23
24 #include <Precision.hxx>
25 #include <Standard_Overflow.hxx>
26
27 #include <NCollection_Vector.hxx>
28 #include <NCollection_IncAllocator.hxx>
29
30 #define ItemType gp_Pnt
31 #define Key1Type Standard_Real
32 #define Key2Type Standard_Integer
33
34 #include <NCollection_DefineArray1.hxx>
35 #include <NCollection_DefineHArray1.hxx>
36 ////////////////////////////////DEFINE_ARRAY1(QANCollection_Array1,QANCollection_BaseCol,ItemType)
37 ////////////////////////////////DEFINE_HARRAY1(QANCollection_HArray1,QANCollection_Array1)
38 DEFINE_ARRAY1(QANCollection_Array1Func,QANCollection_BaseColFunc,ItemType)
39 DEFINE_HARRAY1(QANCollection_HArray1Func,QANCollection_Array1Func)
40
41 #include <NCollection_DefineArray2.hxx>
42 #include <NCollection_DefineHArray2.hxx>
43 ////////////////////////////////DEFINE_ARRAY2(QANCollection_Array2,QANCollection_BaseCol,ItemType)
44 ////////////////////////////////DEFINE_HARRAY2(QANCollection_HArray2,QANCollection_Array2)
45 DEFINE_ARRAY2(QANCollection_Array2Func,QANCollection_BaseColFunc,ItemType)
46 DEFINE_HARRAY2(QANCollection_HArray2Func,QANCollection_Array2Func)
47
48 #include <NCollection_DefineMap.hxx>
49 #include <NCollection_DefineDataMap.hxx>
50 #include <NCollection_DefineDoubleMap.hxx>
51 #include <NCollection_DefineIndexedMap.hxx>
52 #include <NCollection_DefineIndexedDataMap.hxx>
53 ////////////////////////////////DEFINE_MAP(QANCollection_Map,QANCollection_Key1BaseCol,Key1Type)
54 ////////////////////////////////DEFINE_DATAMAP(QANCollection_DataMap,QANCollection_BaseCol,Key1Type,ItemType)
55 ////////////////////////////////DEFINE_DOUBLEMAP(QANCollection_DoubleMap,QANCollection_Key2BaseCol,Key1Type,Key2Type)
56 ////////////////////////////////DEFINE_INDEXEDMAP(QANCollection_IndexedMap,QANCollection_Key1BaseCol,Key1Type)
57 ////////////////////////////////DEFINE_INDEXEDDATAMAP(QANCollection_IDMap,QANCollection_BaseCol,Key1Type,ItemType)
58 DEFINE_MAP(QANCollection_MapFunc,QANCollection_Key1BaseColFunc,Key1Type)
59 DEFINE_DATAMAP(QANCollection_DataMapFunc,QANCollection_BaseColFunc,Key1Type,ItemType)
60 DEFINE_DOUBLEMAP(QANCollection_DoubleMapFunc,QANCollection_Key2BaseColFunc,Key1Type,Key2Type)
61 DEFINE_INDEXEDMAP(QANCollection_IndexedMapFunc,QANCollection_Key1BaseColFunc,Key1Type)
62 DEFINE_INDEXEDDATAMAP(QANCollection_IDMapFunc,QANCollection_BaseColFunc,Key1Type,ItemType)
63
64 #include <NCollection_DefineList.hxx>
65 ////////////////////////////////DEFINE_LIST(QANCollection_List,QANCollection_BaseCol,ItemType)
66 DEFINE_LIST(QANCollection_ListFunc,QANCollection_BaseColFunc,ItemType)
67
68 #include <NCollection_DefineSequence.hxx>
69 #include <NCollection_DefineHSequence.hxx>
70 ////////////////////////////////DEFINE_SEQUENCE(QANCollection_Sequence,QANCollection_BaseCol,ItemType)
71 ////////////////////////////////DEFINE_HSEQUENCE(QANCollection_HSequence,QANCollection_Sequence)
72 DEFINE_SEQUENCE(QANCollection_SequenceFunc,QANCollection_BaseColFunc,ItemType)
73 DEFINE_HSEQUENCE(QANCollection_HSequenceFunc,QANCollection_SequenceFunc)
74
75 // HashCode and IsEquel must be defined for key types of maps
76 Standard_Integer HashCode(const gp_Pnt thePnt, int theUpper)
77 {
78   return HashCode(thePnt.X(),theUpper);
79 }
80
81 Standard_Boolean IsEqual(const gp_Pnt& theP1, const gp_Pnt& theP2)
82 {
83   return theP1.IsEqual(theP2,gp::Resolution());
84 }
85
86 ////////////////////////////////void printCollection (QANCollection_Key1BaseCol& aColl, 
87 template <class Coll>
88 void printCollection (Coll& aColl, const char * str)
89 {
90   printf ("%s:\n",str);
91   Standard_Integer iSize = aColl.Size();
92   ////////////////////////////////QANCollection_Key1BaseCol::Iterator& anIter = aColl.CreateIterator();
93   typename Coll::Iterator anIter (aColl);
94   if (!anIter.More())
95   {
96     if (iSize==0)
97       printf ("   <Empty collection>\n");
98     else
99       printf ("Error   : empty collection has size==%d",iSize);
100   }
101   else
102   {
103     printf ("   Size==%d\n",iSize);
104     for (; anIter.More(); anIter.Next())
105       PrintItem(anIter.Value());
106   }
107 }
108
109 ////////////////////////////////void AssignCollection (QANCollection_BaseCol& aCollSrc,
110 ////////////////////////////////                       QANCollection_BaseCol& aCollDst)
111 template <class Coll>
112 void AssignCollection (Coll& aCollSrc, Coll& aCollDst)
113 {
114   printCollection (aCollSrc,"Source collection");
115   aCollDst.Assign(aCollSrc);
116   printCollection (aCollDst,"Target collection");
117 }
118
119 // ===================== Test methods of Array1 type ==========================
120 ////////////////////////////////void TestArray1  (QANCollection_Array1&     theA1)
121 static void TestArray1  (QANCollection_Array1Func&     theA1)
122 {
123   // Bounds
124   Standard_Integer iLow=theA1.Lower();
125   Standard_Integer iUpp=theA1.Upper();
126   Standard_Integer i;
127
128   printf ("Info: testing Array1(%d,%d), %s\n",
129           iLow, iUpp, (theA1.IsDeletable()?"deletable":"frozen"));
130   // C-array constructor, Length, Init
131   ItemType anItem;
132   Random(anItem);
133   theA1.Init (anItem);
134   ItemType * rBlock = new ItemType[theA1.Length()];
135   ////////////////////////////////QANCollection_Array1 aCArr(*rBlock, iLow-100, iUpp-100);
136   QANCollection_Array1Func aCArr(*rBlock, iLow-100, iUpp-100);
137   printf ("      created the same sized preallocated array (%d,%d), %s\n",
138         aCArr.Lower(),aCArr.Upper(),(aCArr.IsDeletable()?"deletable":"frozen"));
139   // *Value, operator()
140   for (i=iLow+1; i<iUpp; i++)
141   {
142     Random (aCArr.ChangeValue (i-101));
143     aCArr.SetValue (i-100, ItemType(aCArr.Value(i-101)));
144     aCArr(i-99) = aCArr(i-100) = aCArr(i-101);
145   }
146   // Handle, copy constructor (including operator=)
147   ////////////////////////////////Handle(QANCollection_HArray1) aHa = new QANCollection_HArray1(aCArr);
148   Handle(QANCollection_HArray1Func) aHa = new QANCollection_HArray1Func(aCArr);
149   // Assign
150   AssignCollection (aHa->ChangeArray1(), theA1);
151 }
152
153 // ===================== Test methods of Array2 type ==========================
154 ////////////////////////////////void TestArray2  (QANCollection_Array2&     theA2)
155 static void TestArray2  (QANCollection_Array2Func&     theA2)
156 {
157   // Bounds
158   Standard_Integer iLR=theA2.LowerRow(), iLC=theA2.LowerCol();
159   Standard_Integer iUR=theA2.UpperRow(), iUC=theA2.UpperCol();
160   Standard_Integer i,j;
161
162   printf ("Info: testing Array2 (%d,%d)(%d,%d), %s\n",
163           iLR, iUR, iLC, iUC, (theA2.IsDeletable()?"deletable":"frozen"));
164   // C-array constructor, Length, Init, RowLength, ColLength
165   ItemType anItem;
166   Random(anItem);
167   theA2.Init (anItem);
168   ItemType * rBlock = new ItemType[theA2.Length()];
169   ////////////////////////////////QANCollection_Array2 aCArr(*rBlock, iLR-100, iUR-100, iLC, iUC);
170   QANCollection_Array2Func aCArr(*rBlock, iLR-100, iUR-100, iLC, iUC);
171   printf ("      created the same sized preallocated array (%d*%d), %s\n",
172           aCArr.RowLength(), aCArr.ColLength(),
173           (aCArr.IsDeletable()?"deletable":"frozen"));
174   // *Value, operator()
175   for (i=iLR+1; i<iUR; i++)
176   {
177     for (j=iLC; j<=iUC; j++)
178     {
179       Random (aCArr.ChangeValue (i-101, j));
180       aCArr.SetValue (i-100, j, 
181                       ItemType(aCArr.Value(i-101,j)));
182       aCArr(i-99,j) = aCArr(i-100,j) = aCArr(i-101,j);
183     }
184   }
185   // Handle, copy constructor (including operator=)
186   ////////////////////////////////Handle(QANCollection_HArray2) aHa = new QANCollection_HArray2(aCArr);
187   Handle(QANCollection_HArray2Func) aHa = new QANCollection_HArray2Func(aCArr);
188   // Assign
189   AssignCollection (aHa->ChangeArray2(), theA2);
190 }
191
192 // ===================== Test methods of List type ==========================
193 ////////////////////////////////void TestList (QANCollection_List&     theL)
194 static void TestList (QANCollection_ListFunc&     theL)
195 {
196   // Extent
197   Standard_Integer iExt=theL.Extent();
198   Standard_Integer i;
199
200   printf ("Info: testing List(%d)\n", iExt);
201   // Append(2), Prepend(2), InsertBefore(2), InsertAfter(2), 
202   // Remove, RemoveFirst, First, Last
203   ItemType anItem;
204   ////////////////////////////////QANCollection_List aL, aL1;
205   QANCollection_ListFunc aL, aL1;
206   for (i=0; i<4; i++)
207   {
208     Random (anItem);
209     aL.Append (anItem); // #1
210     aL.Append (aL1);    // #2
211     Random (anItem);
212     aL1.Prepend (anItem); // #3
213     aL1.Prepend (aL);     // #4
214     ////////////////////////////////QANCollection_List::Iterator anI(theL);
215     QANCollection_ListFunc::Iterator anI(theL);
216     if (anI.More())
217     {
218       Random (anItem);
219       theL.InsertBefore (anItem, anI); // #5
220       theL.InsertBefore (aL1, anI);    // #6
221       Random (anItem);
222       theL.InsertAfter (anItem, anI); // #7
223       theL.InsertAfter (aL, anI);     // #8
224       theL.Remove (anI);  // #9
225       if (theL.Extent() > 0)
226         theL.RemoveFirst(); // #10
227     }
228     else
229     {
230       theL.Prepend (anItem);
231       PrintItem(theL.First());
232       PrintItem(theL.Last());
233     }
234   }
235   // Copy constructor + operator=
236   ////////////////////////////////aL = QANCollection_List(theL);
237   aL = QANCollection_ListFunc(theL);
238
239   // Assign
240   AssignCollection (theL, aL);
241
242   // Different allocators
243   {
244     // The joining of list having different allocator can cause memory error
245     // if the fact of different allocator is not taken into account.
246     Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator;
247     QANCollection_ListFunc aS2(anAlloc);
248     aS2.Append(anItem);
249     theL.Prepend(aS2);
250     aS2.Append(anItem);
251     theL.Append(aS2);
252     aS2.Append(anItem);
253     QANCollection_ListFunc::Iterator anIter(theL);
254     theL.InsertBefore(aS2, anIter);
255     aS2.Append(anItem);
256     theL.InsertAfter(aS2, anIter);
257   }
258
259   // Clear
260   aL.Clear();
261 }
262
263 // ===================== Test methods of Sequence type ========================
264 ////////////////////////////////void TestSequence (QANCollection_Sequence& theS)
265 static void TestSequence (QANCollection_SequenceFunc& theS)
266 {
267   Standard_Integer i;
268
269   printf ("Info: testing Sequence\n");
270   // Append(2)
271   ItemType anItem;
272   ////////////////////////////////QANCollection_Sequence aS, aS1;
273   QANCollection_SequenceFunc aS, aS1;
274   // Append(2), Prepend(2), InsertBefore(2), InsertAfter(2), 
275   // Remove, RemoveFirst, First, Last
276   for (i=0; i<4; i++)
277   {
278     Random (anItem);
279     aS.Append (anItem); // #1
280     aS.Append (aS1);    // #2
281     Random (anItem);
282     aS1.Prepend (anItem); // #3
283     aS1.Prepend (aS);     // #4
284     if (theS.Length() > 0)
285     {
286       Random (anItem);
287       theS.InsertBefore (1, anItem); // #5
288       theS.InsertBefore (2, aS1);    // #6
289       Random (anItem);
290       theS.InsertAfter (1, anItem); // #7
291       theS.InsertAfter (2, aS);     // #8
292       theS.Remove (1);  // #9
293       if (theS.Length() > 0)
294         theS.Remove(1); // #10
295     }
296     else
297     {
298       theS.Prepend (anItem);
299       PrintItem(theS.First());
300       PrintItem(theS.Last());
301     }
302   }
303
304   // ()
305   PrintItem(theS(1));
306
307   // Handle, Split
308   ////////////////////////////////Handle(QANCollection_HSequence) aHS = new QANCollection_HSequence(aS1);
309   Handle(QANCollection_HSequenceFunc) aHS = new QANCollection_HSequenceFunc(aS1);
310   theS.Split (3, aHS->ChangeSequence());
311
312   // Assign
313   AssignCollection (theS, aS);
314
315   // Different allocators
316   {
317     // The joining of sequence having different allocator can cause memory error
318     // if the fact of different allocator is not taken into account.
319     Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator;
320     QANCollection_SequenceFunc aS2(anAlloc);
321     aS2.Append(anItem);
322     theS.Prepend(aS2);
323     aS2.Append(anItem);
324     theS.Append(aS2);
325     aS2.Append(anItem);
326     theS.InsertBefore(1, aS2);
327     aS2.Append(anItem);
328     theS.InsertAfter(1, aS2);
329   }
330
331   // Clear
332   aS.Clear();
333 }
334
335 // ===================== Test methods of Map type =============================
336 ////////////////////////////////void TestMap  (QANCollection_Map& theM)
337 static void TestMap(QANCollection_MapFunc& theM, Draw_Interpretor& theDI)
338 {
339   {
340     // Extent
341     Standard_Integer iExt=theM.Extent();
342     Standard_Integer i;
343
344     printf ("Info: testing Map(l=%d)\n", iExt);
345     theM.Statistics(cout);
346     // Resize
347     theM.ReSize(8);
348     theM.Statistics(cout);
349     cout.flush();
350     // Constructor
351     ////////////////////////////////QANCollection_Map aM;
352     QANCollection_MapFunc aM;
353     // Add
354     Key1Type aKey;
355     for (i=0; i<8; i++)
356     {
357       Random (aKey);
358       aM.Add (aKey);
359     }
360     // Contains, Remove
361     if (!aM.Contains(aKey))
362     {
363       theDI << "Error: map says that it does not contain its key " << aKey;
364     }
365     else
366     {
367       aM.Remove(aKey);
368       cout << "      successfully removed item, l=%d\n" << aM.Size() << "\n";
369     }
370     // Copy constructor (including operator=)
371     ////////////////////////////////QANCollection_Map aM2 = QANCollection_Map(aM);
372     QANCollection_MapFunc aM2 = QANCollection_MapFunc(aM);
373     // Assign
374     AssignCollection (aM2,theM);
375
376     // Clear
377     aM.Clear();
378   }
379
380   // Check method 'HasIntersection'.
381   {
382     QANCollection_MapFunc aM1, aM2, aM3;
383
384     aM1.Add(6);
385     aM1.Add(8);
386     aM1.Add(10);
387
388     aM2.Add(4);
389     aM2.Add(8);
390     aM2.Add(16);
391
392     aM3.Add(1);
393     aM3.Add(2);
394     aM3.Add(3);
395
396     if (!aM1.HasIntersection(aM2) || !aM2.HasIntersection(aM1) ||
397          aM1.HasIntersection(aM3) ||  aM3.HasIntersection(aM1))
398     {
399       theDI << "Error: method 'HasIntersection' failed.";
400     }
401   }
402 }
403
404 // ===================== Test methods of DataMap type =========================
405 ////////////////////////////////void TestDataMap  (QANCollection_DataMap& theM)
406 static void TestDataMap  (QANCollection_DataMapFunc& theM)
407 {
408   // Extent
409   Standard_Integer iExt=theM.Extent();
410   Standard_Integer i;
411
412   printf ("Info: testing DataMap(l=%d)\n", iExt);
413   theM.Statistics(cout);
414   // Resize
415   theM.ReSize(8);
416   theM.Statistics(cout);
417   cout.flush();
418   // Constructor
419   ////////////////////////////////QANCollection_DataMap aM;
420   QANCollection_DataMapFunc aM;
421   // Bind, Find, ChangeFind, ()
422   Key1Type aKey;
423   ItemType anItem;
424   for (i=0; i<8; i++)
425   {
426     Random (aKey);
427     Random (anItem);
428     aM.Bind (aKey, anItem);
429     PrintItem(aM.Find(aKey));
430     Random(aM(aKey));
431   }
432   // IsBound, UnBind
433   if (!aM.IsBound(aKey))
434   {
435     printf("Error   : map says that it does not contain its key ");
436     PrintItem(aKey);
437   }
438   else
439   {
440     aM.UnBind(aKey);
441     printf("      successfully unbound the key, l=%d\n", aM.Size());
442   }
443   // Copy constructor (including operator=)
444   ////////////////////////////////theM = QANCollection_DataMap(aM);
445   theM = QANCollection_DataMapFunc(aM);
446   // Assign - prohibited
447   // AssignCollection (aM2,theM);
448   printCollection (theM, "DataMap:");
449
450   // Clear
451   aM.Clear();
452 }
453
454
455 // ===================== Test methods of DoubleMap type =======================
456 ////////////////////////////////void TestDoubleMap  (QANCollection_DoubleMap& theM)
457 static void TestDoubleMap  (QANCollection_DoubleMapFunc& theM)
458 {
459   // Extent
460   Standard_Integer iExt=theM.Extent();
461   Standard_Integer i;
462
463   printf ("Info: testing DoubleMap(l=%d)\n", iExt);
464   theM.Statistics(cout);
465   // Resize
466   theM.ReSize(8);
467   theM.Statistics(cout);
468   cout.flush();
469   // Constructor
470   ////////////////////////////////QANCollection_DoubleMap aM;
471   QANCollection_DoubleMapFunc aM;
472   // Bind, Find?, 
473   Key1Type aKey1;
474   Key2Type aKey2;
475   for (i=0; i<8; i++)
476   {
477     Random (aKey1);
478     Random (aKey2);
479     aM.Bind (aKey1, aKey2);
480     PrintItem(aM.Find1(aKey1));
481     if (!aM.IsBound1(aKey1))
482     {
483       printf("Error   : map says that it does not contain its key ");
484       PrintItem(aKey1);
485     }
486     PrintItem(aM.Find2(aKey2));
487     if (!aM.IsBound2(aKey2))
488     {
489       printf("Error   : map says that it does not contain its key ");
490       PrintItem(aKey2);
491     }
492   }
493   // AreBound, UnBind
494   if (!aM.AreBound(aKey1,aKey2))
495   {
496     printf("Error   : map says that it does not contain its keys ");
497     PrintItem(aKey1);
498     PrintItem(aKey2);
499   }
500   else
501   {
502     if (aM.UnBind2(aKey2))
503       printf("      successfully unbound the key, l=%d\n", aM.Size());
504     if (aM.UnBind1(aKey1))
505       printf("Error   : unbound both keys?!\n");
506   }
507   // Copy constructor (including operator=)
508   ////////////////////////////////theM = QANCollection_DoubleMap(aM);
509   theM = QANCollection_DoubleMapFunc(aM);
510   // Assign - prohibited
511   // AssignCollection (aM2,theM);
512   printCollection (theM, "DoubleMap:");
513
514   // Clear
515   aM.Clear();
516 }
517
518 // ===================== Test methods of IndexedMap type ======================
519 ////////////////////////////////void TestIndexedMap  (QANCollection_IndexedMap& theM)
520 static void TestIndexedMap  (QANCollection_IndexedMapFunc& theM)
521 {
522   // Extent
523   Standard_Integer iExt=theM.Extent();
524   Standard_Integer i;
525
526   printf ("Info: testing IndexedMap(l=%d)\n", iExt);
527   theM.Statistics(cout);
528   // Resize
529   theM.ReSize(8);
530   theM.Statistics(cout);
531   cout.flush();
532   // Constructor
533   ////////////////////////////////QANCollection_IndexedMap aM;
534   QANCollection_IndexedMapFunc aM;
535   // Add, FindKey, FindIndex
536   Key1Type aKey;
537   for (i=0; i<8; i++)
538   {
539     Random (aKey);
540     aM.Add (aKey);
541     Standard_Integer iIndex=aM.FindIndex(aKey);
542     printf ("     added a key, i=%d, k=",iIndex);
543     PrintItem(aM(iIndex));
544   }
545   // Contains, Remove
546   if (!aM.Contains(aM.FindKey(aM.FindIndex(aKey))))
547   {
548     printf("Error   : map says that it does not contain its key ");
549     PrintItem(aKey);
550   }
551   else
552   {
553     aM.RemoveLast();
554     printf("      successfully removed item, l=%d\n", aM.Size());
555   }
556   // Substitute
557   Random(aKey);
558   aM.Substitute(1,aKey);
559   if (!aM.Contains (aKey) || aM.FindIndex (aKey) != 1)
560   {
561     printf("Error   : map does not contain valid key after substitute"); 
562   }
563   // Invoke substitute with the same key
564   aM.Substitute(1,aKey);
565   if (!aM.Contains (aKey) || aM.FindIndex (aKey) != 1)
566   {
567     printf("Error   : map does not contain valid key after substitute"); 
568   }
569   // Copy constructor (including operator=)
570   ////////////////////////////////QANCollection_IndexedMap aM2 = QANCollection_IndexedMap(aM);
571   QANCollection_IndexedMapFunc aM2 = QANCollection_IndexedMapFunc(aM);
572   // Assign
573   AssignCollection (aM2,theM);
574
575   // Clear
576   aM.Clear();
577 }
578
579 // ===================== Test methods of IndexedDataMap type ==================
580 ////////////////////////////////void TestIndexedDataMap  (QANCollection_IDMap& theM)
581 static void TestIndexedDataMap  (QANCollection_IDMapFunc& theM)
582 {
583   // Extent
584   Standard_Integer iExt=theM.Extent();
585   Standard_Integer i;
586
587   printf ("Info: testing IndexedDataMap(l=%d)\n", iExt);
588   theM.Statistics(cout);
589   // Resize
590   theM.ReSize(8);
591   theM.Statistics(cout);
592   cout.flush();
593   // Constructor
594   ////////////////////////////////QANCollection_IDMap aM;
595   QANCollection_IDMapFunc aM;
596   // Add, FindKey, FindIndex, FindFromIndex, Change..., ()
597   Key1Type aKey;
598   ItemType anItem;
599   for (i=0; i<8; i++)
600   {
601     Random (aKey);
602     Random (anItem);
603     aM.Add (aKey, anItem);
604     Standard_Integer iIndex=aM.FindIndex(aKey);
605     printf ("     added a key, i=%d, k=",iIndex);
606     PrintItem(aM.FindKey(iIndex));
607     PrintItem(aM(iIndex));
608     Random(aM.ChangeFromIndex(iIndex));
609   }
610   // Contains, Remove, FindFromKey
611   if (!aM.Contains(aM.FindKey(aM.FindIndex(aKey))))
612   {
613     printf("Error   : map says that it does not contain its key ");
614     PrintItem(aKey);
615   }
616   else
617   {
618     anItem = aM.FindFromKey(aKey);
619     aM.RemoveLast();
620     printf("      successfully removed item, l=%d\n", aM.Size());
621   }
622   // Substitute with different keys
623   Random(aKey);
624   aM.Substitute (1, aKey, anItem);
625   if (!aM.Contains (aKey) || aM.FindIndex (aKey) != 1 || !aM.FindFromKey (aKey).IsEqual (anItem, Precision::Confusion()))
626   {
627     printf("Error   : map does not contain valid key and item after substitute"); 
628   }
629   // Substitute with equal keys
630   Random(anItem);
631   aM.Substitute (1, aKey, anItem);
632   if (!aM.Contains (aKey) || aM.FindIndex (aKey) != 1 || !aM.FindFromKey (aKey).IsEqual (anItem, Precision::Confusion()))
633   {
634     printf("Error   : map does not contain valid key and item after substitute"); 
635   }
636   // Copy constructor (including operator=)
637   ////////////////////////////////theM = QANCollection_IDMap(aM);
638   theM = QANCollection_IDMapFunc(aM);
639   // Assign - prohibited
640   // AssignCollection (aM2,theM);
641   printCollection (theM, "DoubleMap:");
642
643   // Clear
644   aM.Clear();
645 }
646
647 //=======================================================================
648 //function : CheckArguments1
649 //purpose  : 
650 //=======================================================================
651 Standard_Integer CheckArguments1(Draw_Interpretor& di, Standard_Integer argc, const char ** argv, Standard_Integer& Lower, Standard_Integer& Upper)
652 {
653   if ( argc != 3) {
654     di << "Usage : " << argv[0] << " Lower Upper\n";
655     return 1;
656   }
657   Lower = Draw::Atoi(argv[1]);
658   Upper = Draw::Atoi(argv[2]);
659   if ( Lower > Upper ) {
660     di << "Lower > Upper\n";
661     return 1;
662   }
663   return 0;
664 }
665
666 //=======================================================================
667 //function : CheckArguments2
668 //purpose  : 
669 //=======================================================================
670 Standard_Integer CheckArguments2(Draw_Interpretor& di, Standard_Integer argc, const char ** argv, Standard_Integer& LowerRow, Standard_Integer& UpperRow, Standard_Integer& LowerCol, Standard_Integer& UpperCol)
671 {
672   if ( argc != 5) {
673     di << "Usage : " << argv[0] << " LowerRow UpperRow LowerCol UpperCol\n";
674     return 1;
675   }
676   LowerRow = Draw::Atoi(argv[1]);
677   UpperRow = Draw::Atoi(argv[2]);
678   LowerCol = Draw::Atoi(argv[3]);
679   UpperCol = Draw::Atoi(argv[4]);
680   if ( LowerRow > UpperRow ) {
681     di << "LowerRow > UpperRow\n";
682     return 1;
683   }
684   if ( LowerCol > UpperCol ) {
685     di << "LowerCol UpperCol> \n";
686     return 1;
687   }
688   return 0;
689 }
690
691
692 //=======================================================================
693 //function : QANColTestArray1
694 //purpose  : 
695 //=======================================================================
696 static Standard_Integer QANColTestArray1(Draw_Interpretor& di, Standard_Integer argc, const char ** argv)
697 {
698   Standard_Integer Lower, Upper;
699   if ( CheckArguments1(di, argc, argv, Lower, Upper) ) {
700     return 1;
701   }
702   QANCollection_Array1Func anArr1(Lower, Upper);
703   TestArray1(anArr1);
704   return 0;
705 }
706
707 //=======================================================================
708 //function : QANColTestArray2
709 //purpose  : 
710 //=======================================================================
711 static Standard_Integer QANColTestArray2(Draw_Interpretor& di, Standard_Integer argc, const char ** argv)
712 {
713   Standard_Integer LowerRow, UpperRow, LowerCol, UpperCol;
714   if ( CheckArguments2(di, argc, argv, LowerRow, UpperRow, LowerCol, UpperCol) ) {
715     return 1;
716   }
717   QANCollection_Array2Func anArr2(LowerRow, UpperRow, LowerCol, UpperCol);
718   TestArray2(anArr2);
719   return 0;
720 }
721
722 //=======================================================================
723 //function : QANColTestMap
724 //purpose  : 
725 //=======================================================================
726 static Standard_Integer QANColTestMap(Draw_Interpretor& di, Standard_Integer argc, const char ** argv)
727 {
728   if ( argc != 1) {
729     di << "Usage : " << argv[0] << "\n";
730     return 1;
731   }
732   QANCollection_MapFunc aMap;
733   TestMap(aMap, di);
734   return 0;
735 }
736
737 //=======================================================================
738 //function : QANColTestDataMap
739 //purpose  : 
740 //=======================================================================
741 static Standard_Integer QANColTestDataMap(Draw_Interpretor& di, Standard_Integer argc, const char ** argv)
742 {
743   if ( argc != 1) {
744     di << "Usage : " << argv[0] << "\n";
745     return 1;
746   }
747   QANCollection_DataMapFunc aDataMap;
748   TestDataMap(aDataMap);
749   return 0;
750 }
751
752 //=======================================================================
753 //function : QANColTestDoubleMap
754 //purpose  : 
755 //=======================================================================
756 static Standard_Integer QANColTestDoubleMap(Draw_Interpretor& di, Standard_Integer argc, const char ** argv)
757 {
758   if ( argc != 1) {
759     di << "Usage : " << argv[0] << "\n";
760     return 1;
761   }
762   QANCollection_DoubleMapFunc aDoubleMap;
763   TestDoubleMap(aDoubleMap);
764   return 0;
765 }
766
767 //=======================================================================
768 //function : QANColTestIndexedMap
769 //purpose  : 
770 //=======================================================================
771 static Standard_Integer QANColTestIndexedMap(Draw_Interpretor& di, Standard_Integer argc, const char ** argv)
772 {
773   if ( argc != 1) {
774     di << "Usage : " << argv[0] << "\n";
775     return 1;
776   }
777   QANCollection_IndexedMapFunc aIndexedMap;
778   TestIndexedMap(aIndexedMap);
779   return 0;
780 }
781
782 //=======================================================================
783 //function : QANColTestIndexedDataMap
784 //purpose  : 
785 //=======================================================================
786 static Standard_Integer QANColTestIndexedDataMap(Draw_Interpretor& di, Standard_Integer argc, const char ** argv)
787 {
788   if ( argc != 1) {
789     di << "Usage : " << argv[0] << "\n";
790     return 1;
791   }
792   QANCollection_IDMapFunc aIDMap;
793   TestIndexedDataMap(aIDMap);
794   return 0;
795 }
796
797 //=======================================================================
798 //function : QANColTestList
799 //purpose  : 
800 //=======================================================================
801 static Standard_Integer QANColTestList(Draw_Interpretor& di, Standard_Integer argc, const char ** argv)
802 {
803   if ( argc != 1) {
804     di << "Usage : " << argv[0] << "\n";
805     return 1;
806   }
807   QANCollection_ListFunc aList;
808   TestList(aList);
809   return 0;
810 }
811
812 //=======================================================================
813 //function : QANColTestVector
814 //purpose  : 
815 //=======================================================================
816 static Standard_Integer QANColTestVector (Draw_Interpretor&, Standard_Integer, const char**)
817 {
818   // test method Append and copying of empty vector
819   NCollection_Vector<int> aVec;
820   NCollection_Vector<int> aVec2 (aVec);
821   NCollection_Vector<int> aVec3;
822   aVec3 = aVec;
823
824   aVec.Append(5);
825   if (aVec(0) != 5)
826     std::cout << "Error: wrong value in original vector!" << endl;
827   aVec2.Append(5);
828   if (aVec2(0) != 5)
829     std::cout << "Error: wrong value in copy-constructed vector!" << endl;
830   aVec3.Append(5);
831   if (aVec3(0) != 5)
832     std::cout << "Error: wrong value in copied vector!" << endl;
833   std::cout << "Test OK" << endl;
834
835   return 0;
836 }
837
838 //=======================================================================
839 //function : QANColTestSequence
840 //purpose  : 
841 //=======================================================================
842 static Standard_Integer QANColTestSequence(Draw_Interpretor& di, Standard_Integer argc, const char ** argv)
843 {
844   if ( argc != 1) {
845     di << "Usage : " << argv[0] << "\n";
846     return 1;
847   }
848   QANCollection_SequenceFunc aSeq;
849   TestSequence(aSeq);
850   return 0;
851 }
852
853 //=======================================================================
854 //function : QANColTestMove
855 //purpose  : 
856 //=======================================================================
857
858 // Return array based on local C array buffer by value.
859 // Note that this is expected to cause errors due
860 // to the fact that returned copy will keep reference to the
861 // buffer allocated in the stack of this function.
862 // Unfortunately, this cannot be prevented due to the fact that
863 // modern compilers use return value optimization in release mode
864 // (object that is returned is constructed once at its target 
865 // place and never copied).
866 static NCollection_Array1<double> GetArrayByValue()
867 {
868   const int aLen = 1024;
869   double aCArray[aLen];
870   NCollection_Array1<double> anArray (aCArray[0], 1, aLen);
871   for (int i = 1; i <= aLen; i++)
872     anArray.SetValue(i, i + 113.);
873   return anArray;
874 }
875
876 // check array for possible corruption
877 static bool CheckArrayByValue(NCollection_Array1<double> theArray)
878 {
879   for (int i = 1; i <= theArray.Length(); i++)
880   {
881     if (theArray.Value(i) != i + 113.)
882     {
883       std::cout << "Error at item " << i << ": value = " << theArray.Value(i) << ", expected " << i + 113. << std::endl;
884       return false;
885     }
886   }
887   return true;
888 }
889
890 static Standard_Integer QANColTestArrayMove (Draw_Interpretor& di, Standard_Integer argc, const char ** argv)
891 {
892   if ( argc != 1) {
893     di << "Usage : " << argv[0] << "\n";
894     return 1;
895   }
896   NCollection_Array1<double> anArray = GetArrayByValue();
897   di << (CheckArrayByValue(anArray) ? "Error: memory corruption is not detected" : "Expected behavior: memory is corrupted");
898   return 0;
899 }
900
901 #include <math_BullardGenerator.hxx>
902 #include <OSD_Timer.hxx>
903
904 static inline double test_atof (const char* theStr) 
905
906   return atof (theStr);
907 }
908
909 static inline double test_Atof (const char* theStr) 
910
911   return Atof (theStr);
912 }
913
914 static inline double test_strtod (const char* theStr) 
915
916   char *end;
917   return strtod (theStr, &end);
918 }
919
920 static inline double test_Strtod (const char* theStr) 
921
922   char *end;
923   return Strtod (theStr, &end);
924 }
925
926 static inline double test_sscanf (const char* theStr) 
927
928   double val = 0.;
929   sscanf (theStr, "%lf", &val);
930   return val; 
931 }
932
933 static int check_atof (const NCollection_Array2<char>& theStrings, const char* theFormat,
934                        double (*test_func)(const char*), Draw_Interpretor& di)
935 {
936   int aNbErr = 0;
937   for (int i = 0; i < theStrings.UpperRow(); i++) 
938   {
939     const char *aStr= &theStrings(i,0);
940     char buff[256];
941     double aVal = test_func (aStr);
942     Sprintf (buff, theFormat, aVal);
943     if (strcasecmp (buff, &theStrings(i,0)))
944     {
945 #if defined(_MSC_VER) && _MSC_VER < 1900
946       // MSVC < 2015 prints nan and inf as 1.#NAN or 1.INF, and noes not recognize nan or inf on read
947       if (strstr (aStr, "1.#") || strstr (aStr, "nan") || strstr (aStr, "inf") || 
948           strstr (aStr, "NAN") || strstr (aStr, "INF"))
949         continue;
950 #endif
951       if (aNbErr < 5)
952       {
953         di << "Deviation parsing " << aStr << " and print back: " << buff << "\n";
954       }
955       aNbErr++;
956     }
957   }
958   return aNbErr;
959 }
960
961 // Test speed of standard and OCCT-specific (accelerated) functions to parse string to double
962 static Standard_Integer QATestAtof (Draw_Interpretor& di, Standard_Integer argc, const char ** argv)
963 {
964   int aNbToTest = Max (100, (argc > 1 ? Draw::Atoi(argv[1]) : 1000000));
965   int aNbDigits = (argc > 2 ? Draw::Atoi(argv[2]) : 10);
966   double aRangeMin = (argc > 3 ? Draw::Atof(argv[3]) : -1e9);
967   double aRangeMax = (argc > 4 ? Draw::Atof(argv[4]) : 1e9);
968
969   char aFormat[256];
970   Sprintf (aFormat, "%%.%dlg", Max (2, Min (20, aNbDigits)));
971
972   // prepare data
973   const int MAXLEN = 256;
974   NCollection_Array2<char> aValuesStr (0, aNbToTest - 1, 0, MAXLEN);
975   math_BullardGenerator aRandom;
976
977   if (aRangeMin < aRangeMax)
978   {
979     // random values within specified range
980 //    std::default_random_engine aRandomEngine;
981 //    std::uniform_real_distribution<double> aRandomDistr (aRangeMin, aRangeMax);
982     const uint64_t aMaxUInt64 = ~(uint64_t)0; // could be (not supported by old GCC): std::numeric_limits<uint64_t>::max()
983     for (int i = 0; i < aNbToTest; i++)
984     {
985 //      double aVal = aRandomDistr (aRandomEngine);
986       uint64_t aIVal = ((uint64_t)aRandom.NextInt() << 32) + aRandom.NextInt();
987       double aVal = aRangeMin + (aIVal / (double)aMaxUInt64) * (aRangeMax - aRangeMin);
988       Sprintf(&aValuesStr(i,0), aFormat, aVal);
989     }
990   }
991   else
992   {
993     // special values
994     int i = 0;
995
996     strcpy (&aValuesStr(i++,0), "nan");
997     strcpy (&aValuesStr(i++,0), "nan(qnan)");
998     strcpy (&aValuesStr(i++,0), "NAN");
999     strcpy (&aValuesStr(i++,0), "-nan");
1000     strcpy (&aValuesStr(i++,0), "-NAN");
1001     strcpy (&aValuesStr(i++,0), "inf");
1002     strcpy (&aValuesStr(i++,0), "INF");
1003     strcpy (&aValuesStr(i++,0), "-inf");
1004     strcpy (&aValuesStr(i++,0), "-INF");
1005
1006     strcpy (&aValuesStr(i++,0), "  ."); // standalone period should not be considered as a  number
1007     strcpy (&aValuesStr(i++,0), "nanabcdef_128  xx"); // extra non-parenthised sequence after "nan"
1008
1009     strcpy (&aValuesStr(i++,0), "905791934.11394954"); // value that gets rounded in a wrong way by fast Strtod()
1010     strcpy (&aValuesStr(i++,0), "9.343962790444495e+148"); // value where strtod() and Strtod() differ by 2 Epsilon
1011
1012     strcpy (&aValuesStr(i++,0), "     12345.67text"); // test for leading whitespaces and trailing text
1013     strcpy (&aValuesStr(i++,0), "000.000"); // test for zero
1014     strcpy (&aValuesStr(i++,0), "000.000e-0002"); // test for zero
1015
1016     strcpy (&aValuesStr(i++,0), "1000000000000000000000000000012345678901234567890"); // huge mantissa
1017     strcpy (&aValuesStr(i++,0), "0000000000.00000000000000000012345678901234567890"); // leading zeros
1018     strcpy (&aValuesStr(i++,0), "1.00000000000000000000000000012345678901234567890"); // long fractional part
1019
1020     strcpy (&aValuesStr(i++,0), "0.0000000001e318"); // large exponent but no overflow
1021     strcpy (&aValuesStr(i++,0), "-1.7976931348623158e+308"); // -DBL_MAX 
1022     strcpy (&aValuesStr(i++,0), "1.79769313486232e+308"); // overflow
1023
1024     strcpy (&aValuesStr(i++,0), "10000000000e-310"); // large negative exponent but no underflow
1025     strcpy (&aValuesStr(i++,0), "1.1e-310"); // underflow
1026     strcpy (&aValuesStr(i++,0), "0.000001e-310"); // underflow
1027     strcpy (&aValuesStr(i++,0), "2.2250738585072014e-308"); // underflow, DBL_MIN
1028     strcpy (&aValuesStr(i++,0), "2.2250738585e-308"); // underflow, value less than DBL_MIN
1029
1030     strcpy (&aValuesStr(i++,0), "2.2204460492503131e-016"); // DBL_EPSILON
1031
1032     // random binary data
1033 //    std::default_random_engine aRandomEngine;
1034 //    std::uniform_int_distribution<uint64_t> aRandomDistr (0, ~(uint64_t)0);
1035     for (; i < aNbToTest; i++)
1036     {
1037       union {
1038         uint64_t valint;
1039         double valdbl;
1040       } aVal;
1041 //      aVal.valint = aRandomDistr (aRandomEngine);
1042       aVal.valint = ((uint64_t)aRandom.NextInt() << 32) + aRandom.NextInt();
1043       Sprintf(&aValuesStr(i,0), aFormat, aVal.valdbl);
1044     }
1045   }
1046
1047   // test different methods
1048 #define TEST_ATOF(method) \
1049   OSD_Timer aT_##method; aT_##method.Start(); \
1050   double aRes_##method = 0.; \
1051   for (int i = 0; i < aNbToTest; i++) { aRes_##method += test_##method (&aValuesStr(i,0)); } \
1052   aT_##method.Stop()
1053
1054   TEST_ATOF(sscanf);
1055   TEST_ATOF(strtod);
1056   TEST_ATOF(atof);
1057   TEST_ATOF(Strtod);
1058   TEST_ATOF(Atof);
1059 #undef TEST_ATOF
1060
1061   // test different methods
1062 #define CHECK_ATOF(method) \
1063   int aNbErr_##method = check_atof (aValuesStr, aFormat, test_##method, di); \
1064   di << "Checking " << #method << ": " << aNbErr_##method << " deviations\n"
1065
1066   CHECK_ATOF(sscanf);
1067   CHECK_ATOF(strtod);
1068   CHECK_ATOF(atof);
1069   CHECK_ATOF(Strtod);
1070   CHECK_ATOF(Atof);
1071 #undef CHECK_ATOF
1072
1073 /* compare results with atof */
1074 #ifdef _MSC_VER
1075 #define ISFINITE _finite
1076 #else
1077 #define ISFINITE std::isfinite
1078 #endif
1079   int nbErr = 0;
1080   for (int i = 0; i < aNbToTest; i++)
1081   {
1082     char *aStr = &aValuesStr(i,0), *anEndOCCT, *anEndStd;
1083     double aRes = Strtod (aStr, &anEndOCCT);
1084     double aRef = strtod (aStr, &anEndStd);
1085     if (ISFINITE(aRes) != ISFINITE(aRef))
1086     {
1087       nbErr++;
1088 #if defined(_MSC_VER) && _MSC_VER < 1900
1089       // MSVC < 2015 prints nan and inf as 1.#NAN or 1.INF, and noes not recognize nan or inf on read
1090       if (strstr (aStr, "1.#") || strstr (aStr, "nan") || strstr (aStr, "inf") || 
1091           strstr (aStr, "NAN") || strstr (aStr, "INF"))
1092         continue;
1093 #endif
1094       if (nbErr < 5)
1095       {
1096         char aBuff[256];
1097         Sprintf (aBuff, "Error parsing %s: %.20lg / %.20lg\n", aStr, aRes, aRef);
1098         di << aBuff;
1099       }
1100     }
1101     else if (ISFINITE(aRef) && Abs (aRes - aRef) > Epsilon (aRef))
1102     {
1103       nbErr++;
1104       if (nbErr < 5)
1105       {
1106         char aBuff[256];
1107         Sprintf (aBuff, "Error parsing %s: %.20lg / %.20lg\n", aStr, aRes, aRef);
1108         di << aBuff;
1109         Sprintf (aBuff, "[Delta = %.8lg, Epsilon = %.8lg]\n", Abs (aRes - aRef), Epsilon (aRef));
1110         di << aBuff;
1111       }
1112     }
1113
1114     // check that Strtod() and strtod() stop at the same place;
1115     // this makes sense for reading special values such as "nan" and thus
1116     // is not relevant for MSVC 2010 and earlier than do not support these
1117 #if ! defined(_MSC_VER) || _MSC_VER >= 1700
1118     if (anEndOCCT != anEndStd)
1119     {
1120       nbErr++;
1121       if (nbErr < 5)
1122         di << "Error: different number of symbols parsed in " 
1123            << aStr << ": " << (int)(anEndOCCT - aStr) << " / " << (int)(anEndStd - aStr) << "\n";
1124     }
1125 #endif
1126   }
1127   di << "Total " << nbErr << " defiations from strtod() found\n"; 
1128 /* */
1129
1130   // print results
1131   di << "Method\t      CPU\t  Elapsed   \t    Deviations \tChecksum\n";
1132
1133 #define PRINT_RES(method) \
1134   di << #method "\t" << aT_##method.UserTimeCPU() << "  \t" << aT_##method.ElapsedTime() << "\t" \
1135   << aNbErr_##method << "\t" << aRes_##method << "\n"
1136   PRINT_RES(sscanf);
1137   PRINT_RES(strtod);
1138   PRINT_RES(atof);
1139   PRINT_RES(Strtod);
1140   PRINT_RES(Atof);
1141 #undef PRINT_RES
1142
1143   return 0;
1144 }
1145
1146 // Test operations with NCollection_Vec4 that caused generation of invalid code by GCC
1147 // due to reinterpret_cast conversions of Vec4 internal buffer to Vec3 (see #29825)
1148 static Standard_Integer QANColTestVec4 (Draw_Interpretor& theDI, Standard_Integer /*theNbArgs*/, const char** /*theArgVec*/)
1149 {
1150   NCollection_Mat4<float> aMatrix;
1151   aMatrix.Translate (NCollection_Vec3<float> (4.0f, 3.0f, 1.0f));
1152
1153   NCollection_Vec4<float> aPoints1[8];
1154   for (int aX = 0; aX < 2; ++aX)
1155   {
1156     for (int aY = 0; aY < 2; ++aY)
1157     {
1158       for (int aZ = 0; aZ < 2; ++aZ)
1159       {
1160         aPoints1[aX * 2 * 2 + aY * 2 + aZ] = NCollection_Vec4<float> (-1.0f + 2.0f * float(aX),
1161                                                                       -1.0f + 2.0f * float(aY),
1162                                                                       -1.0f + 2.0f * float(aZ),
1163                                                                        1.0f);
1164       }
1165     }
1166   }
1167
1168   NCollection_Vec3<float> aPoints2[8];
1169   for (int aPntIdx = 0; aPntIdx < 8; ++aPntIdx)
1170   {
1171     // NB: the evaluation of line below could be dropped by GCC optimizer
1172     // while retrieving xyz() value the line after
1173     aPoints1[aPntIdx] = aMatrix * aPoints1[aPntIdx];
1174     aPoints2[aPntIdx] = aPoints1[aPntIdx].xyz() / aPoints1[aPntIdx].w();
1175     //aPoints2[aPntIdx] = NCollection_Vec3<float> (aPoints1[aPntIdx].x(), aPoints1[aPntIdx].y(), aPoints1[aPntIdx].z()) / aPoints1[aPntIdx].w();
1176   }
1177
1178   for (int aPntIter = 0; aPntIter < 8; ++aPntIter) { theDI << aPoints2[aPntIter].SquareModulus() << " "; }
1179   if ((int )(aPoints2[7].SquareModulus() + 0.5f) != 45)
1180   {
1181     theDI << "Error: method 'NCollection_Vec4::xyz()' failed.";
1182   }
1183   return 0;
1184 }
1185
1186 void QANCollection::CommandsTest(Draw_Interpretor& theCommands) {
1187   const char *group = "QANCollection";
1188
1189   theCommands.Add("QANColTestArray1",         "QANColTestArray1 Lower Upper",
1190     __FILE__, QANColTestArray1, group);
1191   theCommands.Add("QANColTestArray2",         "QANColTestArray2 LowerRow UpperRow LowerCol UpperCol",
1192     __FILE__, QANColTestArray2, group);  
1193   theCommands.Add("QANColTestMap",            "QANColTestMap",            __FILE__, QANColTestMap,            group);  
1194   theCommands.Add("QANColTestDataMap",        "QANColTestDataMap",        __FILE__, QANColTestDataMap,        group);  
1195   theCommands.Add("QANColTestDoubleMap",      "QANColTestDoubleMap",      __FILE__, QANColTestDoubleMap,      group);  
1196   theCommands.Add("QANColTestIndexedMap",     "QANColTestIndexedMap",     __FILE__, QANColTestIndexedMap,     group);  
1197   theCommands.Add("QANColTestIndexedDataMap", "QANColTestIndexedDataMap", __FILE__, QANColTestIndexedDataMap, group);  
1198   theCommands.Add("QANColTestList",           "QANColTestList",           __FILE__, QANColTestList,           group);  
1199   theCommands.Add("QANColTestSequence",       "QANColTestSequence",       __FILE__, QANColTestSequence,       group);  
1200   theCommands.Add("QANColTestVector",         "QANColTestVector",         __FILE__, QANColTestVector,         group);  
1201   theCommands.Add("QANColTestArrayMove",      "QANColTestArrayMove (is expected to give error)", __FILE__, QANColTestArrayMove, group);  
1202   theCommands.Add("QANColTestVec4",           "QANColTestVec4 test Vec4 implementation", __FILE__, QANColTestVec4, group);
1203   theCommands.Add("QATestAtof", "QATestAtof [nbvalues [nbdigits [min [max]]]]", __FILE__, QATestAtof, group);
1204 }