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