VTK-m  2.2
WaveletCompressor.h
Go to the documentation of this file.
1 //============================================================================
2 // Copyright (c) Kitware, Inc.
3 // All rights reserved.
4 // See LICENSE.txt for details.
5 //
6 // This software is distributed WITHOUT ANY WARRANTY; without even
7 // the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
8 // PURPOSE. See the above copyright notice for more information.
9 //============================================================================
10 
11 #ifndef vtk_m_worklet_waveletcompressor_h
12 #define vtk_m_worklet_waveletcompressor_h
13 
14 #include <vtkm/worklet/wavelets/WaveletDWT.h>
15 
16 #include <vtkm/cont/ArrayCopy.h>
18 
19 namespace vtkm
20 {
21 namespace worklet
22 {
23 
24 class WaveletCompressor : public vtkm::worklet::wavelets::WaveletDWT
25 {
26 public:
27  // Constructor
28  WaveletCompressor(wavelets::WaveletName name)
29  : WaveletDWT(name)
30  {
31  }
32 
33  // Multi-level 1D wavelet decomposition
34  template <typename SignalArrayType, typename CoeffArrayType>
35  VTKM_CONT vtkm::Id WaveDecompose(const SignalArrayType& sigIn, // Input
36  vtkm::Id nLevels, // n levels of DWT
37  CoeffArrayType& coeffOut,
38  std::vector<vtkm::Id>& L)
39  {
40  vtkm::Id sigInLen = sigIn.GetNumberOfValues();
41  if (nLevels < 0 || nLevels > WaveletBase::GetWaveletMaxLevel(sigInLen))
42  {
43  throw vtkm::cont::ErrorBadValue("Number of levels of transform is not supported! ");
44  }
45  if (nLevels == 0) // 0 levels means no transform
46  {
47  vtkm::cont::ArrayCopy(sigIn, coeffOut);
48  return 0;
49  }
50 
51  this->ComputeL(sigInLen, nLevels, L); // memory for L is allocated by ComputeL().
52  vtkm::Id CLength = this->ComputeCoeffLength(L, nLevels);
53  VTKM_ASSERT(CLength == sigInLen);
54 
55  vtkm::Id sigInPtr = 0; // pseudo pointer for the beginning of input array
56  vtkm::Id len = sigInLen;
57  vtkm::Id cALen = WaveletBase::GetApproxLength(len);
58  vtkm::Id cptr; // pseudo pointer for the beginning of output array
59  vtkm::Id tlen = 0;
60  std::vector<vtkm::Id> L1d(3, 0);
61 
62  // Use an intermediate array
63  using OutputValueType = typename CoeffArrayType::ValueType;
64  using InterArrayType = vtkm::cont::ArrayHandle<OutputValueType>;
65 
66  // Define a few more types
69 
70  vtkm::cont::ArrayCopy(sigIn, coeffOut);
71 
72  for (vtkm::Id i = nLevels; i > 0; i--)
73  {
74  tlen += L[size_t(i)];
75  cptr = 0 + CLength - tlen - cALen;
76 
77  // make input array (permutation array)
78  IdArrayType inputIndices(sigInPtr, 1, len);
79  PermutArrayType input(inputIndices, coeffOut);
80  // make output array
81  InterArrayType output;
82 
83  WaveletDWT::DWT1D(input, output, L1d);
84 
85  // move intermediate results to final array
86  WaveletBase::DeviceCopyStartX(output, coeffOut, cptr);
87 
88  // update pseudo pointers
89  len = cALen;
90  cALen = WaveletBase::GetApproxLength(cALen);
91  sigInPtr = cptr;
92  }
93 
94  return 0;
95  }
96 
97  // Multi-level 1D wavelet reconstruction
98  template <typename CoeffArrayType, typename SignalArrayType>
99  VTKM_CONT vtkm::Id WaveReconstruct(const CoeffArrayType& coeffIn, // Input
100  vtkm::Id nLevels, // n levels of DWT
101  std::vector<vtkm::Id>& L,
102  SignalArrayType& sigOut)
103  {
104  VTKM_ASSERT(nLevels > 0);
105  vtkm::Id LLength = nLevels + 2;
106  VTKM_ASSERT(vtkm::Id(L.size()) == LLength);
107 
108  std::vector<vtkm::Id> L1d(3, 0); // three elements
109  L1d[0] = L[0];
110  L1d[1] = L[1];
111 
112  using OutValueType = typename SignalArrayType::ValueType;
113  using OutArrayBasic = vtkm::cont::ArrayHandle<OutValueType>;
114  using IdArrayType = vtkm::cont::ArrayHandleCounting<vtkm::Id>;
116 
117  vtkm::cont::ArrayCopy(coeffIn, sigOut);
118 
119  for (vtkm::Id i = 1; i <= nLevels; i++)
120  {
121  L1d[2] = this->GetApproxLengthLevN(L[size_t(LLength - 1)], nLevels - i);
122 
123  // Make an input array
124  IdArrayType inputIndices(0, 1, L1d[2]);
125  PermutArrayType input(inputIndices, sigOut);
126 
127  // Make an output array
128  OutArrayBasic output;
129 
130  WaveletDWT::IDWT1D(input, L1d, output);
131  VTKM_ASSERT(output.GetNumberOfValues() == L1d[2]);
132 
133  // Move output to intermediate array
134  WaveletBase::DeviceCopyStartX(output, sigOut, 0);
135 
136  L1d[0] = L1d[2];
137  L1d[1] = L[size_t(i + 1)];
138  }
139 
140  return 0;
141  }
142 
143  // Multi-level 3D wavelet decomposition
144  template <typename InArrayType, typename OutArrayType>
145  VTKM_CONT vtkm::Float64 WaveDecompose3D(InArrayType& sigIn, // Input
146  vtkm::Id nLevels, // n levels of DWT
147  vtkm::Id inX,
148  vtkm::Id inY,
149  vtkm::Id inZ,
150  OutArrayType& coeffOut,
151  bool discardSigIn) // can we discard sigIn on devices?
152  {
153  vtkm::Id sigInLen = sigIn.GetNumberOfValues();
154  VTKM_ASSERT(inX * inY * inZ == sigInLen);
155  if (nLevels < 0 || nLevels > WaveletBase::GetWaveletMaxLevel(inX) ||
156  nLevels > WaveletBase::GetWaveletMaxLevel(inY) ||
157  nLevels > WaveletBase::GetWaveletMaxLevel(inZ))
158  {
159  throw vtkm::cont::ErrorBadValue("Number of levels of transform is not supported! ");
160  }
161  if (nLevels == 0) // 0 levels means no transform
162  {
163  vtkm::cont::ArrayCopy(sigIn, coeffOut);
164  return 0;
165  }
166 
167  vtkm::Id currentLenX = inX;
168  vtkm::Id currentLenY = inY;
169  vtkm::Id currentLenZ = inZ;
170 
171  using OutValueType = typename OutArrayType::ValueType;
172  using OutBasicArray = vtkm::cont::ArrayHandle<OutValueType>;
173 
174  // First level transform writes to the output array
175  vtkm::Float64 computationTime = WaveletDWT::DWT3D(
176  sigIn, inX, inY, inZ, 0, 0, 0, currentLenX, currentLenY, currentLenZ, coeffOut, discardSigIn);
177 
178  // Successor transforms writes to a temporary array
179  for (vtkm::Id i = nLevels - 1; i > 0; i--)
180  {
181  currentLenX = WaveletBase::GetApproxLength(currentLenX);
182  currentLenY = WaveletBase::GetApproxLength(currentLenY);
183  currentLenZ = WaveletBase::GetApproxLength(currentLenZ);
184 
185  OutBasicArray tempOutput;
186 
187  computationTime += WaveletDWT::DWT3D(
188  coeffOut, inX, inY, inZ, 0, 0, 0, currentLenX, currentLenY, currentLenZ, tempOutput, false);
189 
190  // copy results to coeffOut
191  WaveletBase::DeviceCubeCopyTo(
192  tempOutput, currentLenX, currentLenY, currentLenZ, coeffOut, inX, inY, inZ, 0, 0, 0);
193  }
194 
195  return computationTime;
196  }
197 
198  // Multi-level 3D wavelet reconstruction
199  template <typename InArrayType, typename OutArrayType>
201  InArrayType& arrIn, // Input
202  vtkm::Id nLevels, // n levels of DWT
203  vtkm::Id inX,
204  vtkm::Id inY,
205  vtkm::Id inZ,
206  OutArrayType& arrOut,
207  bool discardArrIn) // can we discard input for more memory?
208  {
209  vtkm::Id arrInLen = arrIn.GetNumberOfValues();
210  VTKM_ASSERT(inX * inY * inZ == arrInLen);
211  if (nLevels < 0 || nLevels > WaveletBase::GetWaveletMaxLevel(inX) ||
212  nLevels > WaveletBase::GetWaveletMaxLevel(inY) ||
213  nLevels > WaveletBase::GetWaveletMaxLevel(inZ))
214  {
215  throw vtkm::cont::ErrorBadValue("Number of levels of transform is not supported! ");
216  }
217  using OutValueType = typename OutArrayType::ValueType;
218  using OutBasicArray = vtkm::cont::ArrayHandle<OutValueType>;
219  vtkm::Float64 computationTime = 0.0;
220 
221  OutBasicArray outBuffer;
222  if (nLevels == 0) // 0 levels means no transform
223  {
224  vtkm::cont::ArrayCopy(arrIn, arrOut);
225  return 0;
226  }
227  else if (discardArrIn)
228  {
229  outBuffer = arrIn;
230  }
231  else
232  {
233  vtkm::cont::ArrayCopy(arrIn, outBuffer);
234  }
235 
236  std::vector<vtkm::Id> L;
237  this->ComputeL3(inX, inY, inZ, nLevels, L);
238  std::vector<vtkm::Id> L3d(27, 0);
239 
240  // All transforms but the last level operate on temporary arrays
241  for (size_t i = 0; i < 24; i++)
242  {
243  L3d[i] = L[i];
244  }
245  for (size_t i = 1; i < static_cast<size_t>(nLevels); i++)
246  {
247  L3d[24] = L3d[0] + L3d[12]; // Total X dim; this is always true for Biorthogonal wavelets
248  L3d[25] = L3d[1] + L3d[7]; // Total Y dim
249  L3d[26] = L3d[2] + L3d[5]; // Total Z dim
250 
251  OutBasicArray tempOutput;
252 
253  // IDWT
254  computationTime +=
255  WaveletDWT::IDWT3D(outBuffer, inX, inY, inZ, 0, 0, 0, L3d, tempOutput, false);
256 
257  // copy back reconstructed block
258  WaveletBase::DeviceCubeCopyTo(
259  tempOutput, L3d[24], L3d[25], L3d[26], outBuffer, inX, inY, inZ, 0, 0, 0);
260 
261  // update L3d array
262  L3d[0] = L3d[24];
263  L3d[1] = L3d[25];
264  L3d[2] = L3d[26];
265  for (size_t j = 3; j < 24; j++)
266  {
267  L3d[j] = L[21 * i + j];
268  }
269  }
270 
271  // The last transform outputs to the final output
272  L3d[24] = L3d[0] + L3d[12];
273  L3d[25] = L3d[1] + L3d[7];
274  L3d[26] = L3d[2] + L3d[5];
275  computationTime += WaveletDWT::IDWT3D(outBuffer, inX, inY, inZ, 0, 0, 0, L3d, arrOut, true);
276 
277  return computationTime;
278  }
279 
280  // Multi-level 2D wavelet decomposition
281  template <typename InArrayType, typename OutArrayType>
282  VTKM_CONT vtkm::Float64 WaveDecompose2D(const InArrayType& sigIn, // Input
283  vtkm::Id nLevels, // n levels of DWT
284  vtkm::Id inX, // Input X dim
285  vtkm::Id inY, // Input Y dim
286  OutArrayType& coeffOut,
287  std::vector<vtkm::Id>& L)
288  {
289  vtkm::Id sigInLen = sigIn.GetNumberOfValues();
290  VTKM_ASSERT(inX * inY == sigInLen);
291  if (nLevels < 0 || nLevels > WaveletBase::GetWaveletMaxLevel(inX) ||
292  nLevels > WaveletBase::GetWaveletMaxLevel(inY))
293  {
294  throw vtkm::cont::ErrorBadValue("Number of levels of transform is not supported! ");
295  }
296  if (nLevels == 0) // 0 levels means no transform
297  {
298  vtkm::cont::ArrayCopy(sigIn, coeffOut);
299  return 0;
300  }
301 
302  this->ComputeL2(inX, inY, nLevels, L);
303  vtkm::Id CLength = this->ComputeCoeffLength2(L, nLevels);
304  VTKM_ASSERT(CLength == sigInLen);
305 
306  vtkm::Id currentLenX = inX;
307  vtkm::Id currentLenY = inY;
308  std::vector<vtkm::Id> L2d(10, 0);
309  vtkm::Float64 computationTime = 0.0;
310 
311  using OutValueType = typename OutArrayType::ValueType;
312  using OutBasicArray = vtkm::cont::ArrayHandle<OutValueType>;
313 
314  // First level transform operates writes to the output array
315  computationTime += WaveletDWT::DWT2D(
316  sigIn, currentLenX, currentLenY, 0, 0, currentLenX, currentLenY, coeffOut, L2d);
317  VTKM_ASSERT(coeffOut.GetNumberOfValues() == currentLenX * currentLenY);
318  currentLenX = WaveletBase::GetApproxLength(currentLenX);
319  currentLenY = WaveletBase::GetApproxLength(currentLenY);
320 
321  // Successor transforms writes to a temporary array
322  for (vtkm::Id i = nLevels - 1; i > 0; i--)
323  {
324  OutBasicArray tempOutput;
325 
326  computationTime +=
327  WaveletDWT::DWT2D(coeffOut, inX, inY, 0, 0, currentLenX, currentLenY, tempOutput, L2d);
328 
329  // copy results to coeffOut
330  WaveletBase::DeviceRectangleCopyTo(
331  tempOutput, currentLenX, currentLenY, coeffOut, inX, inY, 0, 0);
332 
333  // update currentLen
334  currentLenX = WaveletBase::GetApproxLength(currentLenX);
335  currentLenY = WaveletBase::GetApproxLength(currentLenY);
336  }
337 
338  return computationTime;
339  }
340 
341  // Multi-level 2D wavelet reconstruction
342  template <typename InArrayType, typename OutArrayType>
343  VTKM_CONT vtkm::Float64 WaveReconstruct2D(const InArrayType& arrIn, // Input
344  vtkm::Id nLevels, // n levels of DWT
345  vtkm::Id inX, // Input X dim
346  vtkm::Id inY, // Input Y dim
347  OutArrayType& arrOut,
348  std::vector<vtkm::Id>& L)
349  {
350  vtkm::Id arrInLen = arrIn.GetNumberOfValues();
351  VTKM_ASSERT(inX * inY == arrInLen);
352  if (nLevels < 0 || nLevels > WaveletBase::GetWaveletMaxLevel(inX) ||
353  nLevels > WaveletBase::GetWaveletMaxLevel(inY))
354  {
355  throw vtkm::cont::ErrorBadValue("Number of levels of transform is not supported! ");
356  }
357  using OutValueType = typename OutArrayType::ValueType;
358  using OutBasicArray = vtkm::cont::ArrayHandle<OutValueType>;
359  vtkm::Float64 computationTime = 0.0;
360 
361  OutBasicArray outBuffer;
362  if (nLevels == 0) // 0 levels means no transform
363  {
364  vtkm::cont::ArrayCopy(arrIn, arrOut);
365  return 0;
366  }
367  else
368  {
369  vtkm::cont::ArrayCopy(arrIn, outBuffer);
370  }
371 
372  VTKM_ASSERT(vtkm::Id(L.size()) == 6 * nLevels + 4);
373 
374  std::vector<vtkm::Id> L2d(10, 0);
375  L2d[0] = L[0];
376  L2d[1] = L[1];
377  L2d[2] = L[2];
378  L2d[3] = L[3];
379  L2d[4] = L[4];
380  L2d[5] = L[5];
381  L2d[6] = L[6];
382  L2d[7] = L[7];
383 
384  // All transforms but the last operate on temporary arrays
385  for (size_t i = 1; i < static_cast<size_t>(nLevels); i++)
386  {
387  L2d[8] = L2d[0] + L2d[4]; // This is always true for Biorthogonal wavelets
388  L2d[9] = L2d[1] + L2d[3]; // (same above)
389 
390  OutBasicArray tempOutput;
391 
392  // IDWT
393  computationTime += WaveletDWT::IDWT2D(outBuffer, inX, inY, 0, 0, L2d, tempOutput);
394 
395  // copy back reconstructed block
396  WaveletBase::DeviceRectangleCopyTo(tempOutput, L2d[8], L2d[9], outBuffer, inX, inY, 0, 0);
397 
398  // update L2d array
399  L2d[0] = L2d[8];
400  L2d[1] = L2d[9];
401  L2d[2] = L[6 * i + 2];
402  L2d[3] = L[6 * i + 3];
403  L2d[4] = L[6 * i + 4];
404  L2d[5] = L[6 * i + 5];
405  L2d[6] = L[6 * i + 6];
406  L2d[7] = L[6 * i + 7];
407  }
408 
409  // The last transform outputs to the final output
410  L2d[8] = L2d[0] + L2d[4];
411  L2d[9] = L2d[1] + L2d[3];
412  computationTime += WaveletDWT::IDWT2D(outBuffer, inX, inY, 0, 0, L2d, arrOut);
413 
414  return computationTime;
415  }
416 
417  // Squash coefficients smaller than a threshold
418  template <typename CoeffArrayType>
419  vtkm::Id SquashCoefficients(CoeffArrayType& coeffIn, vtkm::Float64 ratio)
420  {
421  if (ratio > 1.0)
422  {
423  vtkm::Id coeffLen = coeffIn.GetNumberOfValues();
424  using ValueType = typename CoeffArrayType::ValueType;
425  using CoeffArrayBasic = vtkm::cont::ArrayHandle<ValueType>;
426  CoeffArrayBasic sortedArray;
427  vtkm::cont::ArrayCopy(coeffIn, sortedArray);
428 
429  WaveletBase::DeviceSort(sortedArray);
430 
431  vtkm::Id n = coeffLen - static_cast<vtkm::Id>(static_cast<vtkm::Float64>(coeffLen) / ratio);
432  vtkm::Float64 nthVal = static_cast<vtkm::Float64>(vtkm::cont::ArrayGetValue(n, sortedArray));
433  if (nthVal < 0.0)
434  {
435  nthVal *= -1.0;
436  }
437 
438  using ThresholdType = vtkm::worklet::wavelets::ThresholdWorklet;
439  ThresholdType thresholdWorklet(nthVal);
440  vtkm::worklet::DispatcherMapField<ThresholdType> dispatcher(thresholdWorklet);
441  dispatcher.Invoke(coeffIn);
442  }
443 
444  return 0;
445  }
446 
447  // Report statistics on reconstructed array
448  template <typename ArrayType>
449  vtkm::Id EvaluateReconstruction(const ArrayType& original, const ArrayType& reconstruct)
450  {
451 #define VAL vtkm::Float64
452 #define MAKEVAL(a) (static_cast<VAL>(a))
453  VAL VarOrig = WaveletBase::DeviceCalculateVariance(original);
454 
455  using ValueType = typename ArrayType::ValueType;
456  using ArrayBasic = vtkm::cont::ArrayHandle<ValueType>;
457  ArrayBasic errorArray, errorSquare;
458 
459  // Use a worklet to calculate point-wise error, and its square
460  using DifferencerWorklet = vtkm::worklet::wavelets::Differencer;
461  DifferencerWorklet dw;
463  dwDispatcher.Invoke(original, reconstruct, errorArray);
464 
465  using SquareWorklet = vtkm::worklet::wavelets::SquareWorklet;
466  SquareWorklet sw;
468  swDispatcher.Invoke(errorArray, errorSquare);
469 
470  VAL varErr = WaveletBase::DeviceCalculateVariance(errorArray);
471  VAL snr, decibels;
472  if (varErr != 0.0)
473  {
474  snr = VarOrig / varErr;
475  decibels = 10 * vtkm::Log10(snr);
476  }
477  else
478  {
479  snr = vtkm::Infinity64();
480  decibels = vtkm::Infinity64();
481  }
482 
483  VAL origMax = WaveletBase::DeviceMax(original);
484  VAL origMin = WaveletBase::DeviceMin(original);
485  VAL errorMax = WaveletBase::DeviceMaxAbs(errorArray);
486  VAL range = origMax - origMin;
487 
488  VAL squareSum = WaveletBase::DeviceSum(errorSquare);
489  VAL rmse = vtkm::Sqrt(MAKEVAL(squareSum) / MAKEVAL(errorArray.GetNumberOfValues()));
490 
491  std::cout << "Data range = " << range << std::endl;
492  std::cout << "SNR = " << snr << std::endl;
493  std::cout << "SNR in decibels = " << decibels << std::endl;
494  std::cout << "L-infy norm = " << errorMax
495  << ", after normalization = " << errorMax / range << std::endl;
496  std::cout << "RMSE = " << rmse << ", after normalization = " << rmse / range
497  << std::endl;
498 #undef MAKEVAL
499 #undef VAL
500 
501  return 0;
502  }
503 
504  // Compute the book keeping array L for 1D DWT
505  void ComputeL(vtkm::Id sigInLen, vtkm::Id nLev, std::vector<vtkm::Id>& L)
506  {
507  size_t nLevels = static_cast<size_t>(nLev); // cast once
508  L.resize(nLevels + 2);
509  L[nLevels + 1] = sigInLen;
510  L[nLevels] = sigInLen;
511  for (size_t i = nLevels; i > 0; i--)
512  {
513  L[i - 1] = WaveletBase::GetApproxLength(L[i]);
514  L[i] = WaveletBase::GetDetailLength(L[i]);
515  }
516  }
517 
518  // Compute the book keeping array L for 2D DWT
519  void ComputeL2(vtkm::Id inX, vtkm::Id inY, vtkm::Id nLev, std::vector<vtkm::Id>& L)
520  {
521  size_t nLevels = static_cast<size_t>(nLev);
522  L.resize(nLevels * 6 + 4);
523  L[nLevels * 6] = inX;
524  L[nLevels * 6 + 1] = inY;
525  L[nLevels * 6 + 2] = inX;
526  L[nLevels * 6 + 3] = inY;
527 
528  for (size_t i = nLevels; i > 0; i--)
529  {
530  // cA
531  L[i * 6 - 6] = WaveletBase::GetApproxLength(L[i * 6 + 0]);
532  L[i * 6 - 5] = WaveletBase::GetApproxLength(L[i * 6 + 1]);
533 
534  // cDh
535  L[i * 6 - 4] = WaveletBase::GetApproxLength(L[i * 6 + 0]);
536  L[i * 6 - 3] = WaveletBase::GetDetailLength(L[i * 6 + 1]);
537 
538  // cDv
539  L[i * 6 - 2] = WaveletBase::GetDetailLength(L[i * 6 + 0]);
540  L[i * 6 - 1] = WaveletBase::GetApproxLength(L[i * 6 + 1]);
541 
542  // cDv - overwrites previous value!
543  L[i * 6 - 0] = WaveletBase::GetDetailLength(L[i * 6 + 0]);
544  L[i * 6 + 1] = WaveletBase::GetDetailLength(L[i * 6 + 1]);
545  }
546  }
547 
548  // Compute the bookkeeping array L for 3D DWT
549  void ComputeL3(vtkm::Id inX, vtkm::Id inY, vtkm::Id inZ, vtkm::Id nLev, std::vector<vtkm::Id>& L)
550  {
551  size_t n = static_cast<size_t>(nLev);
552  L.resize(n * 21 + 6);
553  L[n * 21 + 0] = inX;
554  L[n * 21 + 1] = inY;
555  L[n * 21 + 2] = inZ;
556  L[n * 21 + 3] = inX;
557  L[n * 21 + 4] = inY;
558  L[n * 21 + 5] = inZ;
559 
560  for (size_t i = n; i > 0; i--)
561  {
562  // cLLL
563  L[i * 21 - 21] = WaveletBase::GetApproxLength(L[i * 21 + 0]);
564  L[i * 21 - 20] = WaveletBase::GetApproxLength(L[i * 21 + 1]);
565  L[i * 21 - 19] = WaveletBase::GetApproxLength(L[i * 21 + 2]);
566 
567  // cLLH
568  L[i * 21 - 18] = L[i * 21 - 21];
569  L[i * 21 - 17] = L[i * 21 - 20];
570  L[i * 21 - 16] = WaveletBase::GetDetailLength(L[i * 21 + 2]);
571 
572  // cLHL
573  L[i * 21 - 15] = L[i * 21 - 21];
574  L[i * 21 - 14] = WaveletBase::GetDetailLength(L[i * 21 + 1]);
575  L[i * 21 - 13] = L[i * 21 - 19];
576 
577  // cLHH
578  L[i * 21 - 12] = L[i * 21 - 21];
579  L[i * 21 - 11] = L[i * 21 - 14];
580  L[i * 21 - 10] = L[i * 21 - 16];
581 
582  // cHLL
583  L[i * 21 - 9] = WaveletBase::GetDetailLength(L[i * 21 + 0]);
584  L[i * 21 - 8] = L[i * 21 - 20];
585  L[i * 21 - 7] = L[i * 21 - 19];
586 
587  // cHLH
588  L[i * 21 - 6] = L[i * 21 - 9];
589  L[i * 21 - 5] = L[i * 21 - 20];
590  L[i * 21 - 3] = L[i * 21 - 16];
591 
592  // cHHL
593  L[i * 21 - 3] = L[i * 21 - 9];
594  L[i * 21 - 2] = L[i * 21 - 14];
595  L[i * 21 - 1] = L[i * 21 - 19];
596 
597  // cHHH - overwrites previous value
598  L[i * 21 + 0] = L[i * 21 - 9];
599  L[i * 21 + 1] = L[i * 21 - 14];
600  L[i * 21 + 2] = L[i * 21 - 16];
601  }
602  }
603 
604  // Compute the length of coefficients for 1D transforms
605  vtkm::Id ComputeCoeffLength(std::vector<vtkm::Id>& L, vtkm::Id nLevels)
606  {
607  vtkm::Id sum = L[0]; // 1st level cA
608  for (size_t i = 1; i <= size_t(nLevels); i++)
609  {
610  sum += L[i];
611  }
612  return sum;
613  }
614  // Compute the length of coefficients for 2D transforms
615  vtkm::Id ComputeCoeffLength2(std::vector<vtkm::Id>& L, vtkm::Id nLevels)
616  {
617  vtkm::Id sum = (L[0] * L[1]); // 1st level cA
618  for (size_t i = 1; i <= size_t(nLevels); i++)
619  {
620  sum += L[i * 6 - 4] * L[i * 6 - 3]; // cDh
621  sum += L[i * 6 - 2] * L[i * 6 - 1]; // cDv
622  sum += L[i * 6 - 0] * L[i * 6 + 1]; // cDd
623  }
624  return sum;
625  }
626 
627  // Compute approximate coefficient length at a specific level
629  {
630  vtkm::Id cALen = sigInLen;
631  for (vtkm::Id i = 0; i < levN; i++)
632  {
633  cALen = WaveletBase::GetApproxLength(cALen);
634  if (cALen == 0)
635  {
636  return cALen;
637  }
638  }
639 
640  return cALen;
641  }
642 
643 }; // class WaveletCompressor
644 
645 } // namespace worklet
646 } // namespace vtkm
647 
648 #endif
vtkm::cont::ArrayHandle
Manages an array-worth of data.
Definition: ArrayHandle.h:300
vtkm::worklet::WaveletCompressor::WaveReconstruct
vtkm::Id WaveReconstruct(const CoeffArrayType &coeffIn, vtkm::Id nLevels, std::vector< vtkm::Id > &L, SignalArrayType &sigOut)
Definition: WaveletCompressor.h:99
vtkm
Groups connected points that have the same field value.
Definition: Atomic.h:19
vtkm::Sqrt
vtkm::Float32 Sqrt(vtkm::Float32 x)
Definition: Math.h:943
vtkm::worklet::WaveletCompressor::ComputeL2
void ComputeL2(vtkm::Id inX, vtkm::Id inY, vtkm::Id nLev, std::vector< vtkm::Id > &L)
Definition: WaveletCompressor.h:519
VTKM_ASSERT
#define VTKM_ASSERT(condition)
Definition: Assert.h:43
vtkm::worklet::WaveletCompressor::GetApproxLengthLevN
vtkm::Id GetApproxLengthLevN(vtkm::Id sigInLen, vtkm::Id levN)
Definition: WaveletCompressor.h:628
vtkm::Log10
vtkm::Float32 Log10(vtkm::Float32 x)
Definition: Math.h:1578
vtkm::worklet::WaveletCompressor::ComputeL3
void ComputeL3(vtkm::Id inX, vtkm::Id inY, vtkm::Id inZ, vtkm::Id nLev, std::vector< vtkm::Id > &L)
Definition: WaveletCompressor.h:549
vtkm::worklet::WaveletCompressor::ComputeCoeffLength2
vtkm::Id ComputeCoeffLength2(std::vector< vtkm::Id > &L, vtkm::Id nLevels)
Definition: WaveletCompressor.h:615
vtkm::worklet::WaveletCompressor
Definition: WaveletCompressor.h:24
vtkm::worklet::WaveletCompressor::ComputeCoeffLength
vtkm::Id ComputeCoeffLength(std::vector< vtkm::Id > &L, vtkm::Id nLevels)
Definition: WaveletCompressor.h:605
ArrayCopy.h
vtkm::worklet::WaveletCompressor::ComputeL
void ComputeL(vtkm::Id sigInLen, vtkm::Id nLev, std::vector< vtkm::Id > &L)
Definition: WaveletCompressor.h:505
vtkm::worklet::WaveletCompressor::WaveReconstruct2D
vtkm::Float64 WaveReconstruct2D(const InArrayType &arrIn, vtkm::Id nLevels, vtkm::Id inX, vtkm::Id inY, OutArrayType &arrOut, std::vector< vtkm::Id > &L)
Definition: WaveletCompressor.h:343
vtkm::worklet::WaveletCompressor::SquashCoefficients
vtkm::Id SquashCoefficients(CoeffArrayType &coeffIn, vtkm::Float64 ratio)
Definition: WaveletCompressor.h:419
vtkm::worklet::DispatcherMapField
Dispatcher for worklets that inherit from WorkletMapField.
Definition: DispatcherMapField.h:25
vtkm::worklet::WaveletCompressor::EvaluateReconstruction
vtkm::Id EvaluateReconstruction(const ArrayType &original, const ArrayType &reconstruct)
Definition: WaveletCompressor.h:449
vtkm::cont::ArrayHandlePermutation
Implicitly permutes the values in an array.
Definition: ArrayHandlePermutation.h:233
vtkm::cont::ArrayHandleCounting
ArrayHandleCounting is a specialization of ArrayHandle.
Definition: ArrayHandleCounting.h:130
vtkm::cont::ArrayCopy
void ArrayCopy(const SourceArrayType &source, DestArrayType &destination)
Does a deep copy from one array to another array.
Definition: ArrayCopy.h:120
vtkm::worklet::WaveletCompressor::WaveletCompressor
WaveletCompressor(wavelets::WaveletName name)
Definition: WaveletCompressor.h:28
VTKM_CONT
#define VTKM_CONT
Definition: ExportMacros.h:57
vtkm::Id
vtkm::Int64 Id
Base type to use to index arrays.
Definition: Types.h:227
ArrayGetValues.h
vtkm::worklet::WaveletCompressor::WaveDecompose3D
vtkm::Float64 WaveDecompose3D(InArrayType &sigIn, vtkm::Id nLevels, vtkm::Id inX, vtkm::Id inY, vtkm::Id inZ, OutArrayType &coeffOut, bool discardSigIn)
Definition: WaveletCompressor.h:145
vtkm::cont::ErrorBadValue
This class is thrown when a VTKm function or method encounters an invalid value that inhibits progres...
Definition: ErrorBadValue.h:25
MAKEVAL
#define MAKEVAL(a)
vtkm::worklet::WaveletCompressor::WaveReconstruct3D
vtkm::Float64 WaveReconstruct3D(InArrayType &arrIn, vtkm::Id nLevels, vtkm::Id inX, vtkm::Id inY, vtkm::Id inZ, OutArrayType &arrOut, bool discardArrIn)
Definition: WaveletCompressor.h:200
vtkm::worklet::WaveletCompressor::WaveDecompose2D
vtkm::Float64 WaveDecompose2D(const InArrayType &sigIn, vtkm::Id nLevels, vtkm::Id inX, vtkm::Id inY, OutArrayType &coeffOut, std::vector< vtkm::Id > &L)
Definition: WaveletCompressor.h:282
vtkm::Float64
double Float64
Base type to use for 64-bit floating-point numbers.
Definition: Types.h:161
VAL
#define VAL
vtkm::worklet::WaveletCompressor::WaveDecompose
vtkm::Id WaveDecompose(const SignalArrayType &sigIn, vtkm::Id nLevels, CoeffArrayType &coeffOut, std::vector< vtkm::Id > &L)
Definition: WaveletCompressor.h:35
vtkm::cont::ArrayGetValue
T ArrayGetValue(vtkm::Id id, const vtkm::cont::ArrayHandle< T, S > &data)
Obtain a small set of values from an ArrayHandle with minimal device transfers.
Definition: ArrayGetValues.h:261