/home/pclz-02/oschulz/Data/Science/Projects/Gerda/Software/blitzwave/src/Wavelet.h
00001 // Copyright (C) 2003-2008 Oliver Schulz <oliver.schulz@tu-dortmund.de>
00002 
00003 // This program is free software; you can redistribute it and/or modify
00004 // it under the terms of the GNU General Public License as published by
00005 // the Free Software Foundation; either version 2 of the License, or
00006 // (at your option) any later version.
00007 //
00008 // This program is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011 // GNU General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU General Public License
00014 // along with this program; if not, write to the Free Software
00015 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00016 
00017 
00018 #ifndef WAVELET_H
00019 #define WAVELET_H
00020 
00021 #include <cassert>
00022 #include <cmath>
00023 #include <limits>
00024 #include <vector>
00025 #include <string>
00026 #include <iostream>
00027 #include <blitz/array.h>
00028 
00029 #include "arrayTools.h"
00030 
00031 namespace bwave {
00032 
00033 
00041 
00042 class Wavelet {
00043 public:
00046         static bool equals(double x, double y);
00047 
00048 public:
00051 
00052         class WaveletComponent {
00053         public:
00054                 virtual ~WaveletComponent() { }
00055         };
00056 
00074 
00075         class LiftingStep : public WaveletComponent {
00076         public:
00078                 enum Type { PRIMAL, DUAL, SSCALE, DSCALE };
00079 
00080         protected:
00081                 Type m_type;
00082                 int m_origin;
00083                 std::vector<double> m_coeffs;
00084                 double m_divisor;
00085 
00086                 template<class tp_Type, int tp_size> inline void applyFS
00087                         (blitz::Array<tp_Type, 1> &s, blitz::Array<tp_Type, 1> &d, bool inverse, ExtensionMode be) const;
00088 
00089         public:
00093                 Type type() const { return m_type; }
00094 
00098                 int origin() const { return m_origin; }
00099 
00102                 int size() const { return int(m_coeffs.size()); }
00103 
00107                 double coeff(int i) const { return m_coeffs[i]; }
00108 
00111                 double divisor() const { return m_divisor; }
00112                 
00118                 template<class tp_Type> inline void apply
00119                         (blitz::Array<tp_Type, 1> &s, blitz::Array<tp_Type, 1> &d, bool inverse, ExtensionMode be=CONSTANT_EXT) const;
00120 
00122                 LiftingStep () {}
00123 
00133                 LiftingStep (Type t, int o, double d, double c0);
00135                 LiftingStep (Type t, int o, double d, double c0, double c1);
00137                 LiftingStep (Type t, int o, double d, double c0, double c1, double c2);
00139                 LiftingStep (Type t, int o, double d, double c0, double c1, double c2, double c3);
00141                 LiftingStep (Type t, int o, double d, double c0, double c1, double c2, double c3, double c4);
00143                 LiftingStep (Type t, int o, double d, double c0, double c1, double c2, double c3, double c4, double c5);
00144                 
00149                 bool operator==(const LiftingStep &s) const;
00150                 
00152                 virtual ~LiftingStep() {}
00153         };
00154 
00155 protected:
00156         std::string m_spec;
00157         double m_nS, m_nD;
00158         std::vector<LiftingStep> m_steps;
00159 
00160 public:
00162         const std::string& name() const { return m_spec; }
00163 
00174         bool integerCompatible() const;
00175 
00180         bool normalized() const;
00181 
00183         int steps() const { return int(m_steps.size()); }
00184 
00187         const LiftingStep& liftingStep(int i) const { return m_steps[i]; }
00188 
00193         double normS() const { return m_nS; }
00194 
00197         double normD() const { return m_nD; }
00198 
00202         bool operator==(const Wavelet &w) const;
00203 
00210         template<class tp_Type> void lift( blitz::Array<tp_Type, 1> &s,
00211                 blitz::Array<tp_Type, 1> &d, ExtensionMode be=CONSTANT_EXT) const;
00212 
00217         template<class tp_Type> void invLift( blitz::Array<tp_Type, 1> &s,
00218                 blitz::Array<tp_Type, 1> &d, ExtensionMode be=CONSTANT_EXT) const;
00219 
00220                 
00231         blitz::Array<double, 1> forwardFkt(unsigned int size = 1<<9, int scale = 6,
00232                 unsigned int trans = 3) const;
00233                                                                   
00237         blitz::Array<double, 1> inverseFkt(unsigned int size = 1<<9, int scale = 6,
00238                 unsigned int trans = 3) const;
00239                                                                   
00241         Wavelet() {}
00242 
00252         Wavelet(const std::string &name, double ns, double nd, const LiftingStep &s0, const LiftingStep &s1);
00254         Wavelet(const std::string &name, double ns, double nd, const LiftingStep &s0, const LiftingStep &s1, const LiftingStep &s2);
00256         Wavelet(const std::string &name, double ns, double nd, const LiftingStep &s0, const LiftingStep &s1, const LiftingStep &s2, const LiftingStep &s3);
00257 
00258         virtual ~Wavelet() {}
00259 };
00260 
00261 
00265 std::ostream & operator<<(std::ostream &os, const Wavelet::LiftingStep &s);
00266 
00270 std::ostream & operator<<(std::ostream &os, const Wavelet &w);
00271 
00272 
00275 extern const Wavelet WL_CDF_1_1;
00276 
00281 extern const Wavelet WL_CDF_2_2;
00282 
00284 extern const Wavelet WL_CDF_3_1;
00285 
00287 extern const Wavelet WL_CDF_3_3;
00288 
00290 extern const Wavelet WL_CDF_4_2;
00291 
00296 extern const Wavelet WL_CDF_97;
00297 
00299 extern const Wavelet WL_HAAR;
00300 
00304 extern const Wavelet WL_LEG_5_3;
00305 
00311 extern const Wavelet WL_CUBIC_SPLINE;
00312 
00314 extern const Wavelet WL_D_4;
00315 
00316 
00317 template<class tp_Type, int tp_size> void Wavelet::LiftingStep::applyFS
00318         (blitz::Array<tp_Type, 1> &s, blitz::Array<tp_Type, 1> &d, bool inverse, ExtensionMode be) const
00319 {
00320         assert(size() == tp_size);
00321         tp_Type coeffs[tp_size];
00322         for (int i=0; i<size(); ++i) coeffs[i] = (tp_Type) coeff(i);
00323         GenFilter<tp_Type, tp_size> liftFilter(origin(), coeffs, (tp_Type) divisor());
00324                 
00325         if (type() == PRIMAL) {
00326                 if (!inverse) liftFilter.applyAdd(d, s, be);
00327                 else liftFilter.applySub(d, s, be);
00328         } else if (type() == DUAL) {
00329                 if (!inverse) liftFilter.applyAdd(s, d, be);
00330                 else liftFilter.applySub(s, d, be);
00331         } else if (type() == SSCALE) {
00332                 if (!inverse) {
00333                         s *= tp_Type(coeff(0));
00334                         if (divisor()!=1.) s /= tp_Type(divisor()); 
00335                 }
00336                 else {
00337                         if (divisor()!=1.) s *= tp_Type(divisor()); 
00338                         s /= tp_Type(coeff(0));
00339                 }
00340         } else if (type() == DSCALE) {
00341                 if (!inverse) {
00342                         d *= tp_Type(coeff(0));
00343                         if (divisor()!=1.) d /= tp_Type(divisor()); 
00344                 }
00345                 else {
00346                         if (divisor()!=1.) d *= tp_Type(divisor()); 
00347                         d /= tp_Type(coeff(0));
00348                 }
00349         } else {
00350                 assert(false);
00351         }
00352 }
00353 
00354 
00355 template<class tp_Type> void Wavelet::LiftingStep::apply
00356         (blitz::Array<tp_Type, 1> &s, blitz::Array<tp_Type, 1> &d, bool inverse, ExtensionMode be) const
00357 {
00358         switch(size()) {
00359                 case 1: applyFS<tp_Type, 1>(s, d, inverse, be); break;
00360                 case 2: applyFS<tp_Type, 2>(s, d, inverse, be); break;
00361                 case 3: applyFS<tp_Type, 3>(s, d, inverse, be); break;
00362                 //case 4: applyFS<tp_Type, 4>(s, d, inverse, be); break;
00363                 //case 5: applyFS<tp_Type, 5>(s, d, inverse, be); break;
00364                 //case 6: applyFS<tp_Type, 6>(s, d, inverse, be); break;
00365                 default: assert(false);
00366         }
00367 }
00368 
00369 
00370 template<class tp_Type> void Wavelet::lift( blitz::Array<tp_Type, 1> &s,
00371         blitz::Array<tp_Type, 1> &d, ExtensionMode be) const
00372 {
00373         for (int step=0; step<steps(); ++step)
00374                 liftingStep(step).apply(s, d, false, be);
00375 }
00376 
00377 
00378 template<class tp_Type> void Wavelet::invLift( blitz::Array<tp_Type, 1> &s,
00379         blitz::Array<tp_Type, 1> &d, ExtensionMode be) const
00380 {
00381         for (int step=steps()-1; step>=0; --step)
00382                 liftingStep(step).apply(s, d, true, be);
00383 }
00384 
00385 
00386 } // namespace bwave
00387 
00388 #endif