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