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