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