1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: TestArrayLookup.cxx
5
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 All rights reserved.
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
13
14 =========================================================================*/
15
16 #include "vtkBitArray.h"
17 #include "vtkIdList.h"
18 #include "vtkIdTypeArray.h"
19 #include "vtkIntArray.h"
20 #include "vtkSortDataArray.h"
21 #include "vtkStringArray.h"
22 #include "vtkTimerLog.h"
23 #include "vtkVariantArray.h"
24
25 #include "vtkSmartPointer.h"
26 #define VTK_CREATE(type,name) \
27 vtkSmartPointer<type> name = vtkSmartPointer<type>::New()
28
29 #include <vtksys/stl/vector>
30 #include <vtksys/stl/algorithm>
31 #include <vtksys/stl/utility>
32 #include <vtksys/stl/map>
33
34 struct NodeCompare
35 {
operator ()NodeCompare36 bool operator()(const vtksys_stl::pair<int, vtkIdType>& a, const vtksys_stl::pair<int, vtkIdType>& b) const
37 {
38 return a.first < b.first;
39 }
40 };
41
LookupValue(vtksys_stl::multimap<int,vtkIdType> & lookup,int value)42 vtkIdType LookupValue(vtksys_stl::multimap<int, vtkIdType>& lookup, int value)
43 {
44 vtksys_stl::pair<const int, vtkIdType> found = *lookup.lower_bound(value);
45 if (found.first == value)
46 {
47 return found.second;
48 }
49 return -1;
50 }
51
LookupValue(vtksys_stl::vector<vtksys_stl::pair<int,vtkIdType>> & lookup,int value)52 vtkIdType LookupValue(vtksys_stl::vector<vtksys_stl::pair<int, vtkIdType> >& lookup, int value)
53 {
54 NodeCompare comp;
55 vtksys_stl::pair<int, vtkIdType> val(value, 0);
56 vtksys_stl::pair<int, vtkIdType> found =
57 *vtksys_stl::lower_bound(lookup.begin(), lookup.end(), val, comp);
58 if (found.first == value)
59 {
60 return found.second;
61 }
62 return -1;
63 }
64
LookupValue(vtkIntArray * lookup,vtkIdTypeArray * index,int value)65 vtkIdType LookupValue(vtkIntArray* lookup, vtkIdTypeArray* index, int value)
66 {
67 int* ptr = lookup->GetPointer(0);
68 vtkIdType place = static_cast<vtkIdType>(vtksys_stl::lower_bound(ptr, ptr + lookup->GetNumberOfTuples(), value) - ptr);
69 if (place < lookup->GetNumberOfTuples() && ptr[place] == value)
70 {
71 return index->GetValue(place);
72 }
73 return -1;
74 }
75
TestArrayLookupBit(vtkIdType numVal)76 int TestArrayLookupBit(vtkIdType numVal)
77 {
78 int errors = 0;
79
80 // Create the array
81 vtkIdType arrSize = (numVal-1)*numVal/2;
82 VTK_CREATE(vtkBitArray, arr);
83 for (vtkIdType i = 0; i < arrSize; i++)
84 {
85 arr->InsertNextValue(i < arrSize/2);
86 }
87
88 //
89 // Test lookup implemented inside data array
90 //
91
92 // Time the lookup creation
93 VTK_CREATE(vtkTimerLog, timer);
94 timer->StartTimer();
95 arr->LookupValue(0);
96 timer->StopTimer();
97 cerr << "," << timer->GetElapsedTime();
98
99 // Time simple lookup
100 timer->StartTimer();
101 for (vtkIdType i = 0; i < numVal; i++)
102 {
103 arr->LookupValue(i % 2);
104 }
105 timer->StopTimer();
106 cerr << "," << (timer->GetElapsedTime() / static_cast<double>(numVal));
107
108 // Time list lookup
109 VTK_CREATE(vtkIdList, list);
110 timer->StartTimer();
111 for (vtkIdType i = 0; i < numVal; i++)
112 {
113 arr->LookupValue(i % 2, list);
114 }
115 timer->StopTimer();
116 cerr << "," << (timer->GetElapsedTime() / static_cast<double>(numVal));
117
118 // Test for correctness (-1)
119 vtkIdType index = -1;
120 index = arr->LookupValue(-1);
121 if (index != -1)
122 {
123 cerr << "ERROR: lookup found value at " << index << " but is not there (should return -1)" << endl;
124 errors++;
125 }
126 arr->LookupValue(-1, list);
127 if (list->GetNumberOfIds() != 0)
128 {
129 cerr << "ERROR: lookup found " << list->GetNumberOfIds() << " matches but there should be " << 0 << endl;
130 errors++;
131 }
132
133 // Test for correctness (0)
134 index = arr->LookupValue(0);
135 if (index < arrSize/2 || index > arrSize-1)
136 {
137 cerr << "ERROR: vector lookup found value at " << index << " but is in range [" << arrSize/2 << "," << arrSize-1 << "]" << endl;
138 errors++;
139 }
140 arr->LookupValue(0, list);
141 if (list->GetNumberOfIds() != arrSize - arrSize/2)
142 {
143 cerr << "ERROR: lookup found " << list->GetNumberOfIds() << " matches but there should be " << arrSize - arrSize/2 << endl;
144 errors++;
145 }
146 else
147 {
148 for (vtkIdType j = 0; j < list->GetNumberOfIds(); j++)
149 {
150 if (arr->GetValue(list->GetId(j)) != 0)
151 {
152 cerr << "ERROR: could not find " << j << " in found list" << endl;
153 errors++;
154 }
155 }
156 }
157
158 // Test for correctness (1)
159 index = arr->LookupValue(1);
160 if (index < 0 || index > arrSize/2-1)
161 {
162 cerr << "ERROR: vector lookup found value at " << index << " but is in range [" << 0 << "," << arrSize/2-1 << "]" << endl;
163 errors++;
164 }
165 arr->LookupValue(1, list);
166 if (list->GetNumberOfIds() != arrSize/2)
167 {
168 cerr << "ERROR: lookup found " << list->GetNumberOfIds() << " matches but there should be " << arrSize/2 << endl;
169 errors++;
170 }
171 else
172 {
173 for (vtkIdType j = 0; j < list->GetNumberOfIds(); j++)
174 {
175 if (arr->GetValue(list->GetId(j)) != 1)
176 {
177 cerr << "ERROR: could not find " << j << " in found list" << endl;
178 errors++;
179 }
180 }
181 }
182
183 return errors;
184 }
185
TestArrayLookupVariant(vtkIdType numVal)186 int TestArrayLookupVariant(vtkIdType numVal)
187 {
188 int errors = 0;
189
190 // Create the array
191 vtkIdType arrSize = (numVal-1)*numVal/2;
192 VTK_CREATE(vtkVariantArray, arr);
193 for (vtkIdType i = 0; i < numVal; i++)
194 {
195 for (vtkIdType j = 0; j < numVal-1-i; j++)
196 {
197 arr->InsertNextValue(numVal-1-i);
198 }
199 }
200
201 //
202 // Test lookup implemented inside data array
203 //
204
205 // Time the lookup creation
206 VTK_CREATE(vtkTimerLog, timer);
207 timer->StartTimer();
208 arr->LookupValue(0);
209 timer->StopTimer();
210 cerr << "," << timer->GetElapsedTime();
211
212 // Time simple lookup
213 timer->StartTimer();
214 for (vtkIdType i = 0; i < numVal; i++)
215 {
216 arr->LookupValue(i);
217 }
218 timer->StopTimer();
219 cerr << "," << (timer->GetElapsedTime() / static_cast<double>(numVal));
220
221 // Time list lookup
222 VTK_CREATE(vtkIdList, list);
223 timer->StartTimer();
224 for (vtkIdType i = 0; i < numVal; i++)
225 {
226 arr->LookupValue(i, list);
227 }
228 timer->StopTimer();
229 cerr << "," << (timer->GetElapsedTime() / static_cast<double>(numVal));
230
231 // Test for correctness
232 vtkIdType correctIndex = arrSize;
233 for (vtkIdType i = 0; i < numVal; i++)
234 {
235 correctIndex -= i;
236 vtkIdType index = arr->LookupValue(i);
237 if (i == 0 && index != -1)
238 {
239 cerr << "ERROR: lookup found value at " << index << " but is at -1" << endl;
240 errors++;
241 }
242 if (i != 0 && (index < correctIndex || index > correctIndex + i - 1))
243 {
244 cerr << "ERROR: vector lookup found value at " << index << " but is in range [" << correctIndex << "," << correctIndex + i - 1 << "]" << endl;
245 errors++;
246 }
247 arr->LookupValue(i, list);
248 if (list->GetNumberOfIds() != i)
249 {
250 cerr << "ERROR: lookup found " << list->GetNumberOfIds() << " matches but there should be " << i << endl;
251 errors++;
252 }
253 else
254 {
255 for (vtkIdType j = correctIndex; j < correctIndex + i; j++)
256 {
257 bool inList = false;
258 for (vtkIdType k = 0; k < i; ++k)
259 {
260 if (list->GetId(k) == j)
261 {
262 inList = true;
263 break;
264 }
265 }
266 if (!inList)
267 {
268 cerr << "ERROR: could not find " << j << " in found list" << endl;
269 errors++;
270 }
271 }
272 }
273 }
274 return errors;
275 }
276
TestArrayLookupString(vtkIdType numVal)277 int TestArrayLookupString(vtkIdType numVal)
278 {
279 int errors = 0;
280
281 // Create the array
282 vtkIdType arrSize = (numVal-1)*numVal/2;
283 VTK_CREATE(vtkStringArray, arr);
284 for (vtkIdType i = 0; i < numVal; i++)
285 {
286 for (vtkIdType j = 0; j < numVal-1-i; j++)
287 {
288 arr->InsertNextValue(vtkVariant(numVal-1-i).ToString());
289 }
290 }
291
292 //
293 // Test lookup implemented inside data array
294 //
295
296 // Time the lookup creation
297 VTK_CREATE(vtkTimerLog, timer);
298 timer->StartTimer();
299 arr->LookupValue("0");
300 timer->StopTimer();
301 cerr << "," << timer->GetElapsedTime();
302
303 // Time simple lookup
304 timer->StartTimer();
305 for (vtkIdType i = 0; i < numVal; i++)
306 {
307 arr->LookupValue(vtkVariant(i).ToString());
308 }
309 timer->StopTimer();
310 cerr << "," << (timer->GetElapsedTime() / static_cast<double>(numVal));
311
312 // Time list lookup
313 VTK_CREATE(vtkIdList, list);
314 timer->StartTimer();
315 for (vtkIdType i = 0; i < numVal; i++)
316 {
317 arr->LookupValue(vtkVariant(i).ToString(), list);
318 }
319 timer->StopTimer();
320 cerr << "," << (timer->GetElapsedTime() / static_cast<double>(numVal));
321
322 // Test for correctness
323 vtkIdType correctIndex = arrSize;
324 for (vtkIdType i = 0; i < numVal; i++)
325 {
326 correctIndex -= i;
327 vtkIdType index = arr->LookupValue(vtkVariant(i).ToString());
328 if (i == 0 && index != -1)
329 {
330 cerr << "ERROR: lookup found value at " << index << " but is at -1" << endl;
331 errors++;
332 }
333 if (i != 0 && (index < correctIndex || index > correctIndex + i - 1))
334 {
335 cerr << "ERROR: vector lookup found value at " << index << " but is in range [" << correctIndex << "," << correctIndex + i - 1 << "]" << endl;
336 errors++;
337 }
338 arr->LookupValue(vtkVariant(i).ToString(), list);
339 if (list->GetNumberOfIds() != i)
340 {
341 cerr << "ERROR: lookup found " << list->GetNumberOfIds() << " matches but there should be " << i << endl;
342 errors++;
343 }
344 else
345 {
346 for (vtkIdType j = correctIndex; j < correctIndex + i; j++)
347 {
348 bool inList = false;
349 for (vtkIdType k = 0; k < i; ++k)
350 {
351 if (list->GetId(k) == j)
352 {
353 inList = true;
354 break;
355 }
356 }
357 if (!inList)
358 {
359 cerr << "ERROR: could not find " << j << " in found list" << endl;
360 errors++;
361 }
362 }
363 }
364 }
365 return errors;
366 }
367
TestArrayLookupInt(vtkIdType numVal,bool runComparison)368 int TestArrayLookupInt(vtkIdType numVal, bool runComparison)
369 {
370 int errors = 0;
371
372 // Create the array
373 vtkIdType arrSize = (numVal-1)*numVal/2;
374 VTK_CREATE(vtkIntArray, arr);
375 for (vtkIdType i = 0; i < numVal; i++)
376 {
377 for (vtkIdType j = 0; j < numVal-1-i; j++)
378 {
379 arr->InsertNextValue(numVal-1-i);
380 }
381 }
382
383 //
384 // Test lookup implemented inside data array
385 //
386
387 // Time the lookup creation
388 VTK_CREATE(vtkTimerLog, timer);
389 timer->StartTimer();
390 arr->LookupValue(0);
391 timer->StopTimer();
392 cerr << "," << timer->GetElapsedTime();
393
394 // Time simple lookup
395 timer->StartTimer();
396 for (vtkIdType i = 0; i < numVal; i++)
397 {
398 arr->LookupValue(i);
399 }
400 timer->StopTimer();
401 cerr << "," << (timer->GetElapsedTime() / static_cast<double>(numVal));
402
403 // Time list lookup
404 VTK_CREATE(vtkIdList, list);
405 timer->StartTimer();
406 for (vtkIdType i = 0; i < numVal; i++)
407 {
408 arr->LookupValue(i, list);
409 }
410 timer->StopTimer();
411 cerr << "," << (timer->GetElapsedTime() / static_cast<double>(numVal));
412
413 // Test for correctness
414 vtkIdType correctIndex = arrSize;
415 for (vtkIdType i = 0; i < numVal; i++)
416 {
417 correctIndex -= i;
418 vtkIdType index = arr->LookupValue(i);
419 if (i == 0 && index != -1)
420 {
421 cerr << "ERROR: lookup found value at " << index << " but is at -1" << endl;
422 errors++;
423 }
424 if (i != 0 && (index < correctIndex || index > correctIndex + i - 1))
425 {
426 cerr << "ERROR: vector lookup found value at " << index << " but is in range [" << correctIndex << "," << correctIndex + i - 1 << "]" << endl;
427 errors++;
428 }
429 arr->LookupValue(i, list);
430 if (list->GetNumberOfIds() != i)
431 {
432 cerr << "ERROR: lookup found " << list->GetNumberOfIds() << " matches but there should be " << i << endl;
433 errors++;
434 }
435 else
436 {
437 for (vtkIdType j = correctIndex; j < correctIndex + i; j++)
438 {
439 bool inList = false;
440 for (vtkIdType k = 0; k < i; ++k)
441 {
442 if (list->GetId(k) == j)
443 {
444 inList = true;
445 break;
446 }
447 }
448 if (!inList)
449 {
450 cerr << "ERROR: could not find " << j << " in found list" << endl;
451 errors++;
452 }
453 }
454 }
455 }
456
457 if (runComparison)
458 {
459 //
460 // Test STL map lookup
461 //
462
463 // Time the lookup creation
464 timer->StartTimer();
465 int* ptr = arr->GetPointer(0);
466 vtksys_stl::multimap<int, vtkIdType> map;
467 for (vtkIdType i = 0; i < arrSize; ++i, ++ptr)
468 {
469 map.insert(std::pair<const int, vtkIdType>(*ptr, i));
470 }
471 timer->StopTimer();
472 cerr << "," << timer->GetElapsedTime();
473
474 // Time simple lookup
475 timer->StartTimer();
476 for (vtkIdType i = 0; i < numVal; i++)
477 {
478 LookupValue(map, i);
479 }
480 timer->StopTimer();
481 cerr << "," << (timer->GetElapsedTime() / static_cast<double>(numVal));
482
483 // Test for correctness
484 correctIndex = arrSize;
485 for (vtkIdType i = 0; i < numVal; i++)
486 {
487 correctIndex -= i;
488 vtkIdType index = LookupValue(map, i);
489 if (i == 0 && index != -1)
490 {
491 cerr << "ERROR: lookup found value at " << index << " but is at -1" << endl;
492 errors++;
493 }
494 if (i != 0 && index != correctIndex)
495 {
496 cerr << "ERROR: lookup found value at " << index << " but is at " << correctIndex << endl;
497 errors++;
498 }
499 }
500
501 //
502 // Test STL vector lookup
503 //
504
505 // Time lookup creation
506 timer->StartTimer();
507 ptr = arr->GetPointer(0);
508 vtksys_stl::vector<vtksys_stl::pair<int, vtkIdType> > vec(arrSize);
509 for (vtkIdType i = 0; i < arrSize; ++i, ++ptr)
510 {
511 vec[i] = vtksys_stl::pair<int, vtkIdType>(*ptr, i);
512 }
513 NodeCompare comp;
514 vtksys_stl::sort(vec.begin(), vec.end(), comp);
515 timer->StopTimer();
516 cerr << "," << timer->GetElapsedTime();
517
518 // Time simple lookup
519 timer->StartTimer();
520 for (vtkIdType i = 0; i < numVal; i++)
521 {
522 LookupValue(vec, i);
523 }
524 timer->StopTimer();
525 cerr << "," << (timer->GetElapsedTime() / static_cast<double>(numVal));
526
527 // Test for correctness
528 correctIndex = arrSize;
529 for (vtkIdType i = 0; i < numVal; i++)
530 {
531 correctIndex -= i;
532 vtkIdType index = LookupValue(vec, i);
533 if (i == 0 && index != -1)
534 {
535 cerr << "ERROR: vector lookup found value at " << index << " but is at -1" << endl;
536 errors++;
537 }
538 if (i != 0 && (index < correctIndex || index > correctIndex + i - 1))
539 {
540 cerr << "ERROR: vector lookup found value at " << index << " but is in range [" << correctIndex << "," << correctIndex + i - 1 << "]" << endl;
541 errors++;
542 }
543 }
544
545 //
546 // Test sorted data array lookup
547 //
548
549 // Time lookup creation
550 timer->StartTimer();
551 VTK_CREATE(vtkIdTypeArray, indices);
552 indices->SetNumberOfTuples(arrSize);
553 vtkIdType* keyptr = indices->GetPointer(0);
554 for (vtkIdType i = 0; i < arrSize; ++i, ++keyptr)
555 {
556 *keyptr = i;
557 }
558 VTK_CREATE(vtkIntArray, sorted);
559 sorted->DeepCopy(arr);
560 vtkSortDataArray::Sort(sorted, indices);
561 timer->StopTimer();
562 cerr << "," << timer->GetElapsedTime();
563
564 // Time simple lookup
565 timer->StartTimer();
566 for (vtkIdType i = 0; i < numVal; i++)
567 {
568 LookupValue(sorted, indices, i);
569 }
570 timer->StopTimer();
571 cerr << "," << (timer->GetElapsedTime() / static_cast<double>(numVal));
572
573 // Test for correctness
574 correctIndex = arrSize;
575 for (vtkIdType i = 0; i < numVal; i++)
576 {
577 correctIndex -= i;
578 vtkIdType index = LookupValue(sorted, indices, i);
579 if (i == 0 && index != -1)
580 {
581 cerr << "ERROR: arr lookup found value at " << index << " but is at -1" << endl;
582 errors++;
583 }
584 if (i != 0 && (index < correctIndex || index > correctIndex + i - 1))
585 {
586 cerr << "ERROR: arr lookup found value at " << index << " but is in range [" << correctIndex << "," << correctIndex + i - 1 << "]" << endl;
587 errors++;
588 }
589 }
590 }
591
592 return errors;
593 }
594
TestArrayLookup(int argc,char * argv[])595 int TestArrayLookup(int argc, char* argv[])
596 {
597 vtkIdType min = 100;
598 vtkIdType max = 200;
599 int steps = 2;
600 bool runComparison = false;
601 for (int i = 0; i < argc; ++i)
602 {
603 if (!strcmp(argv[i], "-C"))
604 {
605 runComparison = true;
606 }
607 if (!strcmp(argv[i], "-m") && i+1 < argc)
608 {
609 ++i;
610 int size = atoi(argv[i]);
611 min = static_cast<int>((-1.0 + sqrt(1 + 8.0*size))/2.0);
612 }
613 if (!strcmp(argv[i], "-M") && i+1 < argc)
614 {
615 ++i;
616 int size = atoi(argv[i]);
617 max = static_cast<int>((-1.0 + sqrt(1 + 8.0*size))/2.0);
618 }
619 if (!strcmp(argv[i], "-S") && i+1 < argc)
620 {
621 ++i;
622 steps = atoi(argv[i]);
623 }
624 }
625
626 vtkIdType stepSize = (max-min)/(steps-1);
627 if (stepSize <= 0)
628 {
629 stepSize = 1;
630 }
631
632 int errors = 0;
633 cerr << "distinct values";
634 cerr << ",size";
635 cerr << ",create lookup";
636 cerr << ",index lookup";
637 cerr << ",list lookup";
638 if (runComparison)
639 {
640 cerr << ",create map lookup";
641 cerr << ",index map lookup";
642 cerr << ",create vector lookup";
643 cerr << ",index vector lookup";
644 cerr << ",create array lookup";
645 cerr << ",index array lookup";
646 }
647 cerr << ",string create lookup";
648 cerr << ",string index lookup";
649 cerr << ",string list lookup";
650 cerr << ",variant create lookup";
651 cerr << ",variant index lookup";
652 cerr << ",variant list lookup";
653 cerr << ",bit create lookup";
654 cerr << ",bit index lookup";
655 cerr << ",bit list lookup";
656 cerr << endl;
657 for (vtkIdType numVal = min; numVal <= max; numVal += stepSize)
658 {
659 vtkIdType total = numVal*(numVal+1)/2;
660 cerr << numVal << "," << total;
661 errors += TestArrayLookupInt(numVal, runComparison);
662 errors += TestArrayLookupString(numVal);
663 errors += TestArrayLookupVariant(numVal);
664 errors += TestArrayLookupBit(numVal);
665 cerr << endl;
666 }
667 return errors;
668 }
669