1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    ArrayCasting.cxx
5 
6 -------------------------------------------------------------------------
7   Copyright 2008 Sandia Corporation.
8   Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9   the U.S. Government retains certain rights in this software.
10 -------------------------------------------------------------------------
11 
12   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
13   All rights reserved.
14   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
15 
16      This software is distributed WITHOUT ANY WARRANTY; without even
17      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
18      PURPOSE.  See the above copyright notice for more information.
19 
20 =========================================================================*/
21 
22 #include <vtkDenseArray.h>
23 #include <vtkSmartPointer.h>
24 #include <vtkSparseArray.h>
25 #include <vtkTryDowncast.h>
26 
27 #include <vtksys/ios/iostream>
28 #include <vtksys/ios/sstream>
29 #include <vtksys/stl/stdexcept>
30 
31 #include <boost/algorithm/string.hpp>
32 
33 #define VTK_CREATE(type, name) \
34   vtkSmartPointer<type> name = vtkSmartPointer<type>::New()
35 
36 #define test_expression(expression) \
37 { \
38   if(!(expression)) \
39     { \
40     std::ostringstream buffer; \
41     buffer << "Expression failed at line " << __LINE__ << ": " << #expression; \
42     throw std::runtime_error(buffer.str()); \
43     } \
44 }
45 
46 class DowncastTest
47 {
48 public:
DowncastTest(int & count)49   DowncastTest(int& count) :
50     Count(count)
51   {
52   }
53 
54   template<typename T>
operator ()(T * vtkNotUsed (array)) const55   void operator()(T* vtkNotUsed(array)) const
56   {
57     ++Count;
58   }
59 
60   int& Count;
61 
62 private:
63   DowncastTest& operator=(const DowncastTest&);
64 };
65 
66 template<template <typename> class TargetT, typename TypesT>
SuccessTest(vtkObject * source,int line)67 void SuccessTest(vtkObject* source, int line)
68 {
69   int count = 0;
70   if(!vtkTryDowncast<TargetT, TypesT>(source, DowncastTest(count)))
71     {
72     std::ostringstream buffer;
73     buffer << "Expression failed at line " << line;
74     throw std::runtime_error(buffer.str());
75     }
76 
77   if(count != 1)
78     {
79     std::ostringstream buffer;
80     buffer << "Functor was called " << count << " times at line " << line;
81     throw std::runtime_error(buffer.str());
82     }
83 }
84 
85 template<template <typename> class TargetT, typename TypesT>
FailTest(vtkObject * source,int line)86 void FailTest(vtkObject* source, int line)
87 {
88   int count = 0;
89   if(vtkTryDowncast<TargetT, TypesT>(source, DowncastTest(count)))
90     {
91     std::ostringstream buffer;
92     buffer << "Expression failed at line " << line;
93     throw std::runtime_error(buffer.str());
94     }
95 
96   if(count != 0)
97     {
98     std::ostringstream buffer;
99     buffer << "Functor was called " << count << " times at line " << line;
100     throw std::runtime_error(buffer.str());
101     }
102 }
103 
104 /*
105 // This functor increments array values in-place using a parameter passed via the algorithm (instead of a parameter
106 // stored in the functor).  It can work with any numeric array type.
107 struct IncrementValues
108 {
109   template<typename T>
110   void operator()(T* array, int amount) const
111   {
112     for(vtkIdType n = 0; n != array->GetNonNullSize(); ++n)
113       array->SetValueN(n, array->GetValueN(n) + amount);
114   }
115 };
116 
117 // This functor converts strings in-place to a form suitable for case-insensitive comparison.  It's an example of
118 // how you can write generic code while still specializing functionality on a case-by-case basis, since
119 // in this situation we want to use some special functionality provided by vtkUnicodeString.
120 struct FoldCase
121 {
122   template<typename ValueT>
123   void operator()(vtkTypedArray<ValueT>* array) const
124   {
125     for(vtkIdType n = 0; n != array->GetNonNullSize(); ++n)
126       {
127       ValueT value = array->GetValueN(n);
128       boost::algorithm::to_lower(value);
129       array->SetValueN(n, value);
130       }
131   }
132 
133   void operator()(vtkTypedArray<vtkUnicodeString>* array) const
134   {
135     for(vtkIdType n = 0; n != array->GetNonNullSize(); ++n)
136       array->SetValueN(n, array->GetValueN(n).fold_case());
137   }
138 };
139 
140 // This functor efficiently creates a transposed array.  It's one example of how you can create an output array
141 // with the same type as an input array.
142 struct Transpose
143 {
144   Transpose(vtkSmartPointer<vtkArray>& result_matrix) : ResultMatrix(result_matrix) {}
145 
146   template<typename ValueT>
147   void operator()(vtkDenseArray<ValueT>* input) const
148   {
149     if(input->GetDimensions() != 2 || input->GetExtents()[0] != input->GetExtents()[1])
150       throw std::runtime_error("A square matrix is required.");
151 
152     vtkDenseArray<ValueT>* output = vtkDenseArray<ValueT>::SafeDownCast(input->DeepCopy());
153     for(vtkIdType i = 0; i != input->GetExtents()[0]; ++i)
154       {
155       for(vtkIdType j = i + 1; j != input->GetExtents()[1]; ++j)
156         {
157         output->SetValue(i, j, input->GetValue(j, i));
158         output->SetValue(j, i, input->GetValue(i, j));
159         }
160       }
161 
162     this->ResultMatrix = output;
163   }
164 
165   vtkSmartPointer<vtkArray>& ResultMatrix;
166 };
167 */
168 
169 //
170 //
171 // Here are some examples of how the algorithm might be called.
172 //
173 //
174 
TestArrayCasting(int vtkNotUsed (argc),char * vtkNotUsed (argv)[])175 int TestArrayCasting(int vtkNotUsed(argc), char *vtkNotUsed(argv)[])
176 {
177   try
178     {
179     /* this "if" is a temporary workaround for the clang compiler,
180      * everything inside "#ifdef __clang__" should be removed when
181      * clang no longer needs these templates to be instantiated. */
182 #ifdef __clang__
183     VTK_CREATE(vtkDenseArray<vtkUnicodeString>, dense_unicode);
184     VTK_CREATE(vtkDenseArray<vtkStdString>, dense_string);
185     VTK_CREATE(vtkDenseArray<vtkTypeFloat32>, dense_float);
186     VTK_CREATE(vtkDenseArray<vtkTypeFloat64>, dense_double);
187     VTK_CREATE(vtkDenseArray<vtkTypeUInt8>, dense_uchar);
188     VTK_CREATE(vtkDenseArray<vtkTypeInt8>, dense_schar);
189     VTK_CREATE(vtkDenseArray<vtkTypeUInt16>, dense_ushort);
190     VTK_CREATE(vtkDenseArray<vtkTypeInt16>, dense_short);
191     VTK_CREATE(vtkDenseArray<vtkTypeUInt32>, dense_uint);
192     VTK_CREATE(vtkDenseArray<vtkTypeInt32>, dense_int);
193     VTK_CREATE(vtkDenseArray<vtkTypeUInt64>, dense_ulonglong);
194     VTK_CREATE(vtkDenseArray<vtkTypeInt64>, dense_longlong);
195     VTK_CREATE(vtkDenseArray<vtkIdType>, dense_idtype);
196     VTK_CREATE(vtkSparseArray<vtkUnicodeString>, sparse_unicode);
197     VTK_CREATE(vtkSparseArray<vtkStdString>, sparse_string);
198     VTK_CREATE(vtkSparseArray<vtkTypeFloat32>, sparse_float);
199     VTK_CREATE(vtkSparseArray<vtkTypeFloat64>, sparse_double);
200     VTK_CREATE(vtkSparseArray<vtkTypeUInt8>, sparse_uchar);
201     VTK_CREATE(vtkSparseArray<vtkTypeInt8>, sparse_schar);
202     VTK_CREATE(vtkSparseArray<vtkTypeUInt16>, sparse_ushort);
203     VTK_CREATE(vtkSparseArray<vtkTypeInt16>, sparse_short);
204     VTK_CREATE(vtkSparseArray<vtkTypeUInt32>, sparse_uint);
205     VTK_CREATE(vtkSparseArray<vtkTypeInt32>, sparse_int);
206     VTK_CREATE(vtkSparseArray<vtkTypeUInt64>, sparse_ulonglong);
207     VTK_CREATE(vtkSparseArray<vtkTypeInt64>, sparse_longlong);
208     VTK_CREATE(vtkSparseArray<vtkIdType>, sparse_idtype);
209 #else
210     VTK_CREATE(vtkDenseArray<int>, dense_int);
211     VTK_CREATE(vtkDenseArray<double>, dense_double);
212     VTK_CREATE(vtkDenseArray<vtkStdString>, dense_string);
213     VTK_CREATE(vtkSparseArray<int>, sparse_int);
214     VTK_CREATE(vtkSparseArray<double>, sparse_double);
215     VTK_CREATE(vtkSparseArray<vtkStdString>, sparse_string);
216 #endif
217 
218     SuccessTest<vtkTypedArray, vtkIntegerTypes>(dense_int, __LINE__);
219     FailTest<vtkTypedArray, vtkIntegerTypes>(dense_double, __LINE__);
220     FailTest<vtkTypedArray, vtkIntegerTypes>(dense_string, __LINE__);
221     SuccessTest<vtkTypedArray, vtkIntegerTypes>(sparse_int, __LINE__);
222     FailTest<vtkTypedArray, vtkIntegerTypes>(sparse_double, __LINE__);
223     FailTest<vtkTypedArray, vtkIntegerTypes>(sparse_string, __LINE__);
224 
225     FailTest<vtkTypedArray, vtkFloatingPointTypes>(dense_int, __LINE__);
226     SuccessTest<vtkTypedArray, vtkFloatingPointTypes>(dense_double, __LINE__);
227     FailTest<vtkTypedArray, vtkFloatingPointTypes>(dense_string, __LINE__);
228     FailTest<vtkTypedArray, vtkFloatingPointTypes>(sparse_int, __LINE__);
229     SuccessTest<vtkTypedArray, vtkFloatingPointTypes>(sparse_double, __LINE__);
230     FailTest<vtkTypedArray, vtkFloatingPointTypes>(sparse_string, __LINE__);
231 
232     SuccessTest<vtkTypedArray, vtkNumericTypes>(dense_int, __LINE__);
233     SuccessTest<vtkTypedArray, vtkNumericTypes>(dense_double, __LINE__);
234     FailTest<vtkTypedArray, vtkNumericTypes>(dense_string, __LINE__);
235     SuccessTest<vtkTypedArray, vtkNumericTypes>(sparse_int, __LINE__);
236     SuccessTest<vtkTypedArray, vtkNumericTypes>(sparse_double, __LINE__);
237     FailTest<vtkTypedArray, vtkNumericTypes>(sparse_string, __LINE__);
238 
239     FailTest<vtkTypedArray, vtkStringTypes>(dense_int, __LINE__);
240     FailTest<vtkTypedArray, vtkStringTypes>(dense_double, __LINE__);
241     SuccessTest<vtkTypedArray, vtkStringTypes>(dense_string, __LINE__);
242     FailTest<vtkTypedArray, vtkStringTypes>(sparse_int, __LINE__);
243     FailTest<vtkTypedArray, vtkStringTypes>(sparse_double, __LINE__);
244     SuccessTest<vtkTypedArray, vtkStringTypes>(sparse_string, __LINE__);
245 
246     SuccessTest<vtkTypedArray, vtkAllTypes>(dense_int, __LINE__);
247     SuccessTest<vtkTypedArray, vtkAllTypes>(dense_double, __LINE__);
248     SuccessTest<vtkTypedArray, vtkAllTypes>(dense_string, __LINE__);
249     SuccessTest<vtkTypedArray, vtkAllTypes>(sparse_int, __LINE__);
250     SuccessTest<vtkTypedArray, vtkAllTypes>(sparse_double, __LINE__);
251     SuccessTest<vtkTypedArray, vtkAllTypes>(sparse_string, __LINE__);
252 
253     SuccessTest<vtkDenseArray, vtkAllTypes>(dense_int, __LINE__);
254     FailTest<vtkDenseArray, vtkAllTypes>(sparse_int, __LINE__);
255     FailTest<vtkSparseArray, vtkAllTypes>(dense_int, __LINE__);
256     SuccessTest<vtkSparseArray, vtkAllTypes>(sparse_int, __LINE__);
257 
258     return 0;
259     }
260   catch(std::exception& e)
261     {
262     cerr << e.what() << endl;
263     return 1;
264     }
265 }
266