3a01a933 |
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 | |
985aed12 |
24 | #include <Precision.hxx> |
07bbde45 |
25 | #include <Standard_Overflow.hxx> |
985aed12 |
26 | |
e3a6386d |
27 | #include <NCollection_Vector.hxx> |
395a5977 |
28 | #include <NCollection_IncAllocator.hxx> |
e3a6386d |
29 | |
3a01a933 |
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) |
3a01a933 |
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) |
3a01a933 |
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) |
3a01a933 |
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 | |
395a5977 |
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 | |
3a01a933 |
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 | |
395a5977 |
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 | |
3a01a933 |
331 | // Clear |
332 | aS.Clear(); |
333 | } |
334 | |
335 | // ===================== Test methods of Map type ============================= |
336 | ////////////////////////////////void TestMap (QANCollection_Map& theM) |
d673da18 |
337 | static void TestMap(QANCollection_MapFunc& theM, Draw_Interpretor& theDI) |
3a01a933 |
338 | { |
3a01a933 |
339 | { |
d673da18 |
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(); |
3a01a933 |
378 | } |
d673da18 |
379 | |
380 | // Check method 'HasIntersection'. |
3a01a933 |
381 | { |
d673da18 |
382 | QANCollection_MapFunc aM1, aM2, aM3; |
3a01a933 |
383 | |
d673da18 |
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 | } |
3a01a933 |
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); |
985aed12 |
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 | } |
3a01a933 |
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 | } |
985aed12 |
622 | // Substitute with different keys |
3a01a933 |
623 | Random(aKey); |
624 | aM.Substitute (1, aKey, anItem); |
985aed12 |
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 | } |
3a01a933 |
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) { |
586db386 |
654 | di << "Usage : " << argv[0] << " Lower Upper\n"; |
3a01a933 |
655 | return 1; |
656 | } |
657 | Lower = Draw::Atoi(argv[1]); |
658 | Upper = Draw::Atoi(argv[2]); |
659 | if ( Lower > Upper ) { |
586db386 |
660 | di << "Lower > Upper\n"; |
3a01a933 |
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) { |
586db386 |
673 | di << "Usage : " << argv[0] << " LowerRow UpperRow LowerCol UpperCol\n"; |
3a01a933 |
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 ) { |
586db386 |
681 | di << "LowerRow > UpperRow\n"; |
3a01a933 |
682 | return 1; |
683 | } |
684 | if ( LowerCol > UpperCol ) { |
586db386 |
685 | di << "LowerCol UpperCol> \n"; |
3a01a933 |
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 | return 0; |
720 | } |
721 | |
722 | //======================================================================= |
723 | //function : QANColTestMap |
724 | //purpose : |
725 | //======================================================================= |
726 | static Standard_Integer QANColTestMap(Draw_Interpretor& di, Standard_Integer argc, const char ** argv) |
727 | { |
728 | if ( argc != 1) { |
729 | di << "Usage : " << argv[0] << "\n"; |
730 | return 1; |
731 | } |
732 | QANCollection_MapFunc aMap; |
d673da18 |
733 | TestMap(aMap, di); |
3a01a933 |
734 | return 0; |
735 | } |
736 | |
737 | //======================================================================= |
738 | //function : QANColTestDataMap |
739 | //purpose : |
740 | //======================================================================= |
741 | static Standard_Integer QANColTestDataMap(Draw_Interpretor& di, Standard_Integer argc, const char ** argv) |
742 | { |
743 | if ( argc != 1) { |
744 | di << "Usage : " << argv[0] << "\n"; |
745 | return 1; |
746 | } |
747 | QANCollection_DataMapFunc aDataMap; |
748 | TestDataMap(aDataMap); |
749 | return 0; |
750 | } |
751 | |
752 | //======================================================================= |
753 | //function : QANColTestDoubleMap |
754 | //purpose : |
755 | //======================================================================= |
756 | static Standard_Integer QANColTestDoubleMap(Draw_Interpretor& di, Standard_Integer argc, const char ** argv) |
757 | { |
758 | if ( argc != 1) { |
759 | di << "Usage : " << argv[0] << "\n"; |
760 | return 1; |
761 | } |
762 | QANCollection_DoubleMapFunc aDoubleMap; |
763 | TestDoubleMap(aDoubleMap); |
764 | return 0; |
765 | } |
766 | |
767 | //======================================================================= |
768 | //function : QANColTestIndexedMap |
769 | //purpose : |
770 | //======================================================================= |
771 | static Standard_Integer QANColTestIndexedMap(Draw_Interpretor& di, Standard_Integer argc, const char ** argv) |
772 | { |
773 | if ( argc != 1) { |
774 | di << "Usage : " << argv[0] << "\n"; |
775 | return 1; |
776 | } |
777 | QANCollection_IndexedMapFunc aIndexedMap; |
778 | TestIndexedMap(aIndexedMap); |
779 | return 0; |
780 | } |
781 | |
782 | //======================================================================= |
783 | //function : QANColTestIndexedDataMap |
784 | //purpose : |
785 | //======================================================================= |
786 | static Standard_Integer QANColTestIndexedDataMap(Draw_Interpretor& di, Standard_Integer argc, const char ** argv) |
787 | { |
788 | if ( argc != 1) { |
789 | di << "Usage : " << argv[0] << "\n"; |
790 | return 1; |
791 | } |
792 | QANCollection_IDMapFunc aIDMap; |
793 | TestIndexedDataMap(aIDMap); |
794 | return 0; |
795 | } |
796 | |
797 | //======================================================================= |
798 | //function : QANColTestList |
799 | //purpose : |
800 | //======================================================================= |
801 | static Standard_Integer QANColTestList(Draw_Interpretor& di, Standard_Integer argc, const char ** argv) |
802 | { |
803 | if ( argc != 1) { |
804 | di << "Usage : " << argv[0] << "\n"; |
805 | return 1; |
806 | } |
807 | QANCollection_ListFunc aList; |
808 | TestList(aList); |
809 | return 0; |
810 | } |
811 | |
e3a6386d |
812 | //======================================================================= |
813 | //function : QANColTestVector |
814 | //purpose : |
815 | //======================================================================= |
816 | static Standard_Integer QANColTestVector (Draw_Interpretor&, Standard_Integer, const char**) |
817 | { |
818 | // test method Append and copying of empty vector |
819 | NCollection_Vector<int> aVec; |
820 | NCollection_Vector<int> aVec2 (aVec); |
821 | NCollection_Vector<int> aVec3; |
822 | aVec3 = aVec; |
823 | |
824 | aVec.Append(5); |
825 | if (aVec(0) != 5) |
826 | std::cout << "Error: wrong value in original vector!" << endl; |
827 | aVec2.Append(5); |
828 | if (aVec2(0) != 5) |
829 | std::cout << "Error: wrong value in copy-constructed vector!" << endl; |
830 | aVec3.Append(5); |
831 | if (aVec3(0) != 5) |
832 | std::cout << "Error: wrong value in copied vector!" << endl; |
833 | std::cout << "Test OK" << endl; |
834 | |
835 | return 0; |
836 | } |
837 | |
3a01a933 |
838 | //======================================================================= |
839 | //function : QANColTestSequence |
840 | //purpose : |
841 | //======================================================================= |
842 | static Standard_Integer QANColTestSequence(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_SequenceFunc aSeq; |
849 | TestSequence(aSeq); |
850 | return 0; |
851 | } |
852 | |
6286195c |
853 | //======================================================================= |
854 | //function : QANColTestMove |
855 | //purpose : |
856 | //======================================================================= |
857 | |
858 | // Return array based on local C array buffer by value. |
859 | // Note that this is expected to cause errors due |
860 | // to the fact that returned copy will keep reference to the |
861 | // buffer allocated in the stack of this function. |
862 | // Unfortunately, this cannot be prevented due to the fact that |
863 | // modern compilers use return value optimization in release mode |
864 | // (object that is returned is constructed once at its target |
865 | // place and never copied). |
866 | static NCollection_Array1<double> GetArrayByValue() |
867 | { |
868 | const int aLen = 1024; |
869 | double aCArray[aLen]; |
870 | NCollection_Array1<double> anArray (aCArray[0], 1, aLen); |
871 | for (int i = 1; i <= aLen; i++) |
872 | anArray.SetValue(i, i + 113.); |
873 | return anArray; |
874 | } |
875 | |
876 | // check array for possible corruption |
877 | static bool CheckArrayByValue(NCollection_Array1<double> theArray) |
878 | { |
879 | for (int i = 1; i <= theArray.Length(); i++) |
880 | { |
881 | if (theArray.Value(i) != i + 113.) |
882 | { |
883 | std::cout << "Error at item " << i << ": value = " << theArray.Value(i) << ", expected " << i + 113. << std::endl; |
884 | return false; |
885 | } |
886 | } |
887 | return true; |
888 | } |
889 | |
890 | static Standard_Integer QANColTestArrayMove (Draw_Interpretor& di, Standard_Integer argc, const char ** argv) |
891 | { |
892 | if ( argc != 1) { |
893 | di << "Usage : " << argv[0] << "\n"; |
894 | return 1; |
895 | } |
896 | NCollection_Array1<double> anArray = GetArrayByValue(); |
897 | di << (CheckArrayByValue(anArray) ? "Error: memory corruption is not detected" : "Expected behavior: memory is corrupted"); |
898 | return 0; |
899 | } |
900 | |
07bbde45 |
901 | #include <math_BullardGenerator.hxx> |
902 | #include <OSD_Timer.hxx> |
903 | |
904 | static inline double test_atof (const char* theStr) |
905 | { |
906 | return atof (theStr); |
907 | } |
908 | |
909 | static inline double test_Atof (const char* theStr) |
910 | { |
911 | return Atof (theStr); |
912 | } |
913 | |
914 | static inline double test_strtod (const char* theStr) |
915 | { |
916 | char *end; |
917 | return strtod (theStr, &end); |
918 | } |
919 | |
920 | static inline double test_Strtod (const char* theStr) |
921 | { |
922 | char *end; |
923 | return Strtod (theStr, &end); |
924 | } |
925 | |
926 | static inline double test_sscanf (const char* theStr) |
927 | { |
928 | double val = 0.; |
929 | sscanf (theStr, "%lf", &val); |
930 | return val; |
931 | } |
932 | |
933 | static int check_atof (const NCollection_Array2<char>& theStrings, const char* theFormat, |
934 | double (*test_func)(const char*), Draw_Interpretor& di) |
935 | { |
936 | int aNbErr = 0; |
937 | for (int i = 0; i < theStrings.UpperRow(); i++) |
938 | { |
939 | const char *aStr= &theStrings(i,0); |
940 | char buff[256]; |
941 | double aVal = test_func (aStr); |
942 | Sprintf (buff, theFormat, aVal); |
943 | if (strcasecmp (buff, &theStrings(i,0))) |
944 | { |
945 | #if defined(_MSC_VER) && _MSC_VER < 1900 |
946 | // MSVC < 2015 prints nan and inf as 1.#NAN or 1.INF, and noes not recognize nan or inf on read |
947 | if (strstr (aStr, "1.#") || strstr (aStr, "nan") || strstr (aStr, "inf") || |
948 | strstr (aStr, "NAN") || strstr (aStr, "INF")) |
949 | continue; |
950 | #endif |
951 | if (aNbErr < 5) |
952 | { |
953 | di << "Deviation parsing " << aStr << " and print back: " << buff << "\n"; |
954 | } |
955 | aNbErr++; |
956 | } |
957 | } |
958 | return aNbErr; |
959 | } |
960 | |
961 | // Test speed of standard and OCCT-specific (accelerated) functions to parse string to double |
962 | static Standard_Integer QATestAtof (Draw_Interpretor& di, Standard_Integer argc, const char ** argv) |
963 | { |
964 | int aNbToTest = Max (100, (argc > 1 ? Draw::Atoi(argv[1]) : 1000000)); |
965 | int aNbDigits = (argc > 2 ? Draw::Atoi(argv[2]) : 10); |
966 | double aRangeMin = (argc > 3 ? Draw::Atof(argv[3]) : -1e9); |
967 | double aRangeMax = (argc > 4 ? Draw::Atof(argv[4]) : 1e9); |
968 | |
969 | char aFormat[256]; |
970 | Sprintf (aFormat, "%%.%dlg", Max (2, Min (20, aNbDigits))); |
971 | |
972 | // prepare data |
973 | const int MAXLEN = 256; |
974 | NCollection_Array2<char> aValuesStr (0, aNbToTest - 1, 0, MAXLEN); |
975 | math_BullardGenerator aRandom; |
976 | |
977 | if (aRangeMin < aRangeMax) |
978 | { |
979 | // random values within specified range |
980 | // std::default_random_engine aRandomEngine; |
981 | // std::uniform_real_distribution<double> aRandomDistr (aRangeMin, aRangeMax); |
982 | const uint64_t aMaxUInt64 = ~(uint64_t)0; // could be (not supported by old GCC): std::numeric_limits<uint64_t>::max() |
983 | for (int i = 0; i < aNbToTest; i++) |
984 | { |
985 | // double aVal = aRandomDistr (aRandomEngine); |
986 | uint64_t aIVal = ((uint64_t)aRandom.NextInt() << 32) + aRandom.NextInt(); |
987 | double aVal = aRangeMin + (aIVal / (double)aMaxUInt64) * (aRangeMax - aRangeMin); |
988 | Sprintf(&aValuesStr(i,0), aFormat, aVal); |
989 | } |
990 | } |
991 | else |
992 | { |
993 | // special values |
994 | int i = 0; |
995 | |
996 | strcpy (&aValuesStr(i++,0), "nan"); |
997 | strcpy (&aValuesStr(i++,0), "nan(qnan)"); |
998 | strcpy (&aValuesStr(i++,0), "NAN"); |
999 | strcpy (&aValuesStr(i++,0), "-nan"); |
1000 | strcpy (&aValuesStr(i++,0), "-NAN"); |
1001 | strcpy (&aValuesStr(i++,0), "inf"); |
1002 | strcpy (&aValuesStr(i++,0), "INF"); |
1003 | strcpy (&aValuesStr(i++,0), "-inf"); |
1004 | strcpy (&aValuesStr(i++,0), "-INF"); |
1005 | |
1006 | strcpy (&aValuesStr(i++,0), " ."); // standalone period should not be considered as a number |
1007 | strcpy (&aValuesStr(i++,0), "nanabcdef_128 xx"); // extra non-parenthised sequence after "nan" |
1008 | |
1009 | strcpy (&aValuesStr(i++,0), "905791934.11394954"); // value that gets rounded in a wrong way by fast Strtod() |
1010 | strcpy (&aValuesStr(i++,0), "9.343962790444495e+148"); // value where strtod() and Strtod() differ by 2 Epsilon |
1011 | |
1012 | strcpy (&aValuesStr(i++,0), " 12345.67text"); // test for leading whitespaces and trailing text |
1013 | strcpy (&aValuesStr(i++,0), "000.000"); // test for zero |
1014 | strcpy (&aValuesStr(i++,0), "000.000e-0002"); // test for zero |
1015 | |
1016 | strcpy (&aValuesStr(i++,0), "1000000000000000000000000000012345678901234567890"); // huge mantissa |
1017 | strcpy (&aValuesStr(i++,0), "0000000000.00000000000000000012345678901234567890"); // leading zeros |
1018 | strcpy (&aValuesStr(i++,0), "1.00000000000000000000000000012345678901234567890"); // long fractional part |
1019 | |
1020 | strcpy (&aValuesStr(i++,0), "0.0000000001e318"); // large exponent but no overflow |
1021 | strcpy (&aValuesStr(i++,0), "-1.7976931348623158e+308"); // -DBL_MAX |
1022 | strcpy (&aValuesStr(i++,0), "1.79769313486232e+308"); // overflow |
1023 | |
1024 | strcpy (&aValuesStr(i++,0), "10000000000e-310"); // large negative exponent but no underflow |
1025 | strcpy (&aValuesStr(i++,0), "1.1e-310"); // underflow |
1026 | strcpy (&aValuesStr(i++,0), "0.000001e-310"); // underflow |
1027 | strcpy (&aValuesStr(i++,0), "2.2250738585072014e-308"); // underflow, DBL_MIN |
1028 | strcpy (&aValuesStr(i++,0), "2.2250738585e-308"); // underflow, value less than DBL_MIN |
1029 | |
1030 | strcpy (&aValuesStr(i++,0), "2.2204460492503131e-016"); // DBL_EPSILON |
1031 | |
1032 | // random binary data |
1033 | // std::default_random_engine aRandomEngine; |
1034 | // std::uniform_int_distribution<uint64_t> aRandomDistr (0, ~(uint64_t)0); |
1035 | for (; i < aNbToTest; i++) |
1036 | { |
1037 | union { |
1038 | uint64_t valint; |
1039 | double valdbl; |
1040 | } aVal; |
1041 | // aVal.valint = aRandomDistr (aRandomEngine); |
1042 | aVal.valint = ((uint64_t)aRandom.NextInt() << 32) + aRandom.NextInt(); |
1043 | Sprintf(&aValuesStr(i,0), aFormat, aVal.valdbl); |
1044 | } |
1045 | } |
1046 | |
1047 | // test different methods |
1048 | #define TEST_ATOF(method) \ |
1049 | OSD_Timer aT_##method; aT_##method.Start(); \ |
1050 | double aRes_##method = 0.; \ |
1051 | for (int i = 0; i < aNbToTest; i++) { aRes_##method += test_##method (&aValuesStr(i,0)); } \ |
1052 | aT_##method.Stop() |
1053 | |
1054 | TEST_ATOF(sscanf); |
1055 | TEST_ATOF(strtod); |
1056 | TEST_ATOF(atof); |
1057 | TEST_ATOF(Strtod); |
1058 | TEST_ATOF(Atof); |
1059 | #undef TEST_ATOF |
1060 | |
1061 | // test different methods |
1062 | #define CHECK_ATOF(method) \ |
1063 | int aNbErr_##method = check_atof (aValuesStr, aFormat, test_##method, di); \ |
1064 | di << "Checking " << #method << ": " << aNbErr_##method << " deviations\n" |
1065 | |
1066 | CHECK_ATOF(sscanf); |
1067 | CHECK_ATOF(strtod); |
1068 | CHECK_ATOF(atof); |
1069 | CHECK_ATOF(Strtod); |
1070 | CHECK_ATOF(Atof); |
1071 | #undef CHECK_ATOF |
1072 | |
1073 | /* compare results with atof */ |
1074 | #ifdef _MSC_VER |
1075 | #define ISFINITE _finite |
1076 | #else |
1077 | #define ISFINITE std::isfinite |
1078 | #endif |
1079 | int nbErr = 0; |
1080 | for (int i = 0; i < aNbToTest; i++) |
1081 | { |
1082 | char *aStr = &aValuesStr(i,0), *anEndOCCT, *anEndStd; |
1083 | double aRes = Strtod (aStr, &anEndOCCT); |
1084 | double aRef = strtod (aStr, &anEndStd); |
1085 | if (ISFINITE(aRes) != ISFINITE(aRef)) |
1086 | { |
1087 | nbErr++; |
1088 | #if defined(_MSC_VER) && _MSC_VER < 1900 |
1089 | // MSVC < 2015 prints nan and inf as 1.#NAN or 1.INF, and noes not recognize nan or inf on read |
1090 | if (strstr (aStr, "1.#") || strstr (aStr, "nan") || strstr (aStr, "inf") || |
1091 | strstr (aStr, "NAN") || strstr (aStr, "INF")) |
1092 | continue; |
1093 | #endif |
1094 | if (nbErr < 5) |
1095 | { |
1096 | char aBuff[256]; |
1097 | Sprintf (aBuff, "Error parsing %s: %.20lg / %.20lg\n", aStr, aRes, aRef); |
1098 | di << aBuff; |
1099 | } |
1100 | } |
1101 | else if (ISFINITE(aRef) && Abs (aRes - aRef) > Epsilon (aRef)) |
1102 | { |
1103 | nbErr++; |
1104 | if (nbErr < 5) |
1105 | { |
1106 | char aBuff[256]; |
1107 | Sprintf (aBuff, "Error parsing %s: %.20lg / %.20lg\n", aStr, aRes, aRef); |
1108 | di << aBuff; |
1109 | Sprintf (aBuff, "[Delta = %.8lg, Epsilon = %.8lg]\n", Abs (aRes - aRef), Epsilon (aRef)); |
1110 | di << aBuff; |
1111 | } |
1112 | } |
1113 | |
1114 | // check that Strtod() and strtod() stop at the same place; |
1115 | // this makes sense for reading special values such as "nan" and thus |
1116 | // is not relevant for MSVC 2010 and earlier than do not support these |
1117 | #if ! defined(_MSC_VER) || _MSC_VER >= 1700 |
1118 | if (anEndOCCT != anEndStd) |
1119 | { |
1120 | nbErr++; |
1121 | if (nbErr < 5) |
1122 | di << "Error: different number of symbols parsed in " |
1123 | << aStr << ": " << (int)(anEndOCCT - aStr) << " / " << (int)(anEndStd - aStr) << "\n"; |
1124 | } |
1125 | #endif |
1126 | } |
1127 | di << "Total " << nbErr << " defiations from strtod() found\n"; |
1128 | /* */ |
1129 | |
1130 | // print results |
1131 | di << "Method\t CPU\t Elapsed \t Deviations \tChecksum\n"; |
1132 | |
1133 | #define PRINT_RES(method) \ |
1134 | di << #method "\t" << aT_##method.UserTimeCPU() << " \t" << aT_##method.ElapsedTime() << "\t" \ |
1135 | << aNbErr_##method << "\t" << aRes_##method << "\n" |
1136 | PRINT_RES(sscanf); |
1137 | PRINT_RES(strtod); |
1138 | PRINT_RES(atof); |
1139 | PRINT_RES(Strtod); |
1140 | PRINT_RES(Atof); |
1141 | #undef PRINT_RES |
1142 | |
1143 | return 0; |
1144 | } |
1145 | |
bc379358 |
1146 | // Test operations with NCollection_Vec4 that caused generation of invalid code by GCC |
1147 | // due to reinterpret_cast conversions of Vec4 internal buffer to Vec3 (see #29825) |
1148 | static Standard_Integer QANColTestVec4 (Draw_Interpretor& theDI, Standard_Integer /*theNbArgs*/, const char** /*theArgVec*/) |
1149 | { |
1150 | NCollection_Mat4<float> aMatrix; |
1151 | aMatrix.Translate (NCollection_Vec3<float> (4.0f, 3.0f, 1.0f)); |
1152 | |
1153 | NCollection_Vec4<float> aPoints1[8]; |
1154 | for (int aX = 0; aX < 2; ++aX) |
1155 | { |
1156 | for (int aY = 0; aY < 2; ++aY) |
1157 | { |
1158 | for (int aZ = 0; aZ < 2; ++aZ) |
1159 | { |
1160 | aPoints1[aX * 2 * 2 + aY * 2 + aZ] = NCollection_Vec4<float> (-1.0f + 2.0f * float(aX), |
1161 | -1.0f + 2.0f * float(aY), |
1162 | -1.0f + 2.0f * float(aZ), |
1163 | 1.0f); |
1164 | } |
1165 | } |
1166 | } |
1167 | |
1168 | NCollection_Vec3<float> aPoints2[8]; |
1169 | for (int aPntIdx = 0; aPntIdx < 8; ++aPntIdx) |
1170 | { |
1171 | // NB: the evaluation of line below could be dropped by GCC optimizer |
1172 | // while retrieving xyz() value the line after |
1173 | aPoints1[aPntIdx] = aMatrix * aPoints1[aPntIdx]; |
1174 | aPoints2[aPntIdx] = aPoints1[aPntIdx].xyz() / aPoints1[aPntIdx].w(); |
1175 | //aPoints2[aPntIdx] = NCollection_Vec3<float> (aPoints1[aPntIdx].x(), aPoints1[aPntIdx].y(), aPoints1[aPntIdx].z()) / aPoints1[aPntIdx].w(); |
1176 | } |
1177 | |
1178 | for (int aPntIter = 0; aPntIter < 8; ++aPntIter) { theDI << aPoints2[aPntIter].SquareModulus() << " "; } |
1179 | if ((int )(aPoints2[7].SquareModulus() + 0.5f) != 45) |
1180 | { |
1181 | theDI << "Error: method 'NCollection_Vec4::xyz()' failed."; |
1182 | } |
1183 | return 0; |
1184 | } |
1185 | |
3a01a933 |
1186 | void QANCollection::CommandsTest(Draw_Interpretor& theCommands) { |
1187 | const char *group = "QANCollection"; |
1188 | |
395a5977 |
1189 | theCommands.Add("QANColTestArray1", "QANColTestArray1 Lower Upper", |
1190 | __FILE__, QANColTestArray1, group); |
1191 | theCommands.Add("QANColTestArray2", "QANColTestArray2 LowerRow UpperRow LowerCol UpperCol", |
1192 | __FILE__, QANColTestArray2, group); |
3a01a933 |
1193 | theCommands.Add("QANColTestMap", "QANColTestMap", __FILE__, QANColTestMap, group); |
1194 | theCommands.Add("QANColTestDataMap", "QANColTestDataMap", __FILE__, QANColTestDataMap, group); |
1195 | theCommands.Add("QANColTestDoubleMap", "QANColTestDoubleMap", __FILE__, QANColTestDoubleMap, group); |
1196 | theCommands.Add("QANColTestIndexedMap", "QANColTestIndexedMap", __FILE__, QANColTestIndexedMap, group); |
1197 | theCommands.Add("QANColTestIndexedDataMap", "QANColTestIndexedDataMap", __FILE__, QANColTestIndexedDataMap, group); |
1198 | theCommands.Add("QANColTestList", "QANColTestList", __FILE__, QANColTestList, group); |
1199 | theCommands.Add("QANColTestSequence", "QANColTestSequence", __FILE__, QANColTestSequence, group); |
e3a6386d |
1200 | theCommands.Add("QANColTestVector", "QANColTestVector", __FILE__, QANColTestVector, group); |
07bbde45 |
1201 | theCommands.Add("QANColTestArrayMove", "QANColTestArrayMove (is expected to give error)", __FILE__, QANColTestArrayMove, group); |
bc379358 |
1202 | theCommands.Add("QANColTestVec4", "QANColTestVec4 test Vec4 implementation", __FILE__, QANColTestVec4, group); |
07bbde45 |
1203 | theCommands.Add("QATestAtof", "QATestAtof [nbvalues [nbdigits [min [max]]]]", __FILE__, QATestAtof, group); |
3a01a933 |
1204 | } |