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