vtk-m/vtkm/worklet/wavelets/WaveletDWT.h

2708 lines
93 KiB
C
Raw Normal View History

//============================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//
// Copyright 2014 National Technology & Engineering Solutions of Sandia, LLC (NTESS).
// Copyright 2014 UT-Battelle, LLC.
// Copyright 2014 Los Alamos National Security.
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Under the terms of Contract DE-AC52-06NA25396 with Los Alamos National
// Laboratory (LANL), the U.S. Government retains certain rights in
// this software.
//============================================================================
#ifndef vtk_m_worklet_wavelets_waveletdwt_h
#define vtk_m_worklet_wavelets_waveletdwt_h
#include <vtkm/worklet/wavelets/WaveletBase.h>
#include <vtkm/worklet/wavelets/WaveletTransforms.h>
#include <vtkm/cont/ArrayHandleConcatenate.h>
#include <vtkm/cont/ArrayHandleCounting.h>
#include <vtkm/cont/ArrayHandlePermutation.h>
#include <vtkm/Math.h>
2016-08-12 23:38:04 +00:00
#include <vtkm/cont/Timer.h>
2017-05-18 14:29:41 +00:00
namespace vtkm
{
namespace worklet
{
namespace wavelets
{
class WaveletDWT : public WaveletBase
{
public:
// Constructor
2017-05-18 14:29:41 +00:00
WaveletDWT(WaveletName name)
: WaveletBase(name)
{
}
// Function: extend a cube in X direction
template <typename SigInArrayType, typename ExtensionArrayType>
2017-05-18 14:29:41 +00:00
vtkm::Id Extend3DLeftRight(const SigInArrayType& sigIn, // input
vtkm::Id sigDimX,
vtkm::Id sigDimY,
vtkm::Id sigDimZ,
vtkm::Id sigStartX,
vtkm::Id sigStartY,
vtkm::Id sigStartZ,
vtkm::Id sigPretendDimX,
vtkm::Id sigPretendDimY,
2017-05-18 14:29:41 +00:00
vtkm::Id sigPretendDimZ,
ExtensionArrayType& ext1, // output
ExtensionArrayType& ext2, // output
vtkm::Id addLen,
vtkm::worklet::wavelets::DWTMode ext1Method,
vtkm::worklet::wavelets::DWTMode ext2Method,
bool pretendSigPaddedZero,
bool padZeroAtExt2)
2017-02-16 00:14:33 +00:00
{
// pretendSigPaddedZero and padZeroAtExt2 cannot happen at the same time
2017-05-18 14:29:41 +00:00
VTKM_ASSERT(!pretendSigPaddedZero || !padZeroAtExt2);
2017-02-16 00:14:33 +00:00
2017-05-18 14:29:41 +00:00
if (addLen == 0) // Haar kernel
{
ext1.Allocate(0); // No extension on the left side
2017-05-18 14:29:41 +00:00
if (pretendSigPaddedZero || padZeroAtExt2) // plane of size 1*dimY*dimZ
{
ext2.Allocate(sigPretendDimY * sigPretendDimZ);
WaveletBase::DeviceAssignZero3DPlaneX(ext2, 1, sigPretendDimY, sigPretendDimZ, 0);
}
else
2017-05-18 17:51:35 +00:00
{
ext2.Allocate(0); // No extension on the right side
2017-05-18 17:51:35 +00:00
}
return 0;
}
2018-02-22 13:29:13 +00:00
using ValueType = typename SigInArrayType::ValueType;
using ExtendArrayType = vtkm::cont::ArrayHandle<ValueType>;
using ExtensionWorklet = vtkm::worklet::wavelets::ExtensionWorklet3D;
using DispatcherType = typename vtkm::worklet::DispatcherMapField<ExtensionWorklet>;
2017-05-18 14:29:41 +00:00
vtkm::Id extDimX, extDimY, extDimZ;
vtkm::worklet::wavelets::ExtensionDirection dir;
2017-05-18 14:29:41 +00:00
{ // First work on left extension
dir = LEFT;
extDimX = addLen;
extDimY = sigPretendDimY;
extDimZ = sigPretendDimZ;
2017-05-22 20:47:13 +00:00
ext1.Allocate(extDimX * extDimY * extDimZ);
ExtensionWorklet worklet(extDimX,
extDimY,
extDimZ,
sigDimX,
sigDimY,
sigDimZ,
sigStartX,
sigStartY,
sigStartZ,
sigPretendDimX,
sigPretendDimY,
sigPretendDimZ,
ext1Method,
dir,
2017-05-18 14:29:41 +00:00
false); // not treating input signal as having zeros
DispatcherType dispatcher(worklet);
dispatcher.Invoke(ext1, sigIn);
}
// Then work on right extension
2017-05-18 14:29:41 +00:00
dir = RIGHT;
extDimY = sigPretendDimY;
extDimZ = sigPretendDimZ;
2017-05-18 14:29:41 +00:00
if (!pretendSigPaddedZero && !padZeroAtExt2)
{
extDimX = addLen;
ext2.Allocate(extDimX * extDimY * extDimZ);
ExtensionWorklet worklet(extDimX,
extDimY,
extDimZ,
sigDimX,
sigDimY,
sigDimZ,
sigStartX,
sigStartY,
sigStartZ,
sigPretendDimX,
sigPretendDimY,
sigPretendDimZ,
ext2Method,
dir,
false);
2017-05-18 14:29:41 +00:00
DispatcherType dispatcher(worklet);
dispatcher.Invoke(ext2, sigIn);
}
else if (!pretendSigPaddedZero && padZeroAtExt2)
{ // This case is not exactly padding a zero at the end of Ext2.
// Rather, it is to increase extension length by one and fill it
// to be whatever mirrored.
2017-05-18 14:29:41 +00:00
extDimX = addLen + 1;
ext2.Allocate(extDimX * extDimY * extDimZ);
ExtensionWorklet worklet(extDimX,
extDimY,
extDimZ,
sigDimX,
sigDimY,
sigDimZ,
sigStartX,
sigStartY,
sigStartZ,
sigPretendDimX,
sigPretendDimY,
sigPretendDimZ,
ext2Method,
dir,
false);
2017-05-18 14:29:41 +00:00
DispatcherType dispatcher(worklet);
dispatcher.Invoke(ext2, sigIn);
}
else // pretendSigPaddedZero
{
ExtendArrayType ext2Temp;
extDimX = addLen;
ext2Temp.Allocate(extDimX * extDimY * extDimZ);
ExtensionWorklet worklet(extDimX,
extDimY,
extDimZ,
sigDimX,
sigDimY,
sigDimZ,
sigStartX,
sigStartY,
sigStartZ,
sigPretendDimX,
sigPretendDimY,
sigPretendDimZ,
ext2Method,
dir,
2017-05-18 14:29:41 +00:00
true); // pretend sig is padded a zero
DispatcherType dispatcher(worklet);
dispatcher.Invoke(ext2Temp, sigIn);
2017-05-22 20:47:13 +00:00
// Give ext2 one layer thicker to hold the pretend zeros from signal.
ext2.Allocate((extDimX + 1) * extDimY * extDimZ);
WaveletBase::DeviceCubeCopyTo(
ext2Temp, extDimX, extDimY, extDimZ, ext2, extDimX + 1, extDimY, extDimZ, 1, 0, 0);
WaveletBase::DeviceAssignZero3DPlaneX(ext2, extDimX + 1, extDimY, extDimZ, 0);
}
return 0;
}
// Function: extend a cube in Y direction
template <typename SigInArrayType, typename ExtensionArrayType>
2017-05-18 14:29:41 +00:00
vtkm::Id Extend3DTopDown(const SigInArrayType& sigIn, // input
vtkm::Id sigDimX,
vtkm::Id sigDimY,
vtkm::Id sigDimZ,
vtkm::Id sigStartX,
vtkm::Id sigStartY,
vtkm::Id sigStartZ,
vtkm::Id sigPretendDimX,
vtkm::Id sigPretendDimY,
vtkm::Id sigPretendDimZ,
2017-05-18 14:29:41 +00:00
ExtensionArrayType& ext1, // output
ExtensionArrayType& ext2, // output
vtkm::Id addLen,
vtkm::worklet::wavelets::DWTMode ext1Method,
vtkm::worklet::wavelets::DWTMode ext2Method,
bool pretendSigPaddedZero,
bool padZeroAtExt2)
{
// pretendSigPaddedZero and padZeroAtExt2 cannot happen at the same time
2017-05-18 14:29:41 +00:00
VTKM_ASSERT(!pretendSigPaddedZero || !padZeroAtExt2);
2017-05-18 14:29:41 +00:00
if (addLen == 0) // Haar kernel
{
ext1.Allocate(0); // No extension on the top side
2017-05-18 14:29:41 +00:00
if (pretendSigPaddedZero || padZeroAtExt2) // plane of size dimX*dimZ
{
ext2.Allocate(sigPretendDimX * 1 * sigPretendDimZ);
WaveletBase::DeviceAssignZero3DPlaneY(ext2, sigPretendDimX, 1, sigPretendDimZ, 0);
}
else
2017-05-18 17:51:35 +00:00
{
ext2.Allocate(0); // No extension on the right side
2017-05-18 17:51:35 +00:00
}
return 0;
}
2018-02-22 13:29:13 +00:00
using ValueType = typename SigInArrayType::ValueType;
using ExtendArrayType = vtkm::cont::ArrayHandle<ValueType>;
using ExtensionWorklet = vtkm::worklet::wavelets::ExtensionWorklet3D;
using DispatcherType = typename vtkm::worklet::DispatcherMapField<ExtensionWorklet>;
2017-05-18 14:29:41 +00:00
vtkm::Id extDimX, extDimY, extDimZ;
vtkm::worklet::wavelets::ExtensionDirection dir;
2017-05-18 14:29:41 +00:00
{ // First work on top extension
dir = TOP;
extDimX = sigPretendDimX;
extDimY = addLen;
extDimZ = sigPretendDimZ;
2017-05-22 20:47:13 +00:00
ext1.Allocate(extDimX * extDimY * extDimZ);
ExtensionWorklet worklet(extDimX,
extDimY,
extDimZ,
sigDimX,
sigDimY,
sigDimZ,
sigStartX,
sigStartY,
sigStartZ,
sigPretendDimX,
sigPretendDimY,
sigPretendDimZ,
ext1Method,
dir,
2017-05-18 14:29:41 +00:00
false); // not treating input signal as having zeros
DispatcherType dispatcher(worklet);
dispatcher.Invoke(ext1, sigIn);
}
// Then work on bottom extension
2017-05-18 14:29:41 +00:00
dir = BOTTOM;
extDimX = sigPretendDimX;
extDimZ = sigPretendDimZ;
2017-05-18 14:29:41 +00:00
if (!pretendSigPaddedZero && !padZeroAtExt2)
{
extDimY = addLen;
ext2.Allocate(extDimX * extDimY * extDimZ);
ExtensionWorklet worklet(extDimX,
extDimY,
extDimZ,
sigDimX,
sigDimY,
sigDimZ,
sigStartX,
sigStartY,
sigStartZ,
sigPretendDimX,
sigPretendDimY,
sigPretendDimZ,
ext2Method,
dir,
false);
2017-05-18 14:29:41 +00:00
DispatcherType dispatcher(worklet);
dispatcher.Invoke(ext2, sigIn);
}
else if (!pretendSigPaddedZero && padZeroAtExt2)
{ // This case is not exactly padding a zero at the end of Ext2.
// Rather, it is to increase extension length by one and fill it
// to be whatever mirrored.
extDimY = addLen + 1;
ext2.Allocate(extDimX * extDimY * extDimZ);
ExtensionWorklet worklet(extDimX,
extDimY,
extDimZ,
sigDimX,
sigDimY,
sigDimZ,
sigStartX,
sigStartY,
sigStartZ,
sigPretendDimX,
sigPretendDimY,
sigPretendDimZ,
ext2Method,
dir,
false);
2017-05-18 14:29:41 +00:00
DispatcherType dispatcher(worklet);
dispatcher.Invoke(ext2, sigIn);
}
else // pretendSigPaddedZero
{
ExtendArrayType ext2Temp;
extDimY = addLen;
ext2Temp.Allocate(extDimX * extDimY * extDimZ);
ExtensionWorklet worklet(extDimX,
extDimY,
extDimZ,
sigDimX,
sigDimY,
sigDimZ,
sigStartX,
sigStartY,
sigStartZ,
sigPretendDimX,
sigPretendDimY,
sigPretendDimZ,
ext2Method,
dir,
2017-05-18 14:29:41 +00:00
true); // pretend sig is padded a zero
DispatcherType dispatcher(worklet);
dispatcher.Invoke(ext2Temp, sigIn);
2017-05-22 20:47:13 +00:00
// Give ext2 one layer thicker to hold the pretend zeros from signal.
ext2.Allocate(extDimX * (extDimY + 1) * extDimZ);
WaveletBase::DeviceCubeCopyTo(
ext2Temp, extDimX, extDimY, extDimZ, ext2, extDimX, extDimY + 1, extDimZ, 0, 1, 0);
WaveletBase::DeviceAssignZero3DPlaneY(ext2, extDimX, extDimY + 1, extDimZ, 0);
}
return 0;
}
// Function: extend a cube in Z direction
template <typename SigInArrayType, typename ExtensionArrayType>
2017-05-18 14:29:41 +00:00
vtkm::Id Extend3DFrontBack(const SigInArrayType& sigIn, // input
vtkm::Id sigDimX,
vtkm::Id sigDimY,
vtkm::Id sigDimZ,
vtkm::Id sigStartX,
vtkm::Id sigStartY,
vtkm::Id sigStartZ,
vtkm::Id sigPretendDimX,
vtkm::Id sigPretendDimY,
2017-05-18 14:29:41 +00:00
vtkm::Id sigPretendDimZ,
ExtensionArrayType& ext1, // output
ExtensionArrayType& ext2, // output
vtkm::Id addLen,
vtkm::worklet::wavelets::DWTMode ext1Method,
vtkm::worklet::wavelets::DWTMode ext2Method,
bool pretendSigPaddedZero,
bool padZeroAtExt2)
{
// pretendSigPaddedZero and padZeroAtExt2 cannot happen at the same time
2017-05-18 14:29:41 +00:00
VTKM_ASSERT(!pretendSigPaddedZero || !padZeroAtExt2);
2017-05-18 14:29:41 +00:00
if (addLen == 0) // Haar kernel
{
ext1.Allocate(0); // No extension on the front side
2017-05-18 14:29:41 +00:00
if (pretendSigPaddedZero || padZeroAtExt2) // plane of size dimX * dimY
{
ext2.Allocate(sigPretendDimX * sigPretendDimY * 1);
WaveletBase::DeviceAssignZero3DPlaneZ(ext2, sigPretendDimX, sigPretendDimY, 1, 0);
}
else
2017-05-18 17:51:35 +00:00
{
ext2.Allocate(0); // No extension on the right side
2017-05-18 17:51:35 +00:00
}
return 0;
}
2018-02-22 13:29:13 +00:00
using ValueType = typename SigInArrayType::ValueType;
using ExtendArrayType = vtkm::cont::ArrayHandle<ValueType>;
using ExtensionWorklet = vtkm::worklet::wavelets::ExtensionWorklet3D;
using DispatcherType = typename vtkm::worklet::DispatcherMapField<ExtensionWorklet>;
2017-05-18 14:29:41 +00:00
vtkm::Id extDimX, extDimY, extDimZ;
vtkm::worklet::wavelets::ExtensionDirection dir;
2017-05-18 14:29:41 +00:00
{ // First work on front extension
dir = FRONT;
extDimX = sigPretendDimX;
extDimY = sigPretendDimY;
extDimZ = addLen;
2017-05-22 20:47:13 +00:00
ext1.Allocate(extDimX * extDimY * extDimZ);
ExtensionWorklet worklet(extDimX,
extDimY,
extDimZ,
sigDimX,
sigDimY,
sigDimZ,
sigStartX,
sigStartY,
sigStartZ,
sigPretendDimX,
sigPretendDimY,
sigPretendDimZ,
ext1Method,
dir,
2017-05-18 14:29:41 +00:00
false); // not treating input signal as having zeros
DispatcherType dispatcher(worklet);
dispatcher.Invoke(ext1, sigIn);
}
// Then work on back extension
2017-05-18 14:29:41 +00:00
dir = BACK;
extDimX = sigPretendDimX;
extDimY = sigPretendDimY;
2017-05-18 14:29:41 +00:00
if (!pretendSigPaddedZero && !padZeroAtExt2)
{
extDimZ = addLen;
ext2.Allocate(extDimX * extDimY * extDimZ);
ExtensionWorklet worklet(extDimX,
extDimY,
extDimZ,
sigDimX,
sigDimY,
sigDimZ,
sigStartX,
sigStartY,
sigStartZ,
sigPretendDimX,
sigPretendDimY,
sigPretendDimZ,
ext2Method,
dir,
false);
2017-05-18 14:29:41 +00:00
DispatcherType dispatcher(worklet);
dispatcher.Invoke(ext2, sigIn);
}
else if (!pretendSigPaddedZero && padZeroAtExt2)
{ // This case is not exactly padding a zero at the end of Ext2.
// Rather, it is to increase extension length by one and fill it
// to be whatever mirrored.
extDimZ = addLen + 1;
ext2.Allocate(extDimX * extDimY * extDimZ);
ExtensionWorklet worklet(extDimX,
extDimY,
extDimZ,
sigDimX,
sigDimY,
sigDimZ,
sigStartX,
sigStartY,
sigStartZ,
sigPretendDimX,
sigPretendDimY,
sigPretendDimZ,
ext2Method,
dir,
false);
2017-05-18 14:29:41 +00:00
DispatcherType dispatcher(worklet);
dispatcher.Invoke(ext2, sigIn);
}
else // pretendSigPaddedZero
{
ExtendArrayType ext2Temp;
extDimZ = addLen;
ext2Temp.Allocate(extDimX * extDimY * extDimZ);
ExtensionWorklet worklet(extDimX,
extDimY,
extDimZ,
sigDimX,
sigDimY,
sigDimZ,
sigStartX,
sigStartY,
sigStartZ,
sigPretendDimX,
sigPretendDimY,
sigPretendDimZ,
ext2Method,
dir,
2017-05-18 14:29:41 +00:00
true); // pretend sig is padded a zero
DispatcherType dispatcher(worklet);
dispatcher.Invoke(ext2Temp, sigIn);
2017-05-22 20:47:13 +00:00
// Give ext2 one layer thicker to hold the pretend zeros from signal.
ext2.Allocate(extDimX * extDimY * (extDimZ + 1));
WaveletBase::DeviceCubeCopyTo(
ext2Temp, extDimX, extDimY, extDimZ, ext2, extDimX, extDimY, extDimZ + 1, 0, 0, 1);
WaveletBase::DeviceAssignZero3DPlaneZ(ext2, extDimX, extDimY, extDimZ + 1, 0);
}
return 0;
}
2017-05-22 20:47:13 +00:00
// L[3] L[15]
// -----------------------
// / / /|
// L[5] / / / |
// / LLH / HLH / |
// / / / | L[16]
// ----------------------- |
// / / /| |
// L[2] / / / | /|
// / / / | / |
// /___L[0]___/___L[12]__/ | / | L[22]
// | | | |/ |
// L[1] | | | /HHH /
// | LLL | HLL | /| /
// | | | / | / L[23]
// |---------------------|/ | /
// | | | |/
// | | | /
// L[7] | LHL | HHL | /
// | | | / L[20]
// |__________|__________|/
// L[6] L[18]
2017-02-17 22:27:30 +00:00
//
// Performs one level of 3D discrete wavelet transform on a small cube of input array
// The output has the same size as the small cube
template <typename ArrayInType, typename ArrayOutType>
vtkm::Float64 DWT3D(ArrayInType& sigIn,
vtkm::Id sigDimX,
vtkm::Id sigDimY,
vtkm::Id sigDimZ,
vtkm::Id sigStartX,
vtkm::Id sigStartY,
vtkm::Id sigStartZ,
vtkm::Id sigPretendDimX,
vtkm::Id sigPretendDimY,
vtkm::Id sigPretendDimZ,
2017-05-18 14:29:41 +00:00
ArrayOutType& coeffOut,
bool discardSigIn) // discard sigIn on devices
2017-02-17 22:27:30 +00:00
{
std::vector<vtkm::Id> L(27, 0);
2017-02-17 22:27:30 +00:00
// LLL
2017-05-18 14:29:41 +00:00
L[0] = WaveletBase::GetApproxLength(sigPretendDimX);
L[1] = WaveletBase::GetApproxLength(sigPretendDimY);
L[2] = WaveletBase::GetApproxLength(sigPretendDimZ);
2017-02-17 22:27:30 +00:00
// LLH
2017-05-18 14:29:41 +00:00
L[3] = L[0];
L[4] = L[1];
L[5] = WaveletBase::GetDetailLength(sigPretendDimZ);
2017-02-17 22:27:30 +00:00
// LHL
2017-05-18 14:29:41 +00:00
L[6] = L[0];
L[7] = WaveletBase::GetDetailLength(sigPretendDimY);
L[8] = L[2];
2017-02-17 22:27:30 +00:00
// LHH
2017-05-18 14:29:41 +00:00
L[9] = L[0];
2017-02-17 22:27:30 +00:00
L[10] = L[7];
L[11] = L[5];
// HLL
2017-05-18 14:29:41 +00:00
L[12] = WaveletBase::GetDetailLength(sigPretendDimX);
2017-02-17 22:27:30 +00:00
L[13] = L[1];
L[14] = L[2];
// HLH
L[15] = L[12];
L[16] = L[1];
L[17] = L[5];
// HHL
L[18] = L[12];
L[19] = L[7];
L[20] = L[2];
// HHH
L[21] = L[12];
L[22] = L[7];
L[23] = L[5];
L[24] = sigPretendDimX;
L[25] = sigPretendDimY;
L[26] = sigPretendDimZ;
vtkm::Id filterLen = WaveletBase::filter.GetFilterLength();
2017-05-18 14:29:41 +00:00
bool oddLow = true;
if (filterLen % 2 != 0)
2017-05-18 17:51:35 +00:00
{
2017-02-17 22:27:30 +00:00
oddLow = false;
2017-05-18 17:51:35 +00:00
}
2017-05-18 14:29:41 +00:00
vtkm::Id addLen = filterLen / 2;
2017-02-17 22:27:30 +00:00
2018-02-22 13:29:13 +00:00
using ValueType = typename ArrayInType::ValueType;
using ArrayType = vtkm::cont::ArrayHandle<ValueType>;
using LeftRightXFormType = vtkm::worklet::wavelets::ForwardTransform3DLeftRight;
using TopDownXFormType = vtkm::worklet::wavelets::ForwardTransform3DTopDown;
using FrontBackXFormType = vtkm::worklet::wavelets::ForwardTransform3DFrontBack;
using LeftRightDispatcherType = vtkm::worklet::DispatcherMapField<LeftRightXFormType>;
using TopDownDispatcherType = vtkm::worklet::DispatcherMapField<TopDownXFormType>;
using FrontBackDispatcherType = vtkm::worklet::DispatcherMapField<FrontBackXFormType>;
vtkm::cont::Timer timer;
2017-02-17 22:27:30 +00:00
vtkm::Float64 computationTime = 0.0;
// First transform in X direction
2017-05-18 14:29:41 +00:00
ArrayType afterX;
afterX.Allocate(sigPretendDimX * sigPretendDimY * sigPretendDimZ);
2017-05-18 14:29:41 +00:00
{
ArrayType leftExt, rightExt;
this->Extend3DLeftRight(sigIn,
sigDimX,
sigDimY,
sigDimZ,
sigStartX,
sigStartY,
sigStartZ,
sigPretendDimX,
sigPretendDimY,
sigPretendDimZ,
leftExt,
rightExt,
addLen,
WaveletBase::wmode,
WaveletBase::wmode,
false,
false);
LeftRightXFormType worklet(filterLen,
L[0],
oddLow,
addLen,
sigPretendDimY,
sigPretendDimZ,
sigDimX,
sigDimY,
sigDimZ,
sigStartX,
sigStartY,
sigStartZ,
sigPretendDimX,
sigPretendDimY,
sigPretendDimZ,
addLen,
sigPretendDimY,
sigPretendDimZ);
2017-02-17 22:27:30 +00:00
LeftRightDispatcherType dispatcher(worklet);
timer.Start();
dispatcher.Invoke(leftExt,
sigIn,
rightExt,
WaveletBase::filter.GetLowDecomposeFilter(),
WaveletBase::filter.GetHighDecomposeFilter(),
afterX);
2017-02-17 22:27:30 +00:00
computationTime += timer.GetElapsedTime();
}
2017-05-18 14:29:41 +00:00
if (discardSigIn)
2017-05-18 17:51:35 +00:00
{
2017-05-22 20:47:13 +00:00
sigIn.ReleaseResourcesExecution();
2017-05-18 17:51:35 +00:00
}
2017-03-09 03:29:27 +00:00
2017-02-17 22:27:30 +00:00
// Then do transform in Y direction
2017-05-18 14:29:41 +00:00
ArrayType afterY;
afterY.Allocate(sigPretendDimX * sigPretendDimY * sigPretendDimZ);
2017-05-18 14:29:41 +00:00
{
ArrayType topExt, bottomExt;
this->Extend3DTopDown(afterX,
sigPretendDimX,
sigPretendDimY,
sigPretendDimZ,
0,
0,
0,
sigPretendDimX,
sigPretendDimY,
sigPretendDimZ,
topExt,
bottomExt,
addLen,
WaveletBase::wmode,
WaveletBase::wmode,
false,
false);
TopDownXFormType worklet(filterLen,
L[1],
oddLow,
sigPretendDimX,
addLen,
sigPretendDimZ,
sigPretendDimX,
sigPretendDimY,
sigPretendDimZ,
0,
0,
0,
sigPretendDimX,
sigPretendDimY,
sigPretendDimZ,
sigPretendDimX,
addLen,
sigPretendDimZ);
2017-05-18 14:29:41 +00:00
TopDownDispatcherType dispatcher(worklet);
timer.Start();
dispatcher.Invoke(topExt,
afterX,
bottomExt,
WaveletBase::filter.GetLowDecomposeFilter(),
WaveletBase::filter.GetHighDecomposeFilter(),
afterY);
2017-02-17 22:27:30 +00:00
computationTime += timer.GetElapsedTime();
}
// Then do transform in Z direction
2017-05-18 14:29:41 +00:00
afterX.ReleaseResources(); // release afterX
{
ArrayType frontExt, backExt;
coeffOut.Allocate(sigPretendDimX * sigPretendDimY * sigPretendDimZ);
this->Extend3DFrontBack(afterY,
sigPretendDimX,
sigPretendDimY,
sigPretendDimZ,
0,
0,
0,
sigPretendDimX,
sigPretendDimY,
sigPretendDimZ,
frontExt,
backExt,
addLen,
WaveletBase::wmode,
WaveletBase::wmode,
false,
false);
FrontBackXFormType worklet(filterLen,
L[1],
oddLow,
sigPretendDimX,
sigPretendDimY,
addLen,
sigPretendDimX,
sigPretendDimY,
sigPretendDimZ,
0,
0,
0,
sigPretendDimX,
sigPretendDimY,
sigPretendDimZ,
sigPretendDimX,
sigPretendDimY,
addLen);
2017-05-18 14:29:41 +00:00
FrontBackDispatcherType dispatcher(worklet);
timer.Start();
dispatcher.Invoke(frontExt,
afterY,
backExt,
WaveletBase::filter.GetLowDecomposeFilter(),
WaveletBase::filter.GetHighDecomposeFilter(),
coeffOut);
2017-02-17 22:27:30 +00:00
computationTime += timer.GetElapsedTime();
}
return computationTime;
}
2017-02-21 23:56:57 +00:00
// Performs one level of IDWT on a small cube of a big cube
// The output array has the same dimensions as the small cube.
template <typename ArrayInType, typename ArrayOutType>
vtkm::Float64 IDWT3D(ArrayInType& coeffIn,
vtkm::Id inDimX,
vtkm::Id inDimY,
vtkm::Id inDimZ,
vtkm::Id inStartX,
vtkm::Id inStartY,
vtkm::Id inStartZ,
const std::vector<vtkm::Id>& L,
ArrayOutType& sigOut,
bool discardCoeffIn) // can we discard coeffIn?
2017-02-21 23:56:57 +00:00
{
//VTKM_ASSERT( L.size() == 27 );
//VTKM_ASSERT( inDimX * inDimY * inDimZ == coeffIn.GetNumberOfValues() );
2017-02-21 23:56:57 +00:00
vtkm::Id inPretendDimX = L[0] + L[12];
vtkm::Id inPretendDimY = L[1] + L[7];
vtkm::Id inPretendDimZ = L[2] + L[5];
vtkm::Id filterLen = WaveletBase::filter.GetFilterLength();
2018-02-22 13:29:13 +00:00
using BasicArrayType = vtkm::cont::ArrayHandle<typename ArrayInType::ValueType>;
using LeftRightXFormType = vtkm::worklet::wavelets::InverseTransform3DLeftRight;
using TopDownXFormType = vtkm::worklet::wavelets::InverseTransform3DTopDown;
using FrontBackXFormType = vtkm::worklet::wavelets::InverseTransform3DFrontBack;
using LeftRightDispatcherType = vtkm::worklet::DispatcherMapField<LeftRightXFormType>;
using TopDownDispatcherType = vtkm::worklet::DispatcherMapField<TopDownXFormType>;
using FrontBackDispatcherType = vtkm::worklet::DispatcherMapField<FrontBackXFormType>;
vtkm::cont::Timer timer;
2017-02-26 02:49:12 +00:00
vtkm::Float64 computationTime = 0.0;
2017-02-21 23:56:57 +00:00
2017-04-14 23:15:17 +00:00
// First, inverse transform in Z direction
2017-05-18 14:29:41 +00:00
BasicArrayType afterZ;
afterZ.Allocate(inPretendDimX * inPretendDimY * inPretendDimZ);
2017-05-18 14:29:41 +00:00
{
BasicArrayType ext1, ext2, ext3, ext4;
vtkm::Id extDimX = inPretendDimX;
vtkm::Id extDimY = inPretendDimY;
vtkm::Id ext1DimZ = 0, ext2DimZ = 0, ext3DimZ = 0, ext4DimZ = 0;
this->IDWTHelper3DFrontBack(coeffIn,
inDimX,
inDimY,
inDimZ,
inStartX,
inStartY,
inStartZ,
inPretendDimX,
inPretendDimY,
inPretendDimZ,
L[2],
L[5],
ext1,
ext2,
ext3,
ext4,
ext1DimZ,
ext2DimZ,
ext3DimZ,
ext4DimZ,
filterLen,
wmode);
FrontBackXFormType worklet(filterLen,
extDimX,
extDimY,
ext1DimZ, // ext1
extDimX,
extDimY,
ext2DimZ, // ext2
extDimX,
extDimY,
ext3DimZ, // ext3
extDimX,
extDimY,
ext4DimZ, // ext4
inPretendDimX,
inPretendDimY,
L[2], // cA
inPretendDimX,
inPretendDimY,
L[5], // cD
inDimX,
inDimY,
inDimZ, // coeffIn
inStartX,
inStartY,
inStartZ); // coeffIn
2017-05-18 14:29:41 +00:00
FrontBackDispatcherType dispatcher(worklet);
timer.Start();
dispatcher.Invoke(ext1,
ext2,
ext3,
ext4,
coeffIn,
WaveletBase::filter.GetLowReconstructFilter(),
WaveletBase::filter.GetHighReconstructFilter(),
afterZ);
2017-02-26 02:49:12 +00:00
computationTime += timer.GetElapsedTime();
2017-02-21 23:56:57 +00:00
}
2017-03-09 03:29:27 +00:00
2017-05-18 14:29:41 +00:00
if (discardCoeffIn)
2017-05-18 17:51:35 +00:00
{
2017-05-22 20:47:13 +00:00
coeffIn.ReleaseResourcesExecution();
2017-05-18 17:51:35 +00:00
}
2017-05-22 20:47:13 +00:00
2017-04-14 23:15:17 +00:00
// Second, inverse transform in Y direction
2017-05-18 14:29:41 +00:00
BasicArrayType afterY;
afterY.Allocate(inPretendDimX * inPretendDimY * inPretendDimZ);
2017-02-21 23:56:57 +00:00
{
2017-05-18 14:29:41 +00:00
BasicArrayType ext1, ext2, ext3, ext4;
2017-02-21 23:56:57 +00:00
vtkm::Id extDimX = inPretendDimX;
vtkm::Id extDimZ = inPretendDimZ;
vtkm::Id ext1DimY = 0, ext2DimY = 0, ext3DimY = 0, ext4DimY = 0;
this->IDWTHelper3DTopDown(afterZ,
inPretendDimX,
inPretendDimY,
inPretendDimZ,
0,
0,
0,
inPretendDimX,
inPretendDimY,
inPretendDimZ,
L[1],
L[7],
ext1,
ext2,
ext3,
ext4,
ext1DimY,
ext2DimY,
ext3DimY,
ext4DimY,
filterLen,
wmode);
TopDownXFormType worklet(filterLen,
extDimX,
ext1DimY,
extDimZ, // ext1
extDimX,
ext2DimY,
extDimZ, // ext2
extDimX,
ext3DimY,
extDimZ, // ext3
extDimX,
ext4DimY,
extDimZ, // ext4
inPretendDimX,
L[1],
inPretendDimZ, // cA
inPretendDimX,
L[7],
inPretendDimZ, // cD
inPretendDimX,
inPretendDimY,
inPretendDimZ, // actual signal
0,
0,
0);
2017-05-18 14:29:41 +00:00
TopDownDispatcherType dispatcher(worklet);
timer.Start();
dispatcher.Invoke(ext1,
ext2,
ext3,
ext4,
afterZ,
WaveletBase::filter.GetLowReconstructFilter(),
WaveletBase::filter.GetHighReconstructFilter(),
afterY);
2017-02-26 02:49:12 +00:00
computationTime += timer.GetElapsedTime();
2017-05-22 20:47:13 +00:00
}
2017-02-21 23:56:57 +00:00
2017-04-14 23:15:17 +00:00
// Lastly, inverse transform in X direction
2017-02-21 23:56:57 +00:00
afterZ.ReleaseResources();
{
2017-05-18 14:29:41 +00:00
BasicArrayType ext1, ext2, ext3, ext4;
vtkm::Id extDimY = inPretendDimY;
vtkm::Id extDimZ = inPretendDimZ;
vtkm::Id ext1DimX = 0, ext2DimX = 0, ext3DimX = 0, ext4DimX = 0;
this->IDWTHelper3DLeftRight(afterY,
inPretendDimX,
inPretendDimY,
inPretendDimZ,
0,
0,
0,
inPretendDimX,
inPretendDimY,
inPretendDimZ,
L[0],
L[12],
ext1,
ext2,
ext3,
ext4,
ext1DimX,
ext2DimX,
ext3DimX,
ext4DimX,
filterLen,
wmode);
sigOut.Allocate(inPretendDimX * inPretendDimY * inPretendDimZ);
LeftRightXFormType worklet(filterLen,
ext1DimX,
extDimY,
extDimZ, // ext1
ext2DimX,
extDimY,
extDimZ, // ext2
ext3DimX,
extDimY,
extDimZ, // ext3
ext4DimX,
extDimY,
extDimZ, // ext4
L[0],
inPretendDimY,
inPretendDimZ, // cA
L[12],
inPretendDimY,
inPretendDimZ, // cD
inPretendDimX,
inPretendDimY,
inPretendDimZ, // actual signal
0,
0,
0);
2017-05-18 14:29:41 +00:00
LeftRightDispatcherType dispatcher(worklet);
timer.Start();
dispatcher.Invoke(ext1,
ext2,
ext3,
ext4,
afterY,
WaveletBase::filter.GetLowReconstructFilter(),
WaveletBase::filter.GetHighReconstructFilter(),
sigOut);
2017-05-22 20:47:13 +00:00
computationTime += timer.GetElapsedTime();
2017-02-21 23:56:57 +00:00
}
2017-02-26 02:49:12 +00:00
return computationTime;
2017-02-21 23:56:57 +00:00
}
//=============================================================================
template <typename SigInArrayType, typename ExtensionArrayType>
2017-05-18 14:29:41 +00:00
vtkm::Id Extend2D(const SigInArrayType& sigIn, // Input
vtkm::Id sigDimX,
vtkm::Id sigDimY,
vtkm::Id sigStartX,
vtkm::Id sigStartY,
vtkm::Id sigPretendDimX,
vtkm::Id sigPretendDimY,
2017-05-18 14:29:41 +00:00
ExtensionArrayType& ext1, // left/top extension
ExtensionArrayType& ext2, // right/bottom extension
vtkm::Id addLen,
vtkm::worklet::wavelets::DWTMode ext1Method,
vtkm::worklet::wavelets::DWTMode ext2Method,
bool pretendSigPaddedZero,
2017-05-18 14:29:41 +00:00
bool padZeroAtExt2,
bool modeLR) // true = left-right, false = top-down
{
// pretendSigPaddedZero and padZeroAtExt2 cannot happen at the same time
2017-05-18 14:29:41 +00:00
VTKM_ASSERT(!pretendSigPaddedZero || !padZeroAtExt2);
2017-05-18 14:29:41 +00:00
if (addLen == 0) // Haar kernel
{
ext1.Allocate(0); // no need to extend on left/top
2017-05-18 14:29:41 +00:00
if (pretendSigPaddedZero || padZeroAtExt2)
{
2017-05-18 14:29:41 +00:00
if (modeLR) // right extension
{
ext2.Allocate(sigPretendDimY);
WaveletBase::DeviceAssignZero2DColumn(ext2, 1, sigPretendDimY, 0);
}
2017-05-18 14:29:41 +00:00
else // bottom extension
{
ext2.Allocate(sigPretendDimX);
WaveletBase::DeviceAssignZero2DRow(ext2, sigPretendDimX, 1, 0);
}
}
else
2017-05-18 17:51:35 +00:00
{
ext2.Allocate(0);
2017-05-18 17:51:35 +00:00
}
return 0;
}
2018-02-22 13:29:13 +00:00
using ValueType = typename SigInArrayType::ValueType;
using ExtendArrayType = vtkm::cont::ArrayHandle<ValueType>;
using ExtensionWorklet = vtkm::worklet::wavelets::ExtensionWorklet2D;
using DispatcherType = typename vtkm::worklet::DispatcherMapField<ExtensionWorklet>;
2017-05-18 14:29:41 +00:00
vtkm::Id extDimX, extDimY;
vtkm::worklet::wavelets::ExtensionDirection dir;
2017-05-18 14:29:41 +00:00
{ // Work on left/top extension
if (modeLR)
{
dir = LEFT;
extDimX = addLen;
extDimY = sigPretendDimY;
}
else
{
dir = TOP;
extDimX = sigPretendDimX;
extDimY = addLen;
}
ext1.Allocate(extDimX * extDimY);
ExtensionWorklet worklet(extDimX,
extDimY,
sigDimX,
sigDimY,
sigStartX,
sigStartY,
sigPretendDimX,
sigPretendDimY, // use this area
ext1Method,
dir,
false); // not treating sigIn as having zeros
2017-05-18 14:29:41 +00:00
DispatcherType dispatcher(worklet);
dispatcher.Invoke(ext1, sigIn);
}
// Work on right/bottom extension
2017-05-18 14:29:41 +00:00
if (!pretendSigPaddedZero && !padZeroAtExt2)
{
2017-05-18 14:29:41 +00:00
if (modeLR)
{
dir = RIGHT;
extDimX = addLen;
extDimY = sigPretendDimY;
}
else
{
dir = BOTTOM;
extDimX = sigPretendDimX;
extDimY = addLen;
}
ext2.Allocate(extDimX * extDimY);
ExtensionWorklet worklet(extDimX,
extDimY,
sigDimX,
sigDimY,
sigStartX,
sigStartY,
sigPretendDimX,
sigPretendDimY, // use this area
ext2Method,
dir,
false);
2017-05-18 14:29:41 +00:00
DispatcherType dispatcher(worklet);
dispatcher.Invoke(ext2, sigIn);
}
2017-05-18 14:29:41 +00:00
else if (!pretendSigPaddedZero && padZeroAtExt2)
{
2017-05-18 14:29:41 +00:00
if (modeLR)
{
dir = RIGHT;
2017-05-18 14:29:41 +00:00
extDimX = addLen + 1;
extDimY = sigPretendDimY;
}
else
{
dir = BOTTOM;
extDimX = sigPretendDimX;
2017-05-18 14:29:41 +00:00
extDimY = addLen + 1;
}
ext2.Allocate(extDimX * extDimY);
ExtensionWorklet worklet(extDimX,
extDimY,
sigDimX,
sigDimY,
sigStartX,
sigStartY,
sigPretendDimX,
sigPretendDimY,
ext2Method,
dir,
false);
2017-05-18 14:29:41 +00:00
DispatcherType dispatcher(worklet);
dispatcher.Invoke(ext2, sigIn);
/* Pad a zero at the end of cDTemp, when cDTemp is forced to have the same
length as cATemp. For example, with odd length signal, cA is 1 element
2017-05-22 20:47:13 +00:00
longer than cD.
*/
2017-05-22 20:47:13 +00:00
/* Update 10/24/2016: the extra element of cD shouldn't be zero, just be
* whatever it extends to be.
* if( modeLR )
* WaveletBase::DeviceAssignZero2DColumn( ext2, extDimX, extDimY,
* extDimX-1 );
* else
* WaveletBase::DeviceAssignZero2DRow( ext2, extDimX, extDimY,
* extDimY-1 );
*/
}
2017-05-18 14:29:41 +00:00
else // pretendSigPaddedZero
{
ExtendArrayType ext2Temp;
2017-05-18 14:29:41 +00:00
if (modeLR)
{
dir = RIGHT;
extDimX = addLen;
extDimY = sigPretendDimY;
}
else
{
dir = BOTTOM;
extDimX = sigPretendDimX;
extDimY = addLen;
}
ext2Temp.Allocate(extDimX * extDimY);
ExtensionWorklet worklet(extDimX,
extDimY,
sigDimX,
sigDimY,
sigStartX,
sigStartY,
sigPretendDimX,
sigPretendDimY,
ext2Method,
dir,
2017-05-18 14:29:41 +00:00
true); // pretend sig is padded a zero
DispatcherType dispatcher(worklet);
dispatcher.Invoke(ext2Temp, sigIn);
2017-05-22 20:47:13 +00:00
2017-05-18 14:29:41 +00:00
if (modeLR)
{
ext2.Allocate((extDimX + 1) * extDimY);
WaveletBase::DeviceRectangleCopyTo(
ext2Temp, extDimX, extDimY, ext2, extDimX + 1, extDimY, 1, 0);
WaveletBase::DeviceAssignZero2DColumn(ext2, extDimX + 1, extDimY, 0);
}
else
{
ext2.Allocate(extDimX * (extDimY + 1));
WaveletBase::DeviceRectangleCopyTo(
ext2Temp, extDimX, extDimY, ext2, extDimX, extDimY + 1, 0, 1);
WaveletBase::DeviceAssignZero2DRow(ext2, extDimX, extDimY + 1, 0);
}
}
return 0;
}
2016-09-11 22:14:01 +00:00
// Extend 1D signal
template <typename SigInArrayType, typename SigExtendedArrayType>
2017-05-18 14:29:41 +00:00
vtkm::Id Extend1D(const SigInArrayType& sigIn, // Input
SigExtendedArrayType& sigOut, // Output
vtkm::Id addLen,
vtkm::worklet::wavelets::DWTMode leftExtMethod,
vtkm::worklet::wavelets::DWTMode rightExtMethod,
bool attachZeroRightLeft,
bool attachZeroRightRight)
2017-05-22 20:47:13 +00:00
{
// "right extension" can be attached a zero on either end, but not both ends.
2017-05-18 14:29:41 +00:00
VTKM_ASSERT(!attachZeroRightRight || !attachZeroRightLeft);
2018-02-22 13:29:13 +00:00
using ValueType = typename SigInArrayType::ValueType;
using ExtensionArrayType = vtkm::cont::ArrayHandle<ValueType>;
using ArrayConcat = vtkm::cont::ArrayHandleConcatenate<ExtensionArrayType, SigInArrayType>;
2017-05-22 20:47:13 +00:00
2017-05-18 14:29:41 +00:00
ExtensionArrayType leftExtend, rightExtend;
2017-05-18 14:29:41 +00:00
if (addLen == 0) // Haar kernel
2016-09-07 23:43:10 +00:00
{
2017-05-18 14:29:41 +00:00
if (attachZeroRightLeft || attachZeroRightRight)
2016-09-07 23:43:10 +00:00
{
leftExtend.Allocate(0);
rightExtend.Allocate(1);
WaveletBase::DeviceAssignZero(rightExtend, 0);
2016-09-07 23:43:10 +00:00
}
else
{
leftExtend.Allocate(0);
rightExtend.Allocate(0);
2016-09-07 23:43:10 +00:00
}
2017-05-18 14:29:41 +00:00
ArrayConcat leftOn(leftExtend, sigIn);
sigOut = vtkm::cont::make_ArrayHandleConcatenate(leftOn, rightExtend);
2016-09-07 23:43:10 +00:00
return 0;
}
leftExtend.Allocate(addLen);
vtkm::Id sigInLen = sigIn.GetNumberOfValues();
2018-02-22 13:29:13 +00:00
using LeftSYMH = vtkm::worklet::wavelets::LeftSYMHExtentionWorklet;
using LeftSYMW = vtkm::worklet::wavelets::LeftSYMWExtentionWorklet;
using RightSYMH = vtkm::worklet::wavelets::RightSYMHExtentionWorklet;
using RightSYMW = vtkm::worklet::wavelets::RightSYMWExtentionWorklet;
using LeftASYMH = vtkm::worklet::wavelets::LeftASYMHExtentionWorklet;
using LeftASYMW = vtkm::worklet::wavelets::LeftASYMWExtentionWorklet;
using RightASYMH = vtkm::worklet::wavelets::RightASYMHExtentionWorklet;
using RightASYMW = vtkm::worklet::wavelets::RightASYMWExtentionWorklet;
2017-05-18 14:29:41 +00:00
switch (leftExtMethod)
{
case SYMH:
{
2017-05-18 14:29:41 +00:00
LeftSYMH worklet(addLen);
vtkm::worklet::DispatcherMapField<LeftSYMH> dispatcher(worklet);
2017-05-18 14:29:41 +00:00
dispatcher.Invoke(leftExtend, sigIn);
break;
}
case SYMW:
{
2017-05-18 14:29:41 +00:00
LeftSYMW worklet(addLen);
vtkm::worklet::DispatcherMapField<LeftSYMW> dispatcher(worklet);
2017-05-18 14:29:41 +00:00
dispatcher.Invoke(leftExtend, sigIn);
break;
}
case ASYMH:
{
2017-05-18 14:29:41 +00:00
LeftASYMH worklet(addLen);
vtkm::worklet::DispatcherMapField<LeftASYMH> dispatcher(worklet);
2017-05-18 14:29:41 +00:00
dispatcher.Invoke(leftExtend, sigIn);
break;
}
case ASYMW:
{
2017-05-18 14:29:41 +00:00
LeftASYMW worklet(addLen);
vtkm::worklet::DispatcherMapField<LeftASYMW> dispatcher(worklet);
2017-05-18 14:29:41 +00:00
dispatcher.Invoke(leftExtend, sigIn);
break;
}
default:
{
vtkm::cont::ErrorInternal("Left extension mode not supported!");
return 1;
}
}
2017-05-18 14:29:41 +00:00
if (!attachZeroRightLeft) // no attach zero, or only attach on RightRight
{
// Allocate memory
2017-05-18 14:29:41 +00:00
if (attachZeroRightRight)
2017-05-18 17:51:35 +00:00
{
rightExtend.Allocate(addLen + 1);
2017-05-18 17:51:35 +00:00
}
2017-05-22 20:47:13 +00:00
else
2017-05-18 17:51:35 +00:00
{
rightExtend.Allocate(addLen);
2017-05-18 17:51:35 +00:00
}
2017-05-18 14:29:41 +00:00
switch (rightExtMethod)
{
case SYMH:
{
2017-05-18 14:29:41 +00:00
RightSYMH worklet(sigInLen);
vtkm::worklet::DispatcherMapField<RightSYMH> dispatcher(worklet);
2017-05-18 14:29:41 +00:00
dispatcher.Invoke(rightExtend, sigIn);
break;
}
case SYMW:
{
2017-05-18 14:29:41 +00:00
RightSYMW worklet(sigInLen);
vtkm::worklet::DispatcherMapField<RightSYMW> dispatcher(worklet);
2017-05-18 14:29:41 +00:00
dispatcher.Invoke(rightExtend, sigIn);
break;
}
case ASYMH:
{
2017-05-18 14:29:41 +00:00
RightASYMH worklet(sigInLen);
vtkm::worklet::DispatcherMapField<RightASYMH> dispatcher(worklet);
2017-05-18 14:29:41 +00:00
dispatcher.Invoke(rightExtend, sigIn);
break;
}
case ASYMW:
{
2017-05-18 14:29:41 +00:00
RightASYMW worklet(sigInLen);
vtkm::worklet::DispatcherMapField<RightASYMW> dispatcher(worklet);
2017-05-18 14:29:41 +00:00
dispatcher.Invoke(rightExtend, sigIn);
break;
}
default:
{
vtkm::cont::ErrorInternal("Right extension mode not supported!");
return 1;
}
}
2017-05-18 14:29:41 +00:00
if (attachZeroRightRight)
2017-05-18 17:51:35 +00:00
{
WaveletBase::DeviceAssignZero(rightExtend, addLen);
2017-05-18 17:51:35 +00:00
}
}
2017-05-18 14:29:41 +00:00
else // attachZeroRightLeft mode
{
2018-02-22 13:29:13 +00:00
using ConcatArray = vtkm::cont::ArrayHandleConcatenate<SigInArrayType, ExtensionArrayType>;
// attach a zero at the end of sigIn
2017-05-18 14:29:41 +00:00
ExtensionArrayType singleValArray;
singleValArray.Allocate(1);
WaveletBase::DeviceAssignZero(singleValArray, 0);
2017-05-18 14:29:41 +00:00
ConcatArray sigInPlusOne(sigIn, singleValArray);
// allocate memory for extension
rightExtend.Allocate(addLen);
2017-05-18 14:29:41 +00:00
switch (rightExtMethod)
{
case SYMH:
{
2017-05-18 14:29:41 +00:00
RightSYMH worklet(sigInLen + 1);
vtkm::worklet::DispatcherMapField<RightSYMH> dispatcher(worklet);
2017-05-18 14:29:41 +00:00
dispatcher.Invoke(rightExtend, sigInPlusOne);
break;
}
case SYMW:
{
2017-05-18 14:29:41 +00:00
RightSYMW worklet(sigInLen + 1);
vtkm::worklet::DispatcherMapField<RightSYMW> dispatcher(worklet);
2017-05-18 14:29:41 +00:00
dispatcher.Invoke(rightExtend, sigInPlusOne);
break;
}
case ASYMH:
{
2017-05-18 14:29:41 +00:00
RightASYMH worklet(sigInLen + 1);
vtkm::worklet::DispatcherMapField<RightASYMH> dispatcher(worklet);
2017-05-18 14:29:41 +00:00
dispatcher.Invoke(rightExtend, sigInPlusOne);
break;
}
case ASYMW:
{
2017-05-18 14:29:41 +00:00
RightASYMW worklet(sigInLen + 1);
vtkm::worklet::DispatcherMapField<RightASYMW> dispatcher(worklet);
2017-05-18 14:29:41 +00:00
dispatcher.Invoke(rightExtend, sigInPlusOne);
break;
}
default:
{
vtkm::cont::ErrorInternal("Right extension mode not supported!");
return 1;
}
}
// make a copy of rightExtend with a zero attached to the left
ExtensionArrayType rightExtendPlusOne;
rightExtendPlusOne.Allocate(addLen + 1);
WaveletBase::DeviceCopyStartX(rightExtend, rightExtendPlusOne, 1);
WaveletBase::DeviceAssignZero(rightExtendPlusOne, 0);
2017-05-18 14:29:41 +00:00
rightExtend = rightExtendPlusOne;
}
2016-08-03 03:41:46 +00:00
2017-05-18 14:29:41 +00:00
ArrayConcat leftOn(leftExtend, sigIn);
sigOut = vtkm::cont::make_ArrayHandleConcatenate(leftOn, rightExtend);
return 0;
}
2017-05-22 20:47:13 +00:00
// Performs one level of 1D discrete wavelet transform
// It takes care of boundary conditions, etc.
template <typename SignalArrayType, typename CoeffArrayType>
2017-05-18 14:29:41 +00:00
vtkm::Float64 DWT1D(const SignalArrayType& sigIn, // Input
CoeffArrayType& coeffOut, // Output: cA followed by cD
std::vector<vtkm::Id>& L) // Output: how many cA and cD.
{
vtkm::Id sigInLen = sigIn.GetNumberOfValues();
2017-05-18 14:29:41 +00:00
if (GetWaveletMaxLevel(sigInLen) < 1)
{
2017-05-18 14:29:41 +00:00
vtkm::cont::ErrorInternal("Signal is too short to perform DWT!");
return -1;
2017-05-22 20:47:13 +00:00
}
//VTKM_ASSERT( L.size() == 3 );
2017-05-18 14:29:41 +00:00
L[0] = WaveletBase::GetApproxLength(sigInLen);
L[1] = WaveletBase::GetDetailLength(sigInLen);
L[2] = sigInLen;
//VTKM_ASSERT( L[0] + L[1] == L[2] );
vtkm::Id filterLen = WaveletBase::filter.GetFilterLength();
bool doSymConv = false;
2017-05-18 14:29:41 +00:00
if (WaveletBase::filter.isSymmetric())
{
2017-05-18 14:29:41 +00:00
if ((WaveletBase::wmode == SYMW && (filterLen % 2 != 0)) ||
(WaveletBase::wmode == SYMH && (filterLen % 2 == 0)))
2017-05-18 17:51:35 +00:00
{
doSymConv = true;
2017-05-18 17:51:35 +00:00
}
}
2017-05-18 14:29:41 +00:00
vtkm::Id sigConvolvedLen = L[0] + L[1]; // approx + detail coeffs
vtkm::Id addLen; // for extension
bool oddLow = true;
bool oddHigh = true;
2017-05-18 14:29:41 +00:00
if (filterLen % 2 != 0)
2017-05-18 17:51:35 +00:00
{
oddLow = false;
2017-05-18 17:51:35 +00:00
}
2017-05-18 14:29:41 +00:00
if (doSymConv)
{
addLen = filterLen / 2;
2017-05-18 14:29:41 +00:00
if (sigInLen % 2 != 0)
2017-05-18 17:51:35 +00:00
{
sigConvolvedLen += 1;
2017-05-18 17:51:35 +00:00
}
}
else
2017-05-18 17:51:35 +00:00
{
2017-05-22 20:47:13 +00:00
addLen = filterLen - 1;
2017-05-18 17:51:35 +00:00
}
2017-05-22 20:47:13 +00:00
vtkm::Id sigExtendedLen = sigInLen + 2 * addLen;
2018-02-22 13:29:13 +00:00
using SigInValueType = typename SignalArrayType::ValueType;
using SigInBasic = vtkm::cont::ArrayHandle<SigInValueType>;
2018-02-22 13:29:13 +00:00
using ConcatType1 = vtkm::cont::ArrayHandleConcatenate<SigInBasic, SignalArrayType>;
using ConcatType2 = vtkm::cont::ArrayHandleConcatenate<ConcatType1, SigInBasic>;
2016-08-03 03:41:46 +00:00
ConcatType2 sigInExtended;
this->Extend1D(
sigIn, sigInExtended, addLen, WaveletBase::wmode, WaveletBase::wmode, false, false);
//VTKM_ASSERT( sigInExtended.GetNumberOfValues() == sigExtendedLen );
// initialize a worklet for forward transform
vtkm::worklet::wavelets::ForwardTransform forwardTransform(
filterLen, L[0], L[1], oddLow, oddHigh);
coeffOut.Allocate(sigExtendedLen);
vtkm::worklet::DispatcherMapField<vtkm::worklet::wavelets::ForwardTransform> dispatcher(
forwardTransform);
// put a timer
vtkm::cont::Timer timer;
timer.Start();
dispatcher.Invoke(sigInExtended,
WaveletBase::filter.GetLowDecomposeFilter(),
WaveletBase::filter.GetHighDecomposeFilter(),
coeffOut);
2017-05-22 20:47:13 +00:00
vtkm::Float64 elapsedTime = timer.GetElapsedTime();
//VTKM_ASSERT( L[0] + L[1] <= coeffOut.GetNumberOfValues() );
2017-05-18 14:29:41 +00:00
coeffOut.Shrink(L[0] + L[1]);
2017-05-22 20:47:13 +00:00
return elapsedTime;
}
// Performs one level of inverse wavelet transform
// It takes care of boundary conditions, etc.
template <typename CoeffArrayType, typename SignalArrayType>
2017-05-18 14:29:41 +00:00
vtkm::Float64 IDWT1D(const CoeffArrayType& coeffIn, // Input, cA followed by cD
std::vector<vtkm::Id>& L, // Input, how many cA and cD
SignalArrayType& sigOut) // Output
{
vtkm::Id filterLen = WaveletBase::filter.GetFilterLength();
bool doSymConv = false;
2017-05-18 14:29:41 +00:00
vtkm::worklet::wavelets::DWTMode cALeftMode = WaveletBase::wmode;
vtkm::worklet::wavelets::DWTMode cARightMode = WaveletBase::wmode;
2017-05-18 14:29:41 +00:00
vtkm::worklet::wavelets::DWTMode cDLeftMode = WaveletBase::wmode;
vtkm::worklet::wavelets::DWTMode cDRightMode = WaveletBase::wmode;
2017-05-22 20:47:13 +00:00
2017-05-18 14:29:41 +00:00
if (WaveletBase::filter.isSymmetric()) // this is always true with the 1st 4 filters.
{
2017-05-18 14:29:41 +00:00
if ((WaveletBase::wmode == SYMW && (filterLen % 2 != 0)) ||
(WaveletBase::wmode == SYMH && (filterLen % 2 == 0)))
{
2017-05-18 14:29:41 +00:00
doSymConv = true; // doSymConv is always true with the 1st 4 filters.
2017-05-18 14:29:41 +00:00
if (WaveletBase::wmode == SYMH)
{
cDLeftMode = ASYMH;
2017-05-18 14:29:41 +00:00
if (L[2] % 2 != 0)
{
cARightMode = SYMW;
cDRightMode = ASYMW;
}
else
2017-05-18 17:51:35 +00:00
{
cDRightMode = ASYMH;
2017-05-18 17:51:35 +00:00
}
}
else
{
cDLeftMode = SYMH;
2017-05-18 14:29:41 +00:00
if (L[2] % 2 != 0)
{
cARightMode = SYMW;
cDRightMode = SYMH;
}
else
2017-05-18 17:51:35 +00:00
{
cARightMode = SYMH;
2017-05-18 17:51:35 +00:00
}
}
}
2017-05-22 20:47:13 +00:00
}
2017-05-18 14:29:41 +00:00
vtkm::Id cATempLen, cDTempLen; //, reconTempLen;
vtkm::Id addLen = 0;
2017-05-18 14:29:41 +00:00
vtkm::Id cDPadLen = 0;
if (doSymConv) // extend cA and cD
{
2017-05-18 14:29:41 +00:00
addLen = filterLen / 4; // addLen == 0 for Haar kernel
if ((L[0] > L[1]) && (WaveletBase::wmode == SYMH))
2017-05-18 17:51:35 +00:00
{
2017-05-22 20:47:13 +00:00
cDPadLen = L[0];
2017-05-18 17:51:35 +00:00
}
cATempLen = L[0] + 2 * addLen;
2017-05-18 14:29:41 +00:00
cDTempLen = cATempLen; // same length
}
2017-05-18 14:29:41 +00:00
else // not extend cA and cD
{ // (biorthogonal kernels won't come into this case)
cATempLen = L[0];
cDTempLen = L[1];
}
2018-02-22 13:29:13 +00:00
using IdArrayType = vtkm::cont::ArrayHandleCounting<vtkm::Id>;
using PermutArrayType = vtkm::cont::ArrayHandlePermutation<IdArrayType, CoeffArrayType>;
// Separate cA and cD
2017-05-18 14:29:41 +00:00
IdArrayType approxIndices(0, 1, L[0]);
IdArrayType detailIndices(L[0], 1, L[1]);
PermutArrayType cA(approxIndices, coeffIn);
PermutArrayType cD(detailIndices, coeffIn);
2018-02-22 13:29:13 +00:00
using CoeffValueType = typename CoeffArrayType::ValueType;
using ExtensionArrayType = vtkm::cont::ArrayHandle<CoeffValueType>;
using Concat1 = vtkm::cont::ArrayHandleConcatenate<ExtensionArrayType, PermutArrayType>;
using Concat2 = vtkm::cont::ArrayHandleConcatenate<Concat1, ExtensionArrayType>;
2016-08-03 03:41:46 +00:00
Concat2 cATemp, cDTemp;
2017-05-18 14:29:41 +00:00
if (doSymConv) // Actually extend cA and cD
{
// first extend cA to be cATemp
this->Extend1D(cA, cATemp, addLen, cALeftMode, cARightMode, false, false);
// Then extend cD based on extension needs
2017-05-18 14:29:41 +00:00
if (cDPadLen > 0)
{
// Add back the missing final cD, 0.0, before doing extension
this->Extend1D(cD, cDTemp, addLen, cDLeftMode, cDRightMode, true, false);
}
else
{
vtkm::Id cDTempLenWouldBe = L[1] + 2 * addLen;
2017-05-18 14:29:41 +00:00
if (cDTempLenWouldBe == cDTempLen)
2017-05-22 20:47:13 +00:00
{
this->Extend1D(cD, cDTemp, addLen, cDLeftMode, cDRightMode, false, false);
}
2017-05-18 14:29:41 +00:00
else if (cDTempLenWouldBe == cDTempLen - 1)
2017-05-22 20:47:13 +00:00
{
this->Extend1D(cD, cDTemp, addLen, cDLeftMode, cDRightMode, false, true);
}
2016-08-03 03:41:46 +00:00
else
{
vtkm::cont::ErrorInternal("cDTemp Length not match!");
2016-08-03 03:41:46 +00:00
return 1;
}
}
2017-05-22 20:47:13 +00:00
}
else
{
// make cATemp
ExtensionArrayType dummyArray;
dummyArray.Allocate(0);
2017-05-18 14:29:41 +00:00
Concat1 cALeftOn(dummyArray, cA);
cATemp =
vtkm::cont::make_ArrayHandleConcatenate<Concat1, ExtensionArrayType>(cALeftOn, dummyArray);
2017-05-22 20:47:13 +00:00
// make cDTemp
2017-05-18 14:29:41 +00:00
Concat1 cDLeftOn(dummyArray, cD);
cDTemp =
vtkm::cont::make_ArrayHandleConcatenate<Concat1, ExtensionArrayType>(cDLeftOn, dummyArray);
}
2017-05-18 14:29:41 +00:00
vtkm::cont::ArrayHandleConcatenate<Concat2, Concat2> coeffInExtended(cATemp, cDTemp);
2016-09-05 22:53:44 +00:00
// Allocate memory for sigOut
sigOut.Allocate(cATempLen + cDTempLen);
2017-05-22 20:47:13 +00:00
vtkm::Float64 elapsedTime = 0;
2017-05-18 14:29:41 +00:00
if (filterLen % 2 != 0)
{
vtkm::worklet::wavelets::InverseTransformOdd inverseXformOdd(filterLen, L[0], cATempLen);
vtkm::worklet::DispatcherMapField<vtkm::worklet::wavelets::InverseTransformOdd> dispatcher(
inverseXformOdd);
// use a timer
vtkm::cont::Timer timer;
timer.Start();
dispatcher.Invoke(coeffInExtended,
WaveletBase::filter.GetLowReconstructFilter(),
WaveletBase::filter.GetHighReconstructFilter(),
sigOut);
elapsedTime = timer.GetElapsedTime();
}
else
{
vtkm::worklet::wavelets::InverseTransformEven inverseXformEven(
filterLen, L[0], cATempLen, !doSymConv);
vtkm::worklet::DispatcherMapField<vtkm::worklet::wavelets::InverseTransformEven> dispatcher(
inverseXformEven);
// use a timer
vtkm::cont::Timer timer;
timer.Start();
dispatcher.Invoke(coeffInExtended,
WaveletBase::filter.GetLowReconstructFilter(),
WaveletBase::filter.GetHighReconstructFilter(),
sigOut);
elapsedTime = timer.GetElapsedTime();
}
2017-05-18 14:29:41 +00:00
sigOut.Shrink(L[2]);
return elapsedTime;
2017-05-22 20:47:13 +00:00
}
// Performs one level of 2D discrete wavelet transform
2016-08-09 23:32:13 +00:00
// It takes care of boundary conditions, etc.
// N.B.
// L[0] == L[2]
// L[1] == L[5]
// L[3] == L[7]
// L[4] == L[6]
//
// ____L[0]_______L[4]____
// | | |
// L[1] | cA | cDv | L[5]
// | (LL) | (HL) |
// | | |
// |---------------------|
// | | |
// | cDh | cDd | L[7]
// L[3] | (LH) | (HH) |
// | | |
// |__________|__________|
// L[2] L[6]
//
// Performs one level of 2D discrete wavelet transform on a small rectangle of input array
// The output has the same size as the small rectangle
template <typename ArrayInType, typename ArrayOutType>
vtkm::Float64 DWT2D(const ArrayInType& sigIn,
vtkm::Id sigDimX,
vtkm::Id sigDimY,
vtkm::Id sigStartX,
vtkm::Id sigStartY,
vtkm::Id sigPretendDimX,
vtkm::Id sigPretendDimY,
ArrayOutType& coeffOut,
std::vector<vtkm::Id>& L)
{
2017-05-18 14:29:41 +00:00
L[0] = WaveletBase::GetApproxLength(sigPretendDimX);
L[2] = L[0];
L[1] = WaveletBase::GetApproxLength(sigPretendDimY);
L[5] = L[1];
L[3] = WaveletBase::GetDetailLength(sigPretendDimY);
L[7] = L[3];
L[4] = WaveletBase::GetDetailLength(sigPretendDimX);
L[6] = L[4];
2017-05-22 20:47:13 +00:00
L[8] = sigPretendDimX;
L[9] = sigPretendDimY;
vtkm::Id filterLen = WaveletBase::filter.GetFilterLength();
2017-05-18 14:29:41 +00:00
bool oddLow = true;
if (filterLen % 2 != 0)
2017-05-18 17:51:35 +00:00
{
oddLow = false;
2017-05-18 17:51:35 +00:00
}
2017-05-18 14:29:41 +00:00
vtkm::Id addLen = filterLen / 2;
2018-02-22 13:29:13 +00:00
using ValueType = typename ArrayInType::ValueType;
using ArrayType = vtkm::cont::ArrayHandle<ValueType>;
using ForwardXForm = vtkm::worklet::wavelets::ForwardTransform2D;
using DispatcherType = typename vtkm::worklet::DispatcherMapField<ForwardXForm>;
vtkm::cont::Timer timer;
vtkm::Float64 computationTime = 0.0;
2017-05-18 14:29:41 +00:00
ArrayType afterX;
afterX.Allocate(sigPretendDimX * sigPretendDimY);
// First transform on rows
{
2017-05-18 14:29:41 +00:00
ArrayType leftExt, rightExt;
this->Extend2D(sigIn,
sigDimX,
sigDimY,
sigStartX,
sigStartY,
sigPretendDimX,
sigPretendDimY,
leftExt,
rightExt,
addLen,
WaveletBase::wmode,
WaveletBase::wmode,
false,
false,
true); // Extend in left-right direction
ForwardXForm worklet(filterLen,
L[0],
oddLow,
2017-05-18 14:29:41 +00:00
true, // left-right
addLen,
sigPretendDimY,
sigDimX,
sigDimY,
sigStartX,
sigStartY,
sigPretendDimX,
sigPretendDimY,
addLen,
sigPretendDimY);
DispatcherType dispatcher(worklet);
timer.Start();
dispatcher.Invoke(leftExt,
sigIn,
rightExt,
WaveletBase::filter.GetLowDecomposeFilter(),
WaveletBase::filter.GetHighDecomposeFilter(),
afterX);
computationTime += timer.GetElapsedTime();
}
// Then do transform in Y direction
{
2017-05-18 14:29:41 +00:00
ArrayType topExt, bottomExt;
coeffOut.Allocate(sigPretendDimX * sigPretendDimY);
this->Extend2D(afterX,
sigPretendDimX,
sigPretendDimY,
0,
0,
sigPretendDimX,
sigPretendDimY,
topExt,
bottomExt,
addLen,
WaveletBase::wmode,
WaveletBase::wmode,
false,
false,
false); // Extend in top-down direction
ForwardXForm worklet(filterLen,
L[1],
oddLow,
2017-05-18 14:29:41 +00:00
false, // top-down
sigPretendDimX,
addLen,
sigPretendDimX,
sigPretendDimY,
0,
0,
sigPretendDimX,
sigPretendDimY,
sigPretendDimX,
addLen);
2017-05-18 14:29:41 +00:00
DispatcherType dispatcher(worklet);
timer.Start();
dispatcher.Invoke(topExt,
afterX,
bottomExt,
WaveletBase::filter.GetLowDecomposeFilter(),
WaveletBase::filter.GetHighDecomposeFilter(),
coeffOut);
computationTime += timer.GetElapsedTime();
}
return computationTime;
}
2016-09-13 19:10:38 +00:00
2017-05-22 20:47:13 +00:00
// Performs one level of IDWT.
// The output array has the same dimensions as the small rectangle.
template <typename ArrayInType, typename ArrayOutType>
vtkm::Float64 IDWT2D(const ArrayInType& coeffIn,
vtkm::Id inDimX,
vtkm::Id inDimY,
vtkm::Id inStartX,
vtkm::Id inStartY,
const std::vector<vtkm::Id>& L,
ArrayOutType& sigOut)
{
vtkm::Id inPretendDimX = L[0] + L[4];
vtkm::Id inPretendDimY = L[1] + L[3];
vtkm::Id filterLen = WaveletBase::filter.GetFilterLength();
2018-02-22 13:29:13 +00:00
using BasicArrayType = vtkm::cont::ArrayHandle<typename ArrayInType::ValueType>;
using IDWT2DWorklet = vtkm::worklet::wavelets::InverseTransform2D;
using Dispatcher = vtkm::worklet::DispatcherMapField<IDWT2DWorklet>;
vtkm::cont::Timer timer;
2016-09-22 03:25:56 +00:00
vtkm::Float64 computationTime = 0.0;
// First inverse transform on columns
2017-05-18 14:29:41 +00:00
BasicArrayType afterY;
{
BasicArrayType ext1, ext2, ext3, ext4;
vtkm::Id extDimX = inPretendDimX;
vtkm::Id ext1DimY = 0, ext2DimY = 0, ext3DimY = 0, ext4DimY = 0;
this->IDWTHelper2DTopDown(coeffIn,
inDimX,
inDimY,
inStartX,
inStartY,
inPretendDimX,
inPretendDimY,
L[1],
L[3],
ext1,
ext2,
ext3,
ext4,
ext1DimY,
ext2DimY,
ext3DimY,
ext4DimY,
filterLen,
wmode);
2017-05-18 14:29:41 +00:00
afterY.Allocate(inPretendDimX * inPretendDimY);
IDWT2DWorklet worklet(filterLen,
extDimX,
ext1DimY, // ext1
inPretendDimX,
L[1], // cA
extDimX,
ext2DimY, // ext2
extDimX,
ext3DimY, // ext3
inPretendDimX,
L[3], // cD
extDimX,
ext4DimY, // ext4
inDimX,
inDimY, // coeffIn
inStartX,
inStartY, // coeffIn
false); // top-down
2017-05-18 14:29:41 +00:00
Dispatcher dispatcher(worklet);
timer.Start();
dispatcher.Invoke(ext1,
ext2,
ext3,
ext4,
coeffIn,
WaveletBase::filter.GetLowReconstructFilter(),
WaveletBase::filter.GetHighReconstructFilter(),
afterY);
2017-05-18 14:29:41 +00:00
computationTime += timer.GetElapsedTime();
2016-09-13 19:10:38 +00:00
}
2017-05-22 20:47:13 +00:00
// Then inverse transform on rows
2016-09-17 02:39:42 +00:00
{
2017-05-18 14:29:41 +00:00
BasicArrayType ext1, ext2, ext3, ext4;
vtkm::Id extDimY = inPretendDimY;
vtkm::Id ext1DimX = 0, ext2DimX = 0, ext3DimX = 0, ext4DimX = 0;
this->IDWTHelper2DLeftRight(afterY,
inPretendDimX,
inPretendDimY,
0,
0,
inPretendDimX,
inPretendDimY,
L[0],
L[4],
ext1,
ext2,
ext3,
ext4,
ext1DimX,
ext2DimX,
ext3DimX,
ext4DimX,
filterLen,
wmode);
sigOut.Allocate(inPretendDimX * inPretendDimY);
IDWT2DWorklet worklet(filterLen,
ext1DimX,
extDimY, // ext1
L[0],
inPretendDimY, // cA
ext2DimX,
extDimY, // ext2
ext3DimX,
extDimY, // ext3
L[4],
inPretendDimY, // cA
ext4DimX,
extDimY, // ext4
inPretendDimX,
inPretendDimY,
0,
0,
2017-05-18 14:29:41 +00:00
true); // left-right
Dispatcher dispatcher(worklet);
timer.Start();
dispatcher.Invoke(ext1,
ext2,
ext3,
ext4,
afterY,
WaveletBase::filter.GetLowReconstructFilter(),
WaveletBase::filter.GetHighReconstructFilter(),
sigOut);
2017-05-18 14:29:41 +00:00
computationTime += timer.GetElapsedTime();
2017-05-22 20:47:13 +00:00
}
return computationTime;
}
2016-09-13 19:10:38 +00:00
// decides the correct extension modes for cA and cD separately,
2017-02-19 04:14:20 +00:00
// and fill the extensions (2D matrices)
template <typename ArrayInType, typename ArrayOutType>
void IDWTHelper2DLeftRight(const ArrayInType& coeffIn,
vtkm::Id inDimX,
vtkm::Id inDimY,
vtkm::Id inStartX,
vtkm::Id inStartY,
vtkm::Id inPretendDimX,
vtkm::Id inPretendDimY,
vtkm::Id cADimX,
vtkm::Id cDDimX,
ArrayOutType& ext1,
ArrayOutType& ext2, // output
ArrayOutType& ext3,
ArrayOutType& ext4, // output
vtkm::Id& ext1DimX,
vtkm::Id& ext2DimX, // output
vtkm::Id& ext3DimX,
vtkm::Id& ext4DimX, // output
vtkm::Id filterLen,
DWTMode mode)
{
VTKM_ASSERT(inPretendDimX == (cADimX + cDDimX));
// determine extension modes
DWTMode cALeft, cARight, cDLeft, cDRight;
cALeft = cARight = cDLeft = cDRight = mode;
2017-05-18 14:29:41 +00:00
if (mode == SYMH)
2017-05-22 20:47:13 +00:00
{
cDLeft = ASYMH;
2017-05-18 14:29:41 +00:00
if (inPretendDimX % 2 != 0)
2017-05-22 20:47:13 +00:00
{
cARight = SYMW;
cDRight = ASYMW;
2017-05-22 20:47:13 +00:00
}
else
2017-05-18 17:51:35 +00:00
{
cDRight = ASYMH;
2017-05-18 17:51:35 +00:00
}
2017-05-22 20:47:13 +00:00
}
2017-05-18 14:29:41 +00:00
else // mode == SYMW
2017-05-22 20:47:13 +00:00
{
cDLeft = SYMH;
2017-05-18 14:29:41 +00:00
if (inPretendDimX % 2 != 0)
2017-05-22 20:47:13 +00:00
{
cARight = SYMW;
cDRight = SYMH;
2017-05-22 20:47:13 +00:00
}
else
2017-05-18 17:51:35 +00:00
{
cARight = SYMH;
2017-05-18 17:51:35 +00:00
}
2017-05-22 20:47:13 +00:00
}
// determine length after extension
vtkm::Id cAExtendedDimX, cDExtendedDimX;
2017-05-18 14:29:41 +00:00
vtkm::Id cDPadLen = 0;
vtkm::Id addLen = filterLen / 4; // addLen == 0 for Haar kernel
if ((cADimX > cDDimX) && (mode == SYMH))
2017-05-18 17:51:35 +00:00
{
cDPadLen = cADimX;
2017-05-18 17:51:35 +00:00
}
cAExtendedDimX = cADimX + 2 * addLen;
cDExtendedDimX = cAExtendedDimX;
// extend cA
vtkm::Id cADimY = inPretendDimY;
this->Extend2D(coeffIn,
inDimX,
inDimY,
inStartX,
inStartY,
cADimX,
cADimY,
ext1,
ext2,
addLen,
cALeft,
cARight,
false,
false,
true);
2017-05-22 20:47:13 +00:00
ext1DimX = ext2DimX = addLen;
// extend cD
vtkm::Id cDDimY = inPretendDimY;
2017-05-18 14:29:41 +00:00
if (cDPadLen > 0)
{
this->Extend2D(coeffIn,
inDimX,
inDimY,
inStartX + cADimX,
inStartY,
cDDimX,
cDDimY,
ext3,
ext4,
addLen,
cDLeft,
cDRight,
true,
false,
true);
ext3DimX = addLen;
ext4DimX = addLen + 1;
}
else
{
vtkm::Id cDExtendedWouldBe = cDDimX + 2 * addLen;
2017-05-18 14:29:41 +00:00
if (cDExtendedWouldBe == cDExtendedDimX)
{
this->Extend2D(coeffIn,
inDimX,
inDimY,
inStartX + cADimX,
inStartY,
cDDimX,
cDDimY,
ext3,
ext4,
addLen,
cDLeft,
cDRight,
false,
false,
true);
ext3DimX = ext4DimX = addLen;
}
2017-05-18 14:29:41 +00:00
else if (cDExtendedWouldBe == cDExtendedDimX - 1)
{
this->Extend2D(coeffIn,
inDimX,
inDimY,
inStartX + cADimX,
inStartY,
cDDimX,
cDDimY,
ext3,
ext4,
addLen,
cDLeft,
cDRight,
false,
true,
true);
ext3DimX = addLen;
ext4DimX = addLen + 1;
}
else
2017-05-18 17:51:35 +00:00
{
vtkm::cont::ErrorInternal("cDTemp Length not match!");
2017-05-18 17:51:35 +00:00
}
}
}
// decides the correct extension modes for cA and cD separately,
2017-02-19 04:14:20 +00:00
// and fill the extensions (2D matrices)
template <typename ArrayInType, typename ArrayOutType>
void IDWTHelper2DTopDown(const ArrayInType& coeffIn,
vtkm::Id inDimX,
vtkm::Id inDimY,
vtkm::Id inStartX,
vtkm::Id inStartY,
vtkm::Id inPretendDimX,
vtkm::Id inPretendDimY,
vtkm::Id cADimY,
vtkm::Id cDDimY,
ArrayOutType& ext1,
ArrayOutType& ext2, // output
ArrayOutType& ext3,
ArrayOutType& ext4, // output
vtkm::Id& ext1DimY,
vtkm::Id& ext2DimY, // output
vtkm::Id& ext3DimY,
vtkm::Id& ext4DimY, // output
vtkm::Id filterLen,
DWTMode mode)
{
VTKM_ASSERT(inPretendDimY == (cADimY + cDDimY));
// determine extension modes
2017-02-21 23:56:57 +00:00
DWTMode cATopMode, cADownMode, cDTopMode, cDDownMode;
cATopMode = cADownMode = cDTopMode = cDDownMode = mode;
2017-05-18 14:29:41 +00:00
if (mode == SYMH)
2017-05-22 20:47:13 +00:00
{
2017-02-21 23:56:57 +00:00
cDTopMode = ASYMH;
2017-05-18 14:29:41 +00:00
if (inPretendDimY % 2 != 0)
2017-05-22 20:47:13 +00:00
{
2017-02-21 23:56:57 +00:00
cADownMode = SYMW;
cDDownMode = ASYMW;
2017-05-22 20:47:13 +00:00
}
else
2017-05-18 17:51:35 +00:00
{
2017-02-21 23:56:57 +00:00
cDDownMode = ASYMH;
2017-05-18 17:51:35 +00:00
}
2017-05-22 20:47:13 +00:00
}
2017-05-18 14:29:41 +00:00
else // mode == SYMW
2017-05-22 20:47:13 +00:00
{
2017-02-21 23:56:57 +00:00
cDTopMode = SYMH;
2017-05-18 14:29:41 +00:00
if (inPretendDimY % 2 != 0)
2017-05-22 20:47:13 +00:00
{
2017-02-21 23:56:57 +00:00
cADownMode = SYMW;
cDDownMode = SYMH;
2017-05-22 20:47:13 +00:00
}
else
2017-05-18 17:51:35 +00:00
{
2017-02-21 23:56:57 +00:00
cADownMode = SYMH;
2017-05-18 17:51:35 +00:00
}
2017-05-22 20:47:13 +00:00
}
// determine length after extension
vtkm::Id cAExtendedDimY, cDExtendedDimY;
2017-05-18 14:29:41 +00:00
vtkm::Id cDPadLen = 0;
vtkm::Id addLen = filterLen / 4; // addLen == 0 for Haar kernel
if ((cADimY > cDDimY) && (mode == SYMH))
cDPadLen = cADimY;
cAExtendedDimY = cADimY + 2 * addLen;
cDExtendedDimY = cAExtendedDimY;
// extend cA
2017-05-18 14:29:41 +00:00
vtkm::Id cADimX = inPretendDimX;
this->Extend2D(coeffIn,
inDimX,
inDimY,
inStartX,
inStartY,
cADimX,
cADimY,
ext1,
ext2,
addLen,
cATopMode,
cADownMode,
false,
false,
false);
ext1DimY = ext2DimY = addLen;
// extend cD
2017-05-18 14:29:41 +00:00
vtkm::Id cDDimX = inPretendDimX;
if (cDPadLen > 0)
{
this->Extend2D(coeffIn,
inDimX,
inDimY,
inStartX,
inStartY + cADimY,
cDDimX,
cDDimY,
ext3,
ext4,
addLen,
cDTopMode,
cDDownMode,
true,
false,
false);
ext3DimY = addLen;
ext4DimY = addLen + 1;
}
else
{
vtkm::Id cDExtendedWouldBe = cDDimY + 2 * addLen;
2017-05-18 14:29:41 +00:00
if (cDExtendedWouldBe == cDExtendedDimY)
{
this->Extend2D(coeffIn,
inDimX,
inDimY,
inStartX,
inStartY + cADimY,
cDDimX,
cDDimY,
ext3,
ext4,
addLen,
cDTopMode,
cDDownMode,
false,
false,
false);
ext3DimY = ext4DimY = addLen;
}
2017-05-18 14:29:41 +00:00
else if (cDExtendedWouldBe == cDExtendedDimY - 1)
{
this->Extend2D(coeffIn,
inDimX,
inDimY,
inStartX,
inStartY + cADimY,
cDDimX,
cDDimY,
ext3,
ext4,
addLen,
cDTopMode,
cDDownMode,
false,
true,
false);
ext3DimY = addLen;
ext4DimY = addLen + 1;
}
else
2017-05-18 17:51:35 +00:00
{
vtkm::cont::ErrorInternal("cDTemp Length not match!");
2017-05-18 17:51:35 +00:00
}
}
}
2017-02-21 23:56:57 +00:00
// decides the correct extension modes for cA and cD separately,
// and fill the extensions (3D cubes)
template <typename ArrayInType, typename ArrayOutType>
void IDWTHelper3DLeftRight(const ArrayInType& coeffIn,
vtkm::Id inDimX,
vtkm::Id inDimY,
vtkm::Id inDimZ,
vtkm::Id inStartX,
vtkm::Id inStartY,
vtkm::Id inStartZ,
vtkm::Id inPretendDimX,
vtkm::Id inPretendDimY,
vtkm::Id inPretendDimZ,
vtkm::Id cADimX,
vtkm::Id cDDimX,
ArrayOutType& ext1,
ArrayOutType& ext2, // output
ArrayOutType& ext3,
ArrayOutType& ext4, // output
vtkm::Id& ext1DimX,
vtkm::Id& ext2DimX, // output
vtkm::Id& ext3DimX,
vtkm::Id& ext4DimX, // output
vtkm::Id filterLen,
DWTMode mode)
2017-02-21 23:56:57 +00:00
{
VTKM_ASSERT(inPretendDimX == (cADimX + cDDimX));
2017-02-21 23:56:57 +00:00
// determine extension modes
DWTMode cALeftMode, cARightMode, cDLeftMode, cDRightMode;
cALeftMode = cARightMode = cDLeftMode = cDRightMode = mode;
2017-05-18 14:29:41 +00:00
if (mode == SYMH)
2017-05-22 20:47:13 +00:00
{
2017-02-21 23:56:57 +00:00
cDLeftMode = ASYMH;
2017-05-18 14:29:41 +00:00
if (inPretendDimX % 2 != 0)
2017-05-22 20:47:13 +00:00
{
2017-02-21 23:56:57 +00:00
cARightMode = SYMW;
cDRightMode = ASYMW;
2017-05-22 20:47:13 +00:00
}
2017-02-21 23:56:57 +00:00
else
2017-05-18 17:51:35 +00:00
{
2017-02-21 23:56:57 +00:00
cDRightMode = ASYMH;
2017-05-18 17:51:35 +00:00
}
2017-05-22 20:47:13 +00:00
}
2017-05-18 14:29:41 +00:00
else // mode == SYMW
2017-05-22 20:47:13 +00:00
{
2017-02-21 23:56:57 +00:00
cDLeftMode = SYMH;
2017-05-18 14:29:41 +00:00
if (inPretendDimX % 2 != 0)
2017-05-22 20:47:13 +00:00
{
2017-02-21 23:56:57 +00:00
cARightMode = SYMW;
cDRightMode = SYMH;
2017-05-22 20:47:13 +00:00
}
2017-02-21 23:56:57 +00:00
else
2017-05-18 17:51:35 +00:00
{
2017-02-21 23:56:57 +00:00
cARightMode = SYMH;
2017-05-18 17:51:35 +00:00
}
2017-05-22 20:47:13 +00:00
}
2017-02-21 23:56:57 +00:00
// determine length after extension
vtkm::Id cAExtendedDimX, cDExtendedDimX;
2017-05-18 14:29:41 +00:00
vtkm::Id cDPadLen = 0;
vtkm::Id addLen = filterLen / 4; // addLen == 0 for Haar kernel
if ((cADimX > cDDimX) && (mode == SYMH))
2017-05-18 17:51:35 +00:00
{
2017-02-21 23:56:57 +00:00
cDPadLen = cADimX;
2017-05-18 17:51:35 +00:00
}
2017-02-21 23:56:57 +00:00
cAExtendedDimX = cADimX + 2 * addLen;
cDExtendedDimX = cAExtendedDimX;
// extend cA
vtkm::Id cADimY = inPretendDimY;
vtkm::Id cADimZ = inPretendDimZ;
this->Extend3DLeftRight(coeffIn,
inDimX,
inDimY,
inDimZ,
inStartX,
inStartY,
inStartZ,
cADimX,
cADimY,
cADimZ,
ext1,
ext2,
addLen,
cALeftMode,
cARightMode,
false,
false);
2017-02-21 23:56:57 +00:00
ext1DimX = ext2DimX = addLen;
// extend cD
vtkm::Id cDDimY = inPretendDimY;
vtkm::Id cDDimZ = inPretendDimZ;
bool pretendSigPaddedZero, padZeroAtExt2;
2017-05-18 14:29:41 +00:00
if (cDPadLen > 0)
2017-02-21 23:56:57 +00:00
{
ext3DimX = addLen;
ext4DimX = addLen + 1;
pretendSigPaddedZero = true;
2017-05-18 14:29:41 +00:00
padZeroAtExt2 = false;
2017-02-21 23:56:57 +00:00
}
else
{
vtkm::Id cDExtendedWouldBe = cDDimX + 2 * addLen;
2017-05-18 14:29:41 +00:00
if (cDExtendedWouldBe == cDExtendedDimX)
2017-02-21 23:56:57 +00:00
{
ext3DimX = ext4DimX = addLen;
pretendSigPaddedZero = false;
2017-05-18 14:29:41 +00:00
padZeroAtExt2 = false;
2017-02-21 23:56:57 +00:00
}
2017-05-18 14:29:41 +00:00
else if (cDExtendedWouldBe == cDExtendedDimX - 1)
2017-02-21 23:56:57 +00:00
{
ext3DimX = addLen;
ext4DimX = addLen + 1;
pretendSigPaddedZero = false;
2017-05-18 14:29:41 +00:00
padZeroAtExt2 = true;
2017-02-21 23:56:57 +00:00
}
else
{
2017-05-18 14:29:41 +00:00
pretendSigPaddedZero = padZeroAtExt2 = false; // so the compiler doesn't complain
2017-04-14 20:14:09 +00:00
vtkm::cont::ErrorInternal("cDTemp Length not match!");
}
2017-02-21 23:56:57 +00:00
}
this->Extend3DLeftRight(coeffIn,
inDimX,
inDimY,
inDimZ,
inStartX + cADimX,
inStartY,
inStartZ,
cDDimX,
cDDimY,
cDDimZ,
ext3,
ext4,
addLen,
cDLeftMode,
cDRightMode,
pretendSigPaddedZero,
padZeroAtExt2);
2017-02-21 23:56:57 +00:00
}
template <typename ArrayInType, typename ArrayOutType>
void IDWTHelper3DTopDown(const ArrayInType& coeffIn,
vtkm::Id inDimX,
vtkm::Id inDimY,
vtkm::Id inDimZ,
vtkm::Id inStartX,
vtkm::Id inStartY,
vtkm::Id inStartZ,
vtkm::Id inPretendDimX,
vtkm::Id inPretendDimY,
vtkm::Id inPretendDimZ,
vtkm::Id cADimY,
vtkm::Id cDDimY,
ArrayOutType& ext1,
ArrayOutType& ext2, // output
ArrayOutType& ext3,
ArrayOutType& ext4, // output
vtkm::Id& ext1DimY,
vtkm::Id& ext2DimY, // output
vtkm::Id& ext3DimY,
vtkm::Id& ext4DimY, // output
vtkm::Id filterLen,
DWTMode mode)
2017-02-21 23:56:57 +00:00
{
VTKM_ASSERT(inPretendDimY == (cADimY + cDDimY));
2017-02-21 23:56:57 +00:00
// determine extension modes
DWTMode cATopMode, cADownMode, cDTopMode, cDDownMode;
cATopMode = cADownMode = cDTopMode = cDDownMode = mode;
2017-05-18 14:29:41 +00:00
if (mode == SYMH)
2017-05-22 20:47:13 +00:00
{
2017-02-21 23:56:57 +00:00
cDTopMode = ASYMH;
2017-05-18 14:29:41 +00:00
if (inPretendDimY % 2 != 0)
2017-05-22 20:47:13 +00:00
{
2017-02-21 23:56:57 +00:00
cADownMode = SYMW;
cDDownMode = ASYMW;
2017-05-22 20:47:13 +00:00
}
2017-02-21 23:56:57 +00:00
else
2017-05-18 17:51:35 +00:00
{
2017-02-21 23:56:57 +00:00
cDDownMode = ASYMH;
2017-05-18 17:51:35 +00:00
}
2017-05-22 20:47:13 +00:00
}
2017-05-18 14:29:41 +00:00
else // mode == SYMW
2017-05-22 20:47:13 +00:00
{
2017-02-21 23:56:57 +00:00
cDTopMode = SYMH;
2017-05-18 14:29:41 +00:00
if (inPretendDimY % 2 != 0)
2017-05-22 20:47:13 +00:00
{
2017-02-21 23:56:57 +00:00
cADownMode = SYMW;
cDDownMode = SYMH;
2017-05-22 20:47:13 +00:00
}
2017-02-21 23:56:57 +00:00
else
2017-05-18 17:51:35 +00:00
{
2017-02-21 23:56:57 +00:00
cADownMode = SYMH;
2017-05-18 17:51:35 +00:00
}
2017-05-22 20:47:13 +00:00
}
2017-02-21 23:56:57 +00:00
// determine length after extension
vtkm::Id cAExtendedDimY, cDExtendedDimY;
2017-05-18 14:29:41 +00:00
vtkm::Id cDPadLen = 0;
vtkm::Id addLen = filterLen / 4; // addLen == 0 for Haar kernel
if ((cADimY > cDDimY) && (mode == SYMH))
2017-05-18 17:51:35 +00:00
{
2017-02-21 23:56:57 +00:00
cDPadLen = cADimY;
2017-05-18 17:51:35 +00:00
}
2017-02-21 23:56:57 +00:00
cAExtendedDimY = cADimY + 2 * addLen;
cDExtendedDimY = cAExtendedDimY;
// extend cA
vtkm::Id cADimX = inPretendDimX;
vtkm::Id cADimZ = inPretendDimZ;
this->Extend3DTopDown(coeffIn,
inDimX,
inDimY,
inDimZ,
inStartX,
inStartY,
inStartZ,
cADimX,
cADimY,
cADimZ,
ext1,
ext2,
addLen,
cATopMode,
cADownMode,
false,
false);
2017-02-21 23:56:57 +00:00
ext1DimY = ext2DimY = addLen;
// extend cD
vtkm::Id cDDimX = inPretendDimX;
vtkm::Id cDDimZ = inPretendDimZ;
bool pretendSigPaddedZero, padZeroAtExt2;
2017-05-18 14:29:41 +00:00
if (cDPadLen > 0)
2017-02-21 23:56:57 +00:00
{
ext3DimY = addLen;
ext4DimY = addLen + 1;
pretendSigPaddedZero = true;
2017-05-18 14:29:41 +00:00
padZeroAtExt2 = false;
2017-02-21 23:56:57 +00:00
}
else
{
vtkm::Id cDExtendedWouldBe = cDDimY + 2 * addLen;
2017-05-18 14:29:41 +00:00
if (cDExtendedWouldBe == cDExtendedDimY)
2017-02-21 23:56:57 +00:00
{
ext3DimY = ext4DimY = addLen;
pretendSigPaddedZero = false;
2017-05-18 14:29:41 +00:00
padZeroAtExt2 = false;
2017-02-21 23:56:57 +00:00
}
2017-05-18 14:29:41 +00:00
else if (cDExtendedWouldBe == cDExtendedDimY - 1)
2017-02-21 23:56:57 +00:00
{
ext3DimY = addLen;
ext4DimY = addLen + 1;
pretendSigPaddedZero = false;
2017-05-18 14:29:41 +00:00
padZeroAtExt2 = true;
2017-02-21 23:56:57 +00:00
}
else
{
2017-05-18 14:29:41 +00:00
pretendSigPaddedZero = padZeroAtExt2 = false; // so the compiler doesn't complain
2017-04-14 20:14:09 +00:00
vtkm::cont::ErrorInternal("cDTemp Length not match!");
}
2017-02-21 23:56:57 +00:00
}
this->Extend3DTopDown(coeffIn,
inDimX,
inDimY,
inDimZ,
inStartX,
inStartY + cADimY,
inStartZ,
cDDimX,
cDDimY,
cDDimZ,
ext3,
ext4,
addLen,
cDTopMode,
cDDownMode,
pretendSigPaddedZero,
padZeroAtExt2);
2017-02-21 23:56:57 +00:00
}
template <typename ArrayInType, typename ArrayOutType>
void IDWTHelper3DFrontBack(const ArrayInType& coeffIn,
vtkm::Id inDimX,
vtkm::Id inDimY,
vtkm::Id inDimZ,
vtkm::Id inStartX,
vtkm::Id inStartY,
vtkm::Id inStartZ,
vtkm::Id inPretendDimX,
vtkm::Id inPretendDimY,
vtkm::Id inPretendDimZ,
vtkm::Id cADimZ,
vtkm::Id cDDimZ,
ArrayOutType& ext1,
ArrayOutType& ext2, // output
ArrayOutType& ext3,
ArrayOutType& ext4, // output
vtkm::Id& ext1DimZ,
vtkm::Id& ext2DimZ, // output
vtkm::Id& ext3DimZ,
vtkm::Id& ext4DimZ, // output
vtkm::Id filterLen,
DWTMode mode)
2017-02-21 23:56:57 +00:00
{
VTKM_ASSERT(inPretendDimZ == (cADimZ + cDDimZ));
2017-02-21 23:56:57 +00:00
// determine extension modes
DWTMode cAFrontMode, cABackMode, cDFrontMode, cDBackMode;
cAFrontMode = cABackMode = cDFrontMode = cDBackMode = mode;
2017-05-18 14:29:41 +00:00
if (mode == SYMH)
2017-05-22 20:47:13 +00:00
{
2017-02-21 23:56:57 +00:00
cDFrontMode = ASYMH;
2017-05-18 14:29:41 +00:00
if (inPretendDimZ % 2 != 0)
2017-05-22 20:47:13 +00:00
{
2017-02-21 23:56:57 +00:00
cABackMode = SYMW;
cDBackMode = ASYMW;
2017-05-22 20:47:13 +00:00
}
2017-02-21 23:56:57 +00:00
else
2017-05-18 17:51:35 +00:00
{
2017-02-21 23:56:57 +00:00
cDBackMode = ASYMH;
2017-05-18 17:51:35 +00:00
}
2017-05-22 20:47:13 +00:00
}
2017-05-18 14:29:41 +00:00
else // mode == SYMW
2017-05-22 20:47:13 +00:00
{
2017-02-21 23:56:57 +00:00
cDFrontMode = SYMH;
2017-05-18 14:29:41 +00:00
if (inPretendDimZ % 2 != 0)
2017-05-22 20:47:13 +00:00
{
2017-02-21 23:56:57 +00:00
cABackMode = SYMW;
cDBackMode = SYMH;
2017-05-22 20:47:13 +00:00
}
2017-02-21 23:56:57 +00:00
else
2017-05-18 17:51:35 +00:00
{
2017-02-21 23:56:57 +00:00
cABackMode = SYMH;
2017-05-18 17:51:35 +00:00
}
2017-05-22 20:47:13 +00:00
}
2017-02-21 23:56:57 +00:00
// determine length after extension
vtkm::Id cAExtendedDimZ, cDExtendedDimZ;
2017-05-18 14:29:41 +00:00
vtkm::Id cDPadLen = 0;
vtkm::Id addLen = filterLen / 4; // addLen == 0 for Haar kernel
if ((cADimZ > cDDimZ) && (mode == SYMH))
2017-05-18 17:51:35 +00:00
{
2017-02-21 23:56:57 +00:00
cDPadLen = cADimZ;
2017-05-18 17:51:35 +00:00
}
2017-02-21 23:56:57 +00:00
cAExtendedDimZ = cADimZ + 2 * addLen;
cDExtendedDimZ = cAExtendedDimZ;
// extend cA
vtkm::Id cADimX = inPretendDimX;
vtkm::Id cADimY = inPretendDimY;
this->Extend3DFrontBack(coeffIn,
inDimX,
inDimY,
inDimZ,
inStartX,
inStartY,
inStartZ,
cADimX,
cADimY,
cADimZ,
ext1,
ext2,
addLen,
cAFrontMode,
cABackMode,
false,
false);
2017-02-21 23:56:57 +00:00
ext1DimZ = ext2DimZ = addLen;
// extend cD
vtkm::Id cDDimX = inPretendDimX;
vtkm::Id cDDimY = inPretendDimY;
bool pretendSigPaddedZero, padZeroAtExt2;
2017-05-18 14:29:41 +00:00
if (cDPadLen > 0)
2017-02-21 23:56:57 +00:00
{
ext3DimZ = addLen;
ext4DimZ = addLen + 1;
pretendSigPaddedZero = true;
2017-05-18 14:29:41 +00:00
padZeroAtExt2 = false;
2017-02-21 23:56:57 +00:00
}
else
{
vtkm::Id cDExtendedWouldBe = cDDimZ + 2 * addLen;
2017-05-18 14:29:41 +00:00
if (cDExtendedWouldBe == cDExtendedDimZ)
2017-02-21 23:56:57 +00:00
{
ext3DimZ = ext4DimZ = addLen;
pretendSigPaddedZero = false;
2017-05-18 14:29:41 +00:00
padZeroAtExt2 = false;
2017-02-21 23:56:57 +00:00
}
2017-05-18 14:29:41 +00:00
else if (cDExtendedWouldBe == cDExtendedDimZ - 1)
2017-02-21 23:56:57 +00:00
{
ext3DimZ = addLen;
ext4DimZ = addLen + 1;
pretendSigPaddedZero = false;
2017-05-18 14:29:41 +00:00
padZeroAtExt2 = true;
2017-02-21 23:56:57 +00:00
}
else
{
2017-05-18 14:29:41 +00:00
pretendSigPaddedZero = padZeroAtExt2 = false; // so the compiler doesn't complain
2017-04-14 20:14:09 +00:00
vtkm::cont::ErrorInternal("cDTemp Length not match!");
}
2017-02-21 23:56:57 +00:00
}
this->Extend3DFrontBack(coeffIn,
inDimX,
inDimY,
inDimZ,
inStartX,
inStartY,
inStartZ + cADimZ,
cDDimX,
cDDimY,
cDDimZ,
ext3,
ext4,
addLen,
cDFrontMode,
cDBackMode,
pretendSigPaddedZero,
padZeroAtExt2);
2017-02-21 23:56:57 +00:00
}
2017-05-22 20:47:13 +00:00
};
2017-05-18 14:29:41 +00:00
} // namespace wavelets
} // namespace worklet
} // namespace vtkm
2017-05-22 20:47:13 +00:00
#endif