Logo coherent WaveBurst  
Library Reference Guide
Logo
WaveDWT.cc
Go to the documentation of this file.
1 /*
2 # Copyright (C) 2019 Sergey Klimenko
3 #
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17 
18 
19 // $Id: WaveDWT.cc,v 1.6 2002/06/27 06:30:43 klimenko Exp $
20 
21 #define WAVEDWT_CC
22 
23 #include <strstream>
24 #include <stdexcept>
25 #include "WaveDWT.hh"
26 
27 //namespace datacondAPI {
28 //namespace wat {
29 
30 ClassImp(WaveDWT<double>)
31 
32 using namespace std;
33 
34 // constructors
35 
36 template<class DataType_t>
38 WaveDWT(int mH,int mL,int tree, enum BORDER border) :
39 Wavelet(mH, mL, tree, border), pWWS(NULL), nWWS(0), nSTS(0)
40 { }
41 
42 template<class DataType_t>
44 Wavelet(w), pWWS(NULL), nWWS(0), nSTS(0)
45 {
46  std::cout<<" I am WaveDWT Clone: "<<endl;
47 }
48 
49 template<class DataType_t>
51 Wavelet(w), pWWS(NULL), nWWS(0)
52 {
53  this->nSTS = w.nSTS;
54 }
55 
56 // destructor
57 template<class DataType_t>
59 {
60  release();
61 }
62 
63 template<class DataType_t>
65 {
66  return new WaveDWT<DataType_t>(*this);
67 }
68 
69 // - Virtual procedure for forward wavelet transform.
70 // - Real code for decompose will appear in a derivative
71 // classe, since it depends of the wavelet type.
72 // - Only ldeep steps of decomposition will be done.
73 // - By default ldeep=1, which means do one step.
74 template<class DataType_t>
75 void WaveDWT<DataType_t>::t2w(int ldeep)
76 {
77  int maxLevel = getMaxLevel();
78 
79  int levs = m_Level;
80  int levf = m_Level+ldeep;
81  if((ldeep == -1) || (levf > maxLevel)) levf = maxLevel;
82 
83  int layf;
84  for(int level=levs; level<levf; level++)
85  {
86  layf = (m_TreeType) ? 1<<level : 1;
87 
88  for(int layer=0; layer<layf; layer++)
89  forward(level,layer);
90 
91  m_Level=level+1;
92 
93  }
94 
95  m_Level = levf;
96  m_Layer = (m_TreeType) ? (1<<m_Level)-1 : m_Level;
97 
98 }
99 
100 // - Virtual procedure for inverse wavelet transform.
101 // - Real code for reconstruct will appear in a derivative
102 // classe, since it depends of the type of wavelet.
103 // - Only ldeep steps of reconstruction will be done.
104 // - By default ldeep=1, which means do one step.
105 template<class DataType_t>
107 {
108  int levs = m_Level;
109  int levf = m_Level-ldeep;
110  if((ldeep == -1) || (levf < 0)) levf = 0;
111 
112  int layf;
113  for(int level=levs-1; level>=levf; level--)
114  {
115  layf = (m_TreeType) ? 1<<level : 1;
116 
117  for(int layer=0; layer<layf; layer++)
118  inverse(level,layer);
119 
120  m_Level=level;
121 
122  }
123  m_Level=levf;
124 }
125 
126 
127 // access function
128 template<class DataType_t>
130 {
131 // convert layer index or frequency index to slice
132 // input parameter is the layer number. In general the layer number
133 // is integer, but double is used to distinguish between o and 90 phase
134 // zero layers in WDM: they are accessed as getLayer(+-0.x)
135  int level = m_Level;
136  int layer = int(fabs(index)+0.001); // convert to int
137 
138  int maxlayer = (BinaryTree()) ? (1<<level)-1 : level;
139 
140  if(layer > maxlayer){
141  layer = maxlayer;
142 
143  std::ostrstream oss;
144  oss << "WaveDWT::getSlice(): "
145  << "argument "<<index<<" is set to " << layer << endl;
146 
147  std::invalid_argument exception(oss.str());
148  oss.freeze(0);
149  throw exception;
150  }
151 
152  if(BinaryTree()){
153  layer = convertF2L(level,layer);
154  }
155  else {
156 
157  if(layer) { // detail layers
158  level -= layer-1;
159  layer = 1;
160  }
161  else{ // approximation layer
162  layer = 0;
163  }
164  }
165 
166  return getSlice(level,layer);
167 }
168 
169 // convert (level,layer) to slice
170 template<class DataType_t>
171 slice WaveDWT<DataType_t>::getSlice(const int level, const int layer)
172 {
173  if(!allocate()){
174  std::invalid_argument("WaveDWT::getSlice(): data is not allocated");
175  return slice(0,1,1);
176  }
177 
178  size_t m = nWWS>>level; // number of elements
179  size_t s = 1<<level; // slice step
180  size_t i = getOffset(level,layer); // first element
181 
182  if(i+(m-1)*s+1 > nWWS){
183  std::invalid_argument("WaveDWT::getSlice(): invalide arguments");
184  return slice(0,1,1);
185  }
186 
187  return slice(i,m,s);
188 }
189 
190 
191 // Calculate maximal level of wavelet decomposition,
192 // which depends on the length of wavelet filters.
193 template<class DataType_t>
195 {
196  if(!allocate()) return 0;
197  return Wavelet::getMaxLevel((int)nWWS);
198 }
199 
200 // allocate input data
201 template<class DataType_t>
203 allocate(size_t n, DataType_t *p)
204 {
205  bool allocate = false;
206  if(pWWS == NULL && n>0 && p != NULL){
207  allocate = true;
208  pWWS = p;
209  nWWS = n;
210  }
211  return allocate;
212 }
213 
214 // check allocation status
215 template<class DataType_t>
217 {
218  return (pWWS == NULL || nWWS == 0) ? false : true;
219 }
220 
221 // release input data
222 template<class DataType_t>
224 {
225  pWWS = NULL;
226  nWWS = 0;
227 }
228 
229 // forward does one step of forward Fast Wavelet Transform.
230 // It's implemented for FWT with even number of coefficients.
231 // Also the lenght of high and low pass filters is the same,
232 // It is used for Daubechies, Symlet and Meyer wavelets.
233 //
234 // <level> input parameter is the level to be transformed
235 // <layer> input parameter is the layer to be transformed.
236 // <pF> wavelet filter, the pF length is m_H=m_L
237 //
238 // note: borders are handled in B_CYCLE mode
239 // note: even wavelet mode is standard
240 
241 template<class DataType_t>
242 void WaveDWT<DataType_t>::forwardFWT(int level, int layer,
243  const double* pLPF,
244  const double* pHPF)
245 {
246  int VM = (m_H/2&1); // 1 if Odd Vanishing Moments
247  int nS = nWWS>>level; // number of samples in the layer
248  int kL = -(m_H/2-VM); // k left limit for left border
249  int iL = nS-m_H+1; // i left limit for regular case
250 
251 // switch to odd wavelet mode
252 // if(m_Parity && layer&1) kL -= VM ? 1 : -1;
253  if(m_Parity) kL -= VM ? 1 : -1;
254 
255  int iR = nS+kL; // i right limit for right border
256 
257 //EVM--------------odd wavelet mode-----------------------
258 //
259 // LP [a0] [h0] | h1 h2 h3 0 0 0 0 h0 | [s0]
260 // HP [d0] [h3] |-h2 h1 -h0 0 0 0 0 h3 | [s1]
261 // [a1] | 0 h0 h1 h2 h3 0 0 0 | [s2]
262 // for [d1] = | 0 h3 -h2 h1 -h0 0 0 0 | X [s3]
263 // DB2 [a2] = | 0 0 0 h0 h1 h2 h3 0 | X [s4]
264 // [d2] | 0 0 0 h3 -h2 h1 -h0 0 | [s5]
265 // [a3] | 0 0 0 0 0 h0 h1 h2 | [ h3] [s6]
266 // [d3] |-h0 0 0 0 0 h3 -h2 h1 | [-h0] [s7]
267 //
268 //EVM--------------even border handling---------------------
269 //
270 // LP [a0] [h0 h1] | h2 h3 0 0 0 0 h0 h1 | [s0]
271 // HP [d0] [h3 -h2] | h1 -h0 0 0 0 0 h3 -h2 | [s1]
272 // [a1] | h0 h1 h2 h3 0 0 0 0 | [s2]
273 // for [d1] = | h3 -h2 h1 -h0 0 0 0 0 | X [s3]
274 // DB2 [a2] = | 0 0 h0 h1 h2 h3 0 0 | X [s4]
275 // [d2] | 0 0 h3 -h2 h1 -h0 0 0 | [s5]
276 // [a3] | 0 0 0 0 h0 h1 h2 h3 | [s6]
277 // [d3] | 0 0 0 0 h3 -h2 h1 -h0 | [s7]
278 //
279 //
280 // temp array: a d a d a d ..... a d a d a d
281 // a - approximations, d - details
282 //---------------------------------------------------------
283 
284 
285 //OVM---------------odd border handling-----------------------
286 //
287 // index i: -3 -2 -1 | 0 1 2 3 4 5 6 7 8
288 // limits: iL iR
289 //
290 // index k: -3 -2 -1 | 0 1 2 3 4 5 6 7 8 9 10 11 | 12 13
291 // limits: kL kR
292 //
293 // LP h0 h1 h2 | h3 h4 h5 0 0 0 0 0 0 h0 h1 h2 |
294 // HP h5 -h4 h3 | -h2 h1 -h0 0 0 0 0 0 0 h5 -h4 h3 |
295 // h0 | h1 h2 h3 h4 h5 0 0 0 0 0 0 h0 |
296 // for h5 | -h4 h3 -h2 h1 -h0 0 0 0 0 0 0 h5 |
297 // DB3 | 0 h0 h1 h2 h3 h4 h5 0 0 0 0 0 |
298 // | 0 h5 -h4 h3 -h2 h1 -h0 0 0 0 0 0 |
299 // | 0 0 0 h0 h1 h2 h3 h4 h5 0 0 0 |
300 // | 0 0 0 h5 -h4 h3 -h2 h1 -h0 0 0 0 |
301 // | 0 0 0 0 0 h0 h1 h2 h3 h4 h5 0 |
302 // | 0 0 0 0 0 h5 -h4 h3 -h2 h1 -h0 0 |
303 // | h5 0 0 0 0 0 0 h0 h1 h2 h3 h4 | h5
304 // | -h0 0 0 0 0 0 0 h5 -h4 h3 -h2 h1 | -h0
305 //
306 //OVM---------------even border handling-----------------------
307 //
308 // index i: -2 -1 | 0 1 2 3 4 5 6 7 8 9 10
309 // limits: iL iR
310 //
311 // index k: -2 -1 | 0 1 2 3 4 5 6 7 8 9 10 11 | 12 13 14
312 // limits: kL kR
313 //
314 // LP h0 h1 | h2 h3 h4 h5 0 0 0 0 0 0 h0 h1 |
315 // HP h5 -h4 | h3 -h2 h1 -h0 0 0 0 0 0 0 h5 -h4 |
316 // | h0 h1 h2 h3 h4 h5 0 0 0 0 0 0 |
317 // for | h5 -h4 h3 -h2 h1 -h0 0 0 0 0 0 0 |
318 // DB3 | 0 0 h0 h1 h2 h3 h4 h5 0 0 0 0 |
319 // | 0 0 h5 -h4 h3 -h2 h1 -h0 0 0 0 0 |
320 // | 0 0 0 0 h0 h1 h2 h3 h4 h5 0 0 |
321 // | 0 0 0 0 h5 -h4 h3 -h2 h1 -h0 0 0 |
322 // | 0 0 0 0 0 0 h0 h1 h2 h3 h4 h5 |
323 // | 0 0 0 0 0 0 h5 -h4 h3 -h2 h1 -h0 |
324 // | h4 h5 0 0 0 0 0 0 h0 h1 h2 h3 | h4 h5
325 // | h1 -h0 0 0 0 0 0 0 h5 -h4 h3 -h2 | h1 -h0
326 //
327 // temp array: a d a d a d ..... a d a d a d
328 // a - approximations, d - details
329 //---------------------------------------------------------
330 
331  if(pLPF==NULL || pHPF==NULL) return;
332 
333  register int i,j,k;
334  register double sumA, sumD, data;
335  register const double *p = pLPF;
336  register const double *q = pHPF;
337  register DataType_t *pD;
338  register int stride = 1<<level; // stride parameter
339 
340 // pointer to the first sample in the layer
341  DataType_t *pData = pWWS+getOffset(level,layer);
342 
343  double *temp = new double[nS]; // temporary array
344 
345 // left border
346 
347  i = kL;
348 
349  while(i<0) {
350  sumA=0.; sumD=0.;
351 
352  for(j=0; j<m_H; j++) {
353  k = i+j;
354  if(k < 0) k += nS;
355  data = pData[k<<level];
356  sumA += *p++ * data;
357  sumD += *q++ * data;
358  }
359 
360  *temp++ = sumA;
361  *temp++ = sumD;
362  i += 2;
363  p -= m_H;
364  q -= m_H;
365  }
366 
367 // processing data in the middle of array
368 
369  while(i<iL) {
370  pD = pData + (i<<level) - stride;
371  sumA=0.; sumD=0.;
372 
373  for(j=0; j<m_H; j+=2) {
374  data = *(pD += stride);
375  sumA += *p++ * data;
376  sumD += *q++ * data;
377  data = *(pD += stride);
378  sumA += *p++ * data;
379  sumD += *q++ * data;
380  }
381 
382  *temp++ = sumA;
383  *temp++ = sumD;
384  i += 2;
385  p -= m_H;
386  q -= m_H;
387  }
388 
389 // right border
390 
391  while(i<iR) {
392  sumA=0.; sumD=0.;
393 
394  for(j=0; j<m_H; j++) {
395  k = i+j;
396  if(k >= nS) k -= nS;
397  data = pData[k<<level];
398  sumA += *p++ * data;
399  sumD += *q++ * data;
400  }
401 
402  *temp++ = sumA;
403  *temp++ = sumD;
404  i += 2;
405  p -= m_H;
406  q -= m_H;
407  }
408 
409 // writing data back from temporary storage
410  for(i=nS-1; i>=0; i--) {pData[i<<level] = *(--temp);}
411 
412  if(m_Heterodine){
413  for(i=1; i<nS; i+=4) {pData[i<<level] *= -1;} // heterodine detailes coefficients
414  }
415 
416  delete [] temp;
417 }
418 
419 
420 // inverse does one step of inverse Fast Wavelet Transform.
421 // It's implemented for FWT with even number of coefficients.
422 // Also the lenght of high and low pass filters is the same
423 // It is used for Daubechies and Symlet wavelets.
424 //
425 // <level> input parameter is the level to be transformed
426 // <layer> input parameter is the layer to be transformed.
427 // <pF> wavelet filter, the pF length is m_H=m_L
428 //
429 // note: borders are handled in B_CYCLE mode
430 // note: even wavelet mode is standard
431 
432 template<class DataType_t>
433 void WaveDWT<DataType_t>::inverseFWT(int level, int layer,
434  const double* pLPF,
435  const double* pHPF)
436 {
437  if(pLPF==NULL || pHPF==NULL) return;
438 
439  int VM = (m_H/2&1); // 1 if Odd Vanishing Moments
440  int nS = nWWS>>level; // number of samples in the layer
441  int kL = -(m_H/2-2+VM); // k left limit
442  int iL = nS-m_H+1; // i left limit
443 
444  // bool ODD = m_Parity && layer&1;
445  bool ODD = m_Parity;
446  if(ODD) { kL -= 2-2*VM; }
447 
448  int iR = nS+kL; // i right limit
449 
450 // iLP filter for db2: h3 -h0 h1 -h2
451 // iHP filter for db2: h2 h1 h0 h3
452 // inverse matrix is transpose of forward matrix
453 //EVM------------------odd border handling-----------------------
454 //
455 // index i: -2 -1 0 1 2 3 4 5 6
456 // limits: iL iR
457 //
458 // index k: -2 -1 0 1 2 3 4 5 6 7 8 9
459 // limits: kL
460 // iHP [s0] h3 -h0 | h1 -h2 0 0 0 0 h3 -h0 | [a0]
461 // iLP [s1] | h2 h1 h0 h3 0 0 0 0 | [d0]
462 // [s2] | h3 -h0 h1 -h2 0 0 0 0 | [a1]
463 // for [s3] = | 0 0 h2 h1 h0 h3 0 0 | X [d1]
464 // DB2 [s4] = | 0 0 h3 -h0 h1 -h2 0 0 | X [a2]
465 // [s5] | 0 0 0 0 h2 h1 h0 h3 | [d2]
466 // [s6] | 0 0 0 0 h3 -h0 h1 -h2 | [a3]
467 // [s7] | h0 h3 0 0 0 0 h2 h1 | h0 h3 [d3]
468 //
469 //EVM---------------even border handling-----------------------
470 //
471 // iLP [s0] | h2 h1 h0 h3 0 0 0 0 | [a0]
472 // iHP [s1] | h3 -h0 h1 -h2 0 0 0 0 | [d0]
473 // [s2] | 0 0 h2 h1 h0 h3 0 0 | [a1]
474 // for [s3] = | 0 0 h3 -h0 h1 -h2 0 0 | X [d1]
475 // DB2 [s4] = | 0 0 0 0 h2 h1 h0 h3 | X [a2]
476 // [s5] | 0 0 0 0 h3 -h0 h1 -h2 | [d2]
477 // [s6] | h0 h3 0 0 0 0 h2 h1 | [a3]
478 // [s7] | h1 -h2 0 0 0 0 h3 -h0 | [d3]
479 //
480 // temp array: a d a d a d ..... a d a d a d
481 // a - approximations, d - details
482 //---------------------------------------------------------
483 
484 // iLP filter for db3: h4 h1 h2 h3 h0 h5
485 // iHP filter for db3: h5 -h0 h3 -h2 h1 -h4
486 //OVM---------------odd border handling-----------------------
487 //
488 // index i: -2 -1 | 0 1 2 3 4 5 6 7 8 9 10
489 // limits: iL iR
490 //
491 // index k: -2 -1 | 0 1 2 3 4 5 6 7 8 9 10 11 | 12 13
492 // limits: kL kR
493 //
494 // HP h5 -h0 | h3 -h2 h1 -h4 0 0 0 0 0 0 h5 -h4 |
495 // LP | h4 h1 h2 h3 h0 h5 0 0 0 0 0 0 |
496 // | h5 -h0 h3 -h2 h1 -h4 0 0 0 0 0 0 |
497 // for | 0 0 h4 h1 h2 h3 h0 h5 0 0 0 0 |
498 // DB3 | 0 0 h5 -h0 h3 -h2 h1 -h4 0 0 0 0 |
499 // | 0 0 0 0 h4 h1 h2 h3 h0 h5 0 0 |
500 // | 0 0 0 0 h5 -h0 h3 -h2 h1 -h4 0 0 |
501 // | 0 0 0 0 0 0 h4 h1 h2 h3 h0 h5 |
502 // | 0 0 0 0 0 0 h5 -h0 h3 -h2 h1 -h4 |
503 // | h0 h5 0 0 0 0 0 0 h4 h1 h2 h3 | h0 h5
504 // | h1 -h4 0 0 0 0 0 0 h5 -h0 h3 -h2 | h1 -h4
505 // | h2 h3 h0 h5 0 0 0 0 0 0 h4 h1 | h2 h3 h0 h5
506 //
507 //OVM---------------even border handling-----------------------
508 //
509 // index i: -2 -1 | 0 1 2 3 4 5 6 7 8
510 // limits: iL iR
511 //
512 // index k: -2 -1 | 0 1 2 3 4 5 6 7 8 9 10 11 | 12 13 14
513 // limits: kL kR
514 //
515 // LP h4 h1 | h2 h3 h0 h5 0 0 0 0 0 0 h4 h1 |
516 // HP h5 -h0 | h3 -h2 h1 -h4 0 0 0 0 0 0 h5 -h0 |
517 // | h4 h1 h2 h3 h0 h5 0 0 0 0 0 0 |
518 // for | h5 -h0 h3 -h2 h1 -h4 0 0 0 0 0 0 |
519 // DB3 | 0 0 h4 h1 h2 h3 h0 h5 0 0 0 0 |
520 // | 0 0 h5 -h0 h3 -h2 h1 -h4 0 0 0 0 |
521 // | 0 0 0 0 h4 h1 h2 h3 h0 h5 0 0 |
522 // | 0 0 0 0 h5 -h0 h3 -h2 h1 -h4 0 0 |
523 // | 0 0 0 0 0 0 h4 h1 h2 h3 h0 h5 |
524 // | 0 0 0 0 0 0 h5 -h0 h3 -h2 h1 -h4 |
525 // | h0 h5 0 0 0 0 0 0 h4 h1 h2 h3 | h0 h5
526 // | h1 -h4 0 0 0 0 0 0 h5 -h0 h3 -h2 | h1 -h4
527 //
528 // temp array: a d a d a d ..... a d a d a d
529 // a - approximations, d - details
530 //---------------------------------------------------------
531 
532 
533  register long i,j,k;
534  register double sumA, sumD, data;
535  register const double *p = pLPF;
536  register const double *q = pHPF;
537  register DataType_t *pD;
538  register int stride = 1<<level; // stride parameter
539 
540 // pointer to the first sample in the layer
541  DataType_t *pData = pWWS+getOffset(level,layer);
542 
543  double *temp = new double[nS]; // temporary array
544 
545  if(m_Heterodine){
546  for(i=1; i<nS; i+=4) {pData[i<<level] *= -1;} // heterodine detailes coefficients
547  }
548 
549 // left border
550 
551  i = kL;
552 
553  if(ODD){ // handle ODD wavelet mode on left border
554  p = pHPF;
555  *temp = 0;
556 
557  for(j=0; j<m_H; j++) {
558  k = i+j;
559  if(k < 0) k += nS;
560  *temp += *p++ * pData[k<<level];
561  }
562  temp++;
563  i += 2;
564  p = pLPF;
565  }
566 
567  while(i<0) {
568  sumA = 0.; sumD = 0.;
569 
570  for(j=0; j<m_H; j++) {
571  k = i+j;
572  if(k < 0) k += nS;
573  data = pData[k<<level];
574  sumA += *p++ * data;
575  sumD += *q++ * data;
576  }
577 
578  *temp++ = sumA;
579  *temp++ = sumD;
580  i += 2;
581  p -= m_H;
582  q -= m_H;
583  }
584 
585 // processing data in the middle of array
586 
587  while(i<iL) {
588  pD = pData + (i<<level) - stride;
589  sumA = 0.; sumD = 0.;
590 
591  for(j=0; j<m_H; j+=2) {
592  data = *(pD += stride);
593  sumA += *p++ * data;
594  sumD += *q++ * data;
595  data = *(pD += stride);
596  sumD += *q++ * data;
597  sumA += *p++ * data;
598  }
599 
600  *temp++ = sumA;
601  *temp++ = sumD;
602  i += 2;
603  p -= m_H;
604  q -= m_H;
605  }
606 
607 // right border
608 
609  while(i<iR) {
610  sumA = 0.; sumD = 0.;
611 
612  for(j=0; j<m_H; j++) {
613  k = i+j;
614  if(k >= nS) k -= nS;
615  data = pData[k<<level];
616  sumA += *p++ * data;
617  sumD += *q++ * data;
618  }
619 
620  *temp++ = sumA;
621  *temp++ = sumD;
622  i += 2;
623  p -= m_H;
624  q -= m_H;
625  }
626 
627  if(ODD){ // handle odd wavelet mode on right border
628  q = pLPF;
629  *temp = 0.;
630 
631  for(j=0; j<m_H; j++) {
632  k = i+j;
633  if(k >= nS) k -= nS;
634  *temp += *q++ * pData[k<<level];
635  }
636  temp++;
637  }
638 
639 // writing data back from temporary storage
640  for(i=nS-1; i>=0; i--)
641  pData[i<<level] = *(--temp);
642 
643  delete [] temp;
644 }
645 
646 // predict function does one lifting prediction step
647 // <level> input parameter is the level to be transformed
648 // <layer> input parameter is the layer to be transformed.
649 // <p_H> pointer to prediction filter. It has length m_H
650 template<class DataType_t>
652  int layer,
653  const double* p_H)
654 {
655  level++; // increment level (next level now)
656 
657 //------------------predict border handling-----------------------
658 // use even samples to predict odd samples
659 // an example for m_H=8 and 20 samples
660 // i index limits nL............nM....nR-1
661 // i index : -3 -2 -1 0 1 2 3 4 5 6
662 // j index (approx): -3 -2 -1 0 1 2 3 4 5 6 7 8 9 | 10 11 12 13
663 // odd samples: 0 1 2 3 4 5 6 7 8 9
664 // L L L M M M R R R R
665 // L,R - samples affected by borders
666 // M - not affected samples
667 //---------------------------------------------------------
668 
669  int nS = nWWS>>level; // nS - number of samples in the layer
670  int nL = 1-m_H/2; // nL - left limit of predict i index
671  int nR = nS+nL; // nR - right limit of predict i index
672  int nM = nS-m_H+1; // nM - number of M samples (first aR sample)
673  int mM = nM<<level; // (number of M samples)<<level
674 
675  double data;
676  double hsum = 0.; // filter sum
677 
678  register int i,j,k;
679  register double sum = 0.;
680 
681  register const double *h; // pointer to filter coefficient
682  register const DataType_t *dataL; // pointer to left data sample
683  register const DataType_t *dataR; // pointer to right data sample
684  register const int stride = 1<<level; // stride parameter
685 
686  double *pBorder=new double[2*(m_H-nL)]; // border array
687  double *pB;
688 
689  DataType_t *dataA, *dataD;
690 
691  dataA=pWWS+getOffset(level,layer<<1); // pointer to approximation layer
692  dataD=pWWS+getOffset(level,(layer<<1)+1); // pointer to detail layer
693 
694  for(k=0; k<m_H; k++) hsum += p_H[k];
695 
696 // left border
697 
698  pB = pBorder;
699  dataL = dataA; // first (left) sample
700  for(k=0; k<(m_H-nL); k++){
701  j = k + nL;
702  pB[k] = *(dataL + abs(j<<level));
703 
704  if(j>=0) continue;
705 
706  data = *(dataL + ((j+nS)<<level));
707  switch (m_Border) {
708  case B_PAD_ZERO : pB[k] = 0.; break; // pad zero
709  case B_PAD_EDGE : pB[k] = *dataL; break; // pad by edge value
710  case B_CYCLE : pB[k] = data; break; // cycle data
711  default : break; // mirror or interpolate
712  }
713  }
714 
715  for(i=nL; i<0; i++) { // i index
716 
717  if(m_Border != B_POLYNOM){
718  sum = 0.;
719  for(k=0; k<m_H/2; k++)
720  sum += p_H[k] * (pB[k] + pB[m_H-1-k]);
721  pB++;
722  }
723  else{
724 // pB = pBorder - nL; // point to dataA
725 // sum = hsum*Nevill(i+0.5-nL, m_H+i, pB, pB+m_H); // POLYNOM1
726  pB = pBorder - nL; // point to dataA
727  sum = hsum*Nevill(i+0.5-nL, m_H+2*i, pB, pB+m_H); // POLYNOM2
728  }
729 
730  *dataD -= sum;
731  dataD += stride;
732  }
733 
734 // regular case (no borders)
735 
736  k = (m_H-1)<<level;
737 
738  for(i=0; i<mM; i+=stride) {
739  dataL = dataA+i;
740  dataR = dataL+k;
741  h = p_H;
742 
743  sum=0.;
744  do sum += *(h++) * (*dataL + *dataR);
745  while((dataL+=stride) < (dataR-=stride));
746 /*
747  sum = *(h++) * (*dataL + *dataR);
748  if ((dataL+=stride) > (dataR-=stride)) goto P0;
749  sum += *(h++) * (*dataL + *dataR);
750  if ((dataL+=stride) > (dataR-=stride)) goto P0;
751  sum += *(h++) * (*dataL + *dataR);
752  if ((dataL+=stride) > (dataR-=stride)) goto P0;
753  sum += *(h++) * (*dataL + *dataR);
754  if ((dataL+=stride) > (dataR-=stride)) goto P0;
755  sum += *(h++) * (*dataL + *dataR);
756  if ((dataL+=stride) > (dataR-=stride)) goto P0;
757  sum += *(h++) * (*dataL + *dataR);
758  if ((dataL+=stride) > (dataR-=stride)) goto P0;
759  sum += *(h++) * (*dataL + *dataR);
760  if ((dataL+=stride) > (dataR-=stride)) goto P0;
761  sum += *(h++) * (*dataL + *dataR);
762  if ((dataL+=stride) > (dataR-=stride)) goto P0;
763  sum += *(h++) * (*dataL + *dataR);
764  if ((dataL+=stride) > (dataR-=stride)) goto P0;
765  sum += *(h++) * (*dataL + *dataR);
766  if ((dataL+=stride) > (dataR-=stride)) goto P0;
767  sum += *(h++) * (*dataL + *dataR);
768  if ((dataL+=stride) > (dataR-=stride)) goto P0;
769  sum += *(h++) * (*dataL + *dataR);
770  if ((dataL+=stride) > (dataR-=stride)) goto P0;
771  sum += *(h++) * (*dataL + *dataR);
772  if ((dataL+=stride) > (dataR-=stride)) goto P0;
773  sum += *(h++) * (*dataL + *dataR);
774  if ((dataL+=stride) > (dataR-=stride)) goto P0;
775  sum += *(h++) * (*dataL + *dataR);
776 
777 P0: *dataD -= sum; */
778  *dataD -= sum;
779  dataD += stride;
780  }
781 
782 // right border
783 
784  pB = pBorder;
785  dataR = dataA + ((nS-1)<<level); // last (right) sample
786 
787  for(k=0; k<(m_H-nL+1); k++){
788  j = m_H - 1 - k;
789  pB[k] = *(dataR - abs(j<<level));
790 
791  if(j>=0) continue;
792 
793  data = *(dataR - ((j+nS)<<level));
794  switch (m_Border) {
795  case B_PAD_ZERO : pB[k] = 0.; break; // pad zero
796  case B_PAD_EDGE : pB[k] = *dataR; break; // pad by edge value
797  case B_CYCLE : pB[k] = data; break; // cycle data
798  default : break; // mirror or interpolate
799  }
800  }
801 
802  k = 0;
803  for(i=nM; i<nR; i++) {
804 
805  if(m_Border != B_POLYNOM){
806  sum = 0.; pB++;
807 
808  for(k=0; k<m_H/2; k++)
809  sum += p_H[k] * (pB[k] + pB[m_H-1-k]);
810  }
811  else{
812 // sum = hsum*Nevill(0.5-nL, nS-i, ++pB, pBorder+m_H+1);
813  k += 2;
814  sum = hsum*Nevill((m_H-k-1)/2., m_H-k, pB+k, pBorder+m_H+1);
815  if(k == m_H) sum = *(pB+k-1) * hsum;
816  }
817 
818  *dataD -= sum;
819  dataD += stride;
820  }
821 
822  delete [] pBorder;
823 }
824 
825 
826 // update function does one lifting update step
827 // <level> input parameter is the level to be transformed.
828 // <layer> input parameter is the layer to be transformed.
829 
830 template<class DataType_t>
832  int layer,
833  const double* p_L)
834 {
835  level++; // current level
836 
837 //------------------update border handling-----------------------
838 // use odd samples to update even samples
839 // an example for m_H=8 and 20 samples
840 // L L L L M M M R R R
841 // even samples : 0 1 2 3 4 5 6 7 8 9
842 // j index (detail): -4 -3 -2 -1 0 1 2 3 4 5 6 7 8 9 | 10 11 12
843 // i index : -4 -3 -2 -1 0 1 2 3 4 5
844 // i index limits nL...............nM..nR-1
845 // L,R - samples affected by borders
846 // M - not affected samples
847 //---------------------------------------------------------
848 
849  int nS = nWWS>>level; // nS - number of samples in the layer
850  int nL = -m_L/2; // nL - left limit of update i index
851  int nR = nS+nL; // nR - right limit of update i index
852  int nM = nS-m_L+1; // nM - number of M samples
853  int mM = nM<<level; // (number of M samples)<<level
854 
855  double data;
856  double hsum = 0.; // filter sum
857 
858  register int i,j,k;
859  register double sum = 0.;
860 
861  register const double *h; // pointer to filter coefficient
862  register const DataType_t *dataL; // pointer to left data sample
863  register const DataType_t *dataR; // pointer to right data sample
864  register const int stride = 1<<level; // stride parameter
865 
866  DataType_t *dataA, *dataD;
867 
868  double *pBorder=new double[2*(m_L-nL)]; // border array
869  double *pB;
870 
871  dataA=pWWS+getOffset(level,layer<<1); // pointer to approximation layer
872  dataD=pWWS+getOffset(level,(layer<<1)+1); // pointer to detail layer
873 
874  for(k=0; k<m_L; k++) hsum += p_L[k];
875 
876 // left border
877 
878  pB = pBorder;
879  dataL = dataD; // first (left) sample
880  for(k=0; k<(m_L-nL); k++){
881  j = k + nL;
882  pB[k] = *(dataL + abs(j<<level));
883 
884  if(j>=0) continue;
885 
886  data = *(dataL + ((j+nS)<<level));
887  switch (m_Border) {
888  case B_PAD_ZERO : pB[k] = 0.; break; // pad zero
889  case B_PAD_EDGE : pB[k] = *dataL; break; // pad by edge value
890  case B_CYCLE : pB[k] = data; break; // cycle data
891  default : break; // mirror or interpolate
892  }
893  }
894 
895  for(i=nL; i<0; i++) { // i index
896 
897  if(m_Border != B_POLYNOM){
898  sum = 0.;
899  for(k=0; k<m_L/2; k++)
900  sum += p_L[k] * (pB[k] + pB[m_L-1-k]);
901  pB++;
902  }
903  else{
904 // pB = pBorder - nL; // point to dataD
905 // sum = hsum*Nevill(i-0.5-nL, m_L+i, pB, pB+m_L); // POLYNOM1
906  pB = pBorder - nL; // point to dataD
907  sum = hsum*Nevill(i-0.5-nL, m_L+2*i, pB, pB+m_L); // POLYNOM2
908  }
909 
910  *dataA += sum;
911  dataA += stride;
912  }
913 
914 // regular case (no borders)
915 
916  k = (m_L-1)<<level;
917 
918  for(i=0; i<mM; i+=stride) {
919  dataL = dataD+i;
920  dataR = dataL+k;
921  h = p_L;
922 
923  sum=0.;
924  do sum += *(h++) * (*dataL + *dataR);
925  while((dataL+=stride) < (dataR-=stride));
926 /*
927  sum = *(h++) * (*dataL + *dataR);
928  if ((dataL+=stride) > (dataR-=stride)) goto U0;
929  sum += *(h++) * (*dataL + *dataR);
930  if ((dataL+=stride) > (dataR-=stride)) goto U0;
931  sum += *(h++) * (*dataL + *dataR);
932  if ((dataL+=stride) > (dataR-=stride)) goto U0;
933  sum += *(h++) * (*dataL + *dataR);
934  if ((dataL+=stride) > (dataR-=stride)) goto U0;
935  sum += *(h++) * (*dataL + *dataR);
936  if ((dataL+=stride) > (dataR-=stride)) goto U0;
937  sum += *(h++) * (*dataL + *dataR);
938  if ((dataL+=stride) > (dataR-=stride)) goto U0;
939  sum += *(h++) * (*dataL + *dataR);
940  if ((dataL+=stride) > (dataR-=stride)) goto U0;
941  sum += *(h++) * (*dataL + *dataR);
942  if ((dataL+=stride) > (dataR-=stride)) goto U0;
943  sum += *(h++) * (*dataL + *dataR);
944  if ((dataL+=stride) > (dataR-=stride)) goto U0;
945  sum += *(h++) * (*dataL + *dataR);
946  if ((dataL+=stride) > (dataR-=stride)) goto U0;
947  sum += *(h++) * (*dataL + *dataR);
948  if ((dataL+=stride) > (dataR-=stride)) goto U0;
949  sum += *(h++) * (*dataL + *dataR);
950  if ((dataL+=stride) > (dataR-=stride)) goto U0;
951  sum += *(h++) * (*dataL + *dataR);
952  if ((dataL+=stride) > (dataR-=stride)) goto U0;
953  sum += *(h++) * (*dataL + *dataR);
954  if ((dataL+=stride) > (dataR-=stride)) goto U0;
955  sum += *(h++) * (*dataL + *dataR);
956 
957 U0: *dataA += sum; */
958  *dataA += sum;
959  dataA += stride;
960  }
961 
962 // right border
963 
964  pB = pBorder;
965  dataR = dataD + ((nS-1)<<level); // last detail sample
966 
967  for(k=0; k<(m_L-nL); k++){
968  j = m_L - 1 - k;
969  pB[k] = *(dataR - abs(j<<level));
970 
971  if(j>=0) continue;
972 
973  data = *(dataR - ((j+nS)<<level));
974  switch (m_Border) {
975  case B_PAD_ZERO : pB[k] = 0.; break; // pad zero
976  case B_PAD_EDGE : pB[k] = *dataR; break; // pad by edge value
977  case B_CYCLE : pB[k] = data; break; // cycle data
978  default : break; // mirror or interpolate
979  }
980  }
981 
982  k = 0;
983  for(i=nM; i<nR; i++) {
984 
985  if(m_Border != B_POLYNOM){
986  sum = 0.; pB++;
987  for(k=0; k<m_L/2; k++)
988  sum += p_L[k] * (pB[k] + pB[m_L-1-k]);
989  }
990  else{
991 // sum = hsum*Nevill(-0.5-nL, nS-i, ++pB, pBorder+m_L+1);
992  k += 2;
993 // sum = hsum*Nevill((m_L-k-1)/2., m_L-k, pB+k, pBorder+m_L+1); // wat version
994  sum = hsum*Nevill((m_H-k-1)/2., m_H-k, pB+k, pBorder+m_H+1); // datacond version
995  }
996 
997  *dataA += sum;
998  dataA += stride;
999  }
1000 
1001  delete [] pBorder;
1002 }
1003 
1004 template <class DataType_t>
1005 void WaveDWT<DataType_t>::Streamer(TBuffer &R__b)
1006 {
1007  // Stream an object of class WaveDWT<double>.
1008  UInt_t R__s, R__c;
1009  if (R__b.IsReading()) {
1010  Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) { }
1011  Wavelet::Streamer(R__b);
1012  R__b >> nWWS;
1013  R__b >> nSTS;
1014  pWWS=NULL;
1015  R__b.CheckByteCount(R__s, R__c, WaveDWT<DataType_t>::IsA());
1016  } else {
1017  R__c = R__b.WriteVersion(WaveDWT<DataType_t>::IsA(), kTRUE);
1018  Wavelet::Streamer(R__b);
1019  R__b << nWWS;
1020  R__b << nSTS;
1021  R__b.SetByteCount(R__c, kTRUE);
1022  }
1023 }
1024 
1025 
1026 // instantiations
1027 
1028 #define CLASS_INSTANTIATION(class_) template class WaveDWT< class_ >;
1029 
1030 CLASS_INSTANTIATION(float)
1031 CLASS_INSTANTIATION(double)
1032 //CLASS_INSTANTIATION(std::complex<float>)
1033 //CLASS_INSTANTIATION(std::complex<double>)
1034 
1035 #undef CLASS_INSTANTIATION
1036 
1037 //} // namespace wat
1038 //} // namespace datacondAPI
TTree * tree
Definition: TimeSortTree.C:20
virtual ~WaveDWT()
Definition: WaveDWT.cc:58
bool m_Parity
Definition: Wavelet.hh:127
WaveDWT(int mH=1, int mL=1, int tree=0, enum BORDER border=B_CYCLE)
Definition: WaveDWT.cc:38
int n
Definition: cwb_net.C:28
virtual void t2w(int=1)
Definition: WaveDWT.cc:75
virtual void inverse(int, int)
Definition: WaveDWT.hh:139
int m_TreeType
Definition: Wavelet.hh:112
BORDER
Definition: Wavelet.hh:36
STL namespace.
double Nevill(const double x0, int n, DataType_t *p, double *q)
Definition: watfun.hh:56
int m
Definition: cwb_net.C:28
DataType_t * pWWS
Definition: WaveDWT.hh:141
virtual void inverseFWT(int, int, const double *, const double *)
Definition: WaveDWT.cc:433
int j
Definition: cwb_net.C:28
i drho i
void release()
Definition: WaveDWT.cc:223
wavearray< double > w
Definition: Test1.C:27
virtual void forwardFWT(int, int, const double *, const double *)
Definition: WaveDWT.cc:242
int m_L
Definition: Wavelet.hh:124
virtual void forward(int, int)
Definition: WaveDWT.hh:137
unsigned long nSTS
Definition: WaveDWT.hh:143
wavearray< double > h
Definition: Regression_H1.C:25
i() int(T_cor *100))
virtual int convertF2L(int, int)
Definition: Wavelet.cc:93
enum BORDER m_Border
Definition: Wavelet.hh:109
int k
int m_Level
Definition: Wavelet.hh:115
#define CLASS_INSTANTIATION(class_)
Definition: WaveDWT.cc:1028
bool allocate()
Definition: WaveDWT.cc:216
bool m_Heterodine
Definition: Wavelet.hh:126
virtual void update(int, int, const double *)
Definition: WaveDWT.cc:831
s s
Definition: cwb_net.C:155
virtual void predict(int, int, const double *)
Definition: WaveDWT.cc:651
bool BinaryTree()
Definition: Wavelet.hh:97
unsigned long nWWS
pointer to wavelet work space
Definition: WaveDWT.hh:142
virtual std::slice getSlice(const double)
Definition: WaveDWT.cc:129
wavearray< int > index
double fabs(const Complex &x)
Definition: numpy.cc:55
virtual void w2t(int=1)
Definition: WaveDWT.cc:106
virtual int getMaxLevel()
Definition: WaveDWT.cc:194
virtual int getOffset(int, int)
Definition: Wavelet.cc:69
virtual int getMaxLevel(int)
Definition: Wavelet.hh:134
int m_Layer
Definition: Wavelet.hh:118
virtual WaveDWT< DataType_t > * Clone() const
return: Wavelet* - duplicate of *this, allocated on heap
Definition: WaveDWT.cc:64
int m_H
Definition: Wavelet.hh:121
detector ** pD