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