00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef WAVELETDECOMP_H
00019 #define WAVELETDECOMP_H
00020
00021 #include <cassert>
00022 #include <iostream>
00023 #include <blitz/array.h>
00024
00025 #include "Wavelet.h"
00026
00027 namespace bwave {
00028
00029
00035
00036 enum DecompType {
00037 STD_DECOMP=0,
00038 NONSTD_DECOMP=1
00039 };
00040
00041
00057
00058 enum CoeffStorage {
00059 NESTED_COEFFS=0,
00060 SEPARATED_COEFFS=1
00061 };
00062
00063
00071
00072 template<int tp_rank> class WaveletDecomp {
00073 protected:
00074 Wavelet m_wavelet;
00075 DecompType m_decomp;
00076 CoeffStorage m_storageMode;
00077 ExtensionMode m_extMode;
00078 int m_maxLevel;
00079 blitz::TinyVector<bool, tp_rank> m_dimSelect;
00080
00081 template<class tp_Type> inline void trafoStep
00082 (blitz::Array<tp_Type,tp_rank> &data, int targetDim, bool inverse) const;
00083
00084 template<class tp_Type> inline blitz::TinyVector<int, tp_rank> waveletDecompose
00085 (blitz::Array<tp_Type,tp_rank> &data, int maxlevel=0) const;
00086
00087 template<class tp_Type> inline blitz::TinyVector<int, tp_rank> waveletRecompose
00088 (blitz::Array<tp_Type,tp_rank> &data, int maxlevel=0) const;
00089
00090 public:
00092 Wavelet wavelet() const { return m_wavelet; }
00093
00096 DecompType decompType() const { return m_decomp; }
00097
00101 CoeffStorage storageMode() const { return m_storageMode; }
00102
00110 CoeffStorage storageMode(CoeffStorage newCS)
00111 { return m_storageMode=newCS; }
00112
00116 ExtensionMode extensionMode() const { return m_extMode; }
00117
00122 ExtensionMode extensionMode(ExtensionMode newEM)
00123 { return m_extMode=newEM; }
00124
00126 bool dimSelected(int dim) const { return m_dimSelect(dim); }
00127
00130 blitz::TinyVector<bool, tp_rank> dimSelection() const { return m_dimSelect; }
00131
00138 blitz::TinyVector<bool, tp_rank> dimSelection(blitz::TinyVector<bool, tp_rank> selection)
00139 { return m_dimSelect = selection; }
00140
00152 template<class tp_Type> inline blitz::TinyVector<int, tp_rank> apply
00153 (blitz::Array<tp_Type,tp_rank> &data) const
00154 {
00155 assert(storageMode()==NESTED_COEFFS);
00156 return waveletDecompose(data, m_maxLevel);
00157 }
00158
00168 template<class tp_Type> inline blitz::TinyVector<int, tp_rank> applyInv
00169 (blitz::Array<tp_Type,tp_rank> &data) const
00170 {
00171 assert(storageMode()==NESTED_COEFFS);
00172 return waveletRecompose(data, m_maxLevel);
00173 }
00174
00175
00190 template<class tp_Type>
00191 blitz::Array< blitz::TinyVector<int, tp_rank>, 1> indices(
00192 blitz::Array<tp_Type,tp_rank> &data) const;
00193
00229 template<class tp_Type>
00230 blitz::Array<tp_Type,tp_rank> coeffs(blitz::Array<tp_Type,tp_rank> &data,
00231 blitz::TinyVector<int, tp_rank> indices) const;
00232
00240 double normFactor(blitz::TinyVector<int, tp_rank> indices) const {
00241 blitz::TinyVector<double, 2> baseNF(wavelet().normS(), wavelet().normD());
00242 double norm=1;
00243 for (int i=0; i<tp_rank; ++i) {
00244 norm *= indices(i)>=0 ? pow(baseNF(0), indices(i))
00245 : pow(baseNF(0), -indices(i)-1) * baseNF(1);
00246 }
00247 return norm;
00248 }
00249
00250
00263 WaveletDecomp(Wavelet wl, DecompType decomp=NONSTD_DECOMP,
00264 int maxlevel=0, CoeffStorage cs=NESTED_COEFFS, ExtensionMode em=CONSTANT_EXT)
00265 : m_wavelet(wl), m_decomp(decomp), m_storageMode(cs), m_extMode(em),
00266 m_maxLevel(maxlevel)
00267 { m_dimSelect = true; }
00268 };
00269
00270
00271 template<int tp_rank> template<class tp_Type>
00272 inline void WaveletDecomp<tp_rank>::trafoStep
00273 (blitz::Array<tp_Type,tp_rank> &data, int targetDim, bool inverse) const
00274 {
00275 using namespace blitz;
00276 assert( targetDim < tp_rank );
00277 TinyVector<int, tp_rank> stride=1, lboundS=data.lbound(), lboundD=data.lbound();
00278 stride(targetDim)=2;
00279 lboundD(targetDim)+=1;
00280
00281 TinyVector<int, tp_rank> uboundS, uboundD;
00282 for (int dim=0; dim<tp_rank; ++dim) {
00283 uboundS(dim) = lboundS(dim) + (data.ubound()(dim)-lboundS(dim)) / stride(dim) * stride(dim);
00284 uboundD(dim) = lboundD(dim) + (data.ubound()(dim)-lboundD(dim)) / stride(dim) * stride(dim);
00285 }
00286
00287 StridedDomain<tp_rank> subsetS(lboundS, uboundS, stride);
00288 StridedDomain<tp_rank> subsetD(lboundD, uboundD, stride);
00289 blitz::Array<tp_Type,tp_rank> s( data(subsetS) );
00290 blitz::Array<tp_Type,tp_rank> d( data(subsetD) );
00291
00292 int n = data.size() / data.extent(targetDim);
00293
00294 TinyVector<int, tp_rank> position = data.lbound();
00295 int lastDim = targetDim!=tp_rank-1 ? tp_rank-1 : tp_rank-2;
00296
00297 for (int i=0; i<n; ++i) {
00298 Array<tp_Type, 1> sliceS( slice(s, targetDim, position) );
00299 Array<tp_Type, 1> sliceD( slice(d, targetDim, position) );
00300 if (!inverse) m_wavelet.lift(sliceS, sliceD, m_extMode);
00301 else m_wavelet.invLift(sliceS, sliceD, m_extMode);
00302
00303 if (i < n-1) {
00304 position(lastDim) += 1;
00305 for (int d=lastDim; d>0; --d) {
00306 if ( (d!=targetDim) && (position(d)>data.ubound(d)) ) {
00307 position(d)=data.lbound(d);
00308 ++position(targetDim!=d-1 ? d-1 : d-2);
00309 }
00310 }
00311 }
00312 }
00313
00314 }
00315
00316
00317 template<int tp_rank> template<class tp_Type>
00318 inline blitz::TinyVector<int, tp_rank>
00319 WaveletDecomp<tp_rank>::waveletDecompose
00320 (blitz::Array<tp_Type,tp_rank> &data, int maxlevel) const
00321 {
00322 using namespace blitz;
00323
00324 TinyVector<int, tp_rank> depth=0;
00325
00326 switch (decompType()) {
00327 case STD_DECOMP: assert(false); break;
00328 case NONSTD_DECOMP: {
00329 for (int dim=0; dim<tp_rank; ++dim)
00330 if ( (data.extent(dim)>1) && dimSelected(dim) ) {
00331 trafoStep(data, dim, false);
00332 depth(dim) += 1;
00333 }
00334
00335 bool descend = false;
00336 for (int dim=0; dim<tp_rank; ++dim)
00337 if ((data.extent(dim)>2) && dimSelected(dim)) descend = true;
00338
00339 if ( descend && ((maxlevel==0) || (maxlevel>1)) ) {
00340 TinyVector<int, tp_rank> stride, lbound, ubound;
00341 for (int dim=0; dim<tp_rank; ++dim) {
00342 stride(dim) = dimSelected(dim) ? 2 : 1;
00343 lbound(dim) = data.lbound()(dim);
00344 ubound(dim) = lbound(dim) + (data.ubound()(dim)-lbound(dim)) / stride(dim) * stride(dim);
00345 }
00346 StridedDomain<tp_rank> subsetS(lbound, ubound, stride);
00347 blitz::Array<tp_Type,tp_rank> sub(data(subsetS));
00348
00349 depth += waveletDecompose(sub, maxlevel>0 ? maxlevel-1 : 0);
00350 }
00351
00352 break;
00353 }
00354 default: assert(false);
00355 }
00356
00357 return depth;
00358 }
00359
00360
00361 template<int tp_rank> template<class tp_Type>
00362 inline blitz::TinyVector<int, tp_rank>
00363 WaveletDecomp<tp_rank>::waveletRecompose
00364 (blitz::Array<tp_Type,tp_rank> &data, int maxlevel) const
00365 {
00366 using namespace blitz;
00367
00368 TinyVector<int, tp_rank> depth=0;
00369
00370 switch (decompType()) {
00371 case STD_DECOMP: assert(false); break;
00372 case NONSTD_DECOMP: {
00373 bool descend = false;
00374 for (int dim=0; dim<tp_rank; ++dim)
00375 if ((data.extent(dim)>2) && dimSelected(dim)) descend = true;
00376
00377 if ( descend && ((maxlevel==0) || (maxlevel>1)) ) {
00378 TinyVector<int, tp_rank> stride, lbound, ubound;
00379 for (int dim=0; dim<tp_rank; ++dim) {
00380 stride(dim) = dimSelected(dim) ? 2 : 1;
00381 lbound(dim) = data.lbound()(dim);
00382 ubound(dim) = lbound(dim) + (data.ubound()(dim)-lbound(dim)) / stride(dim) * stride(dim);
00383 }
00384 StridedDomain<tp_rank> subsetS(lbound, ubound, stride);
00385 blitz::Array<tp_Type,tp_rank> sub(data(subsetS));
00386
00387 depth += waveletRecompose(sub, maxlevel>0 ? maxlevel-1 : 0);
00388 }
00389
00390 for (int dim=tp_rank-1; dim>=0; --dim)
00391 if ( (data.extent(dim)>1) && dimSelected(dim) ) {
00392 trafoStep(data, dim, true);
00393 depth(dim) -= 1;
00394 }
00395
00396 break;
00397 }
00398 default: assert(false);
00399 }
00400
00401 return depth;
00402 }
00403
00404
00405 template<int tp_rank> template<class tp_Type>
00406 blitz::Array< blitz::TinyVector<int, tp_rank>, 1>
00407 WaveletDecomp<tp_rank>::indices(
00408 blitz::Array<tp_Type,tp_rank> &data) const
00409 {
00410 using namespace blitz;
00411 TinyVector<int, tp_rank> decompDepth;
00412 Array< TinyVector<int, tp_rank>, 1> idx;
00413
00414 for (int dim=0; dim<tp_rank; ++dim) {
00415
00416 int val = (int) ceil(log((double)data.extent(dim)-0.1) / log(2.0));
00417 decompDepth(dim) = dimSelected(dim) ?
00418 (m_maxLevel>0 ? min(m_maxLevel, val) : val) : 0;
00419 }
00420
00421 switch (decompType()) {
00422 case STD_DECOMP: assert(false); break;
00423 case NONSTD_DECOMP: {
00424 int maxLevel = max(decompDepth);
00425 idx.resize(max(1, maxLevel*(1<<tp_rank)));
00426 idx(0) = 0;
00427 int begin=0, end=0;
00428 for (int level=1; level<=maxLevel; ++level) {
00429 for (int dim=0; dim<tp_rank; ++dim)
00430 if (decompDepth(dim)>=level)
00431 {
00432 int offset = end-begin+1;
00433 for (int i=begin; i<=end; ++i) {
00434 idx(i+offset) = idx(i);
00435 idx(i)(dim) = -level;
00436 idx(i+offset)(dim) = level;
00437 }
00438 end += offset;
00439 }
00440 begin = end;
00441 }
00442 idx.resizeAndPreserve(end+1);
00443 break;
00444 }
00445 default: assert(false);
00446 }
00447 return idx;
00448 }
00449
00450
00451 template<int tp_rank> template<class tp_Type>
00452 blitz::Array<tp_Type,tp_rank> WaveletDecomp<tp_rank>::coeffs(
00453 blitz::Array<tp_Type,tp_rank> &data,
00454 blitz::TinyVector<int, tp_rank> indices) const
00455 {
00456 using namespace blitz;
00457
00458 Array<tp_Type,tp_rank> c;
00459 TinyVector<int, tp_rank> ubound, lbound, stride;
00460
00461 for (int dim=0; dim<tp_rank; ++dim) {
00462 int i = indices(dim);
00463
00464
00465 int n = data.extent(dim);
00466
00467 if (storageMode()==NESTED_COEFFS) {
00468
00469
00470
00471 stride(dim) = i>=0 ? 1 << i : 1 << -i;
00472 lbound(dim) = data.lbound()(dim) + ( i>=0 ? 0 : 1 << (-i-1) );
00473 ubound(dim) = lbound(dim) + (data.ubound()(dim)-lbound(dim)) / stride(dim) * stride(dim);
00474 } else if (storageMode()==SEPARATED_COEFFS) {
00475
00476
00477
00478
00479 stride(dim) = 1;
00480 lbound(dim) = data.lbound()(dim) + ( i>=0 ? 0 : (n + (1<<-i) - 1) >> -i );
00481 ubound(dim) = data.lbound()(dim) + ( i>=0 ? ( (n + (1<<i) - 1) >> i) - 1
00482 : ( (n + (1<<(-i-1)) - 1) >> (-i-1) ) - 1 );
00483 } else assert(false);
00484
00485 assert( lbound(dim) <= ubound(dim));
00486 assert( lbound(dim) >= data.lbound(dim));
00487 assert( ubound(dim) <= data.ubound(dim));
00488 }
00489
00490 StridedDomain<tp_rank> subset(lbound, ubound, stride);
00491 c.reference(data(subset));
00492
00493 return c;
00494 }
00495
00496
00497 }
00498
00499 #endif