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