3 * Copyright (C) 2004 Ivo Alxneit
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or (at
8 * your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 /* function dwt_step is based on the public domain function pwt.c
21 * available from http://www.numerical-recipes.com
25 #include <gsl/gsl_errno.h>
26 #include <gsl/gsl_wavelet.h>
27 #include <gsl/gsl_wavelet2d.h>
29 #define ELEMENT(a,stride,i) ((a)[(stride)*(i)])
31 static int binary_logn (const size_t n);
32 static void dwt_step (const gsl_wavelet * w, double *a, size_t stride, size_t n, gsl_wavelet_direction dir, gsl_wavelet_workspace * work);
35 binary_logn (const size_t n)
51 return -1; /* n is not a power of 2 */
58 dwt_step (const gsl_wavelet * w, double *a, size_t stride, size_t n,
59 gsl_wavelet_direction dir, gsl_wavelet_workspace * work)
65 size_t n1, ni, nh, nmod;
67 for (i = 0; i < work->n; i++)
69 work->scratch[i] = 0.0;
73 nmod -= w->offset; /* center support */
78 if (dir == gsl_wavelet_forward)
80 for (ii = 0, i = 0; i < n; i += 2, ii++)
86 for (k = 0; k < w->nc; k++)
89 h += w->h1[k] * ELEMENT (a, stride, jf);
90 g += w->g1[k] * ELEMENT (a, stride, jf);
93 work->scratch[ii] += h;
94 work->scratch[ii + nh] += g;
99 for (ii = 0, i = 0; i < n; i += 2, ii++)
101 ai = ELEMENT (a, stride, ii);
102 ai1 = ELEMENT (a, stride, ii + nh);
104 for (k = 0; k < w->nc; k++)
106 jf = (n1 & (ni + k));
107 work->scratch[jf] += (w->h2[k] * ai + w->g2[k] * ai1);
112 for (i = 0; i < n; i++)
114 ELEMENT (a, stride, i) = work->scratch[i];
119 gsl_wavelet_transform (const gsl_wavelet * w,
120 double *data, size_t stride, size_t n,
121 gsl_wavelet_direction dir,
122 gsl_wavelet_workspace * work)
128 GSL_ERROR ("not enough workspace provided", GSL_EINVAL);
131 if (binary_logn (n) == -1)
133 GSL_ERROR ("n is not a power of 2", GSL_EINVAL);
141 if (dir == gsl_wavelet_forward)
143 for (i = n; i >= 2; i >>= 1)
145 dwt_step (w, data, stride, i, dir, work);
150 for (i = 2; i <= n; i <<= 1)
152 dwt_step (w, data, stride, i, dir, work);
160 gsl_wavelet_transform_forward (const gsl_wavelet * w,
161 double *data, size_t stride, size_t n,
162 gsl_wavelet_workspace * work)
164 return gsl_wavelet_transform (w, data, stride, n, gsl_wavelet_forward, work);
168 gsl_wavelet_transform_inverse (const gsl_wavelet * w,
169 double *data, size_t stride, size_t n,
170 gsl_wavelet_workspace * work)
172 return gsl_wavelet_transform (w, data, stride, n, gsl_wavelet_backward, work);
176 /* Leaving this out for now BJG */
179 gsl_dwt_vector (const gsl_wavelet * w, gsl_vector *v, gsl_wavelet_direction
180 dir, gsl_wavelet_workspace * work)
182 return gsl_dwt (w, v->data, v->stride, v->size, dir, work);
187 gsl_wavelet2d_transform (const gsl_wavelet * w,
188 double *data, size_t tda, size_t size1,
189 size_t size2, gsl_wavelet_direction dir,
190 gsl_wavelet_workspace * work)
196 GSL_ERROR ("2d dwt works only with square matrix", GSL_EINVAL);
201 GSL_ERROR ("not enough workspace provided", GSL_EINVAL);
204 if (binary_logn (size1) == -1)
206 GSL_ERROR ("n is not a power of 2", GSL_EINVAL);
214 if (dir == gsl_wavelet_forward)
216 for (i = 0; i < size1; i++) /* for every row j */
218 gsl_wavelet_transform (w, &ELEMENT(data, tda, i), 1, size1, dir, work);
220 for (i = 0; i < size2; i++) /* for every column j */
222 gsl_wavelet_transform (w, &ELEMENT(data, 1, i), tda, size2, dir, work);
227 for (i = 0; i < size2; i++) /* for every column j */
229 gsl_wavelet_transform (w, &ELEMENT(data, 1, i), tda, size2, dir, work);
231 for (i = 0; i < size1; i++) /* for every row j */
233 gsl_wavelet_transform (w, &ELEMENT(data, tda, i), 1, size1, dir, work);
241 gsl_wavelet2d_nstransform (const gsl_wavelet * w,
242 double *data, size_t tda, size_t size1,
243 size_t size2, gsl_wavelet_direction dir,
244 gsl_wavelet_workspace * work)
250 GSL_ERROR ("2d dwt works only with square matrix", GSL_EINVAL);
255 GSL_ERROR ("not enough workspace provided", GSL_EINVAL);
258 if (binary_logn (size1) == -1)
260 GSL_ERROR ("n is not a power of 2", GSL_EINVAL);
268 if (dir == gsl_wavelet_forward)
270 for (i = size1; i >= 2; i >>= 1)
272 for (j = 0; j < i; j++) /* for every row j */
274 dwt_step (w, &ELEMENT(data, tda, j), 1, i, dir, work);
276 for (j = 0; j < i; j++) /* for every column j */
278 dwt_step (w, &ELEMENT(data, 1, j), tda, i, dir, work);
284 for (i = 2; i <= size1; i <<= 1)
286 for (j = 0; j < i; j++) /* for every column j */
288 dwt_step (w, &ELEMENT(data, 1, j), tda, i, dir, work);
290 for (j = 0; j < i; j++) /* for every row j */
292 dwt_step (w, &ELEMENT(data, tda, j), 1, i, dir, work);
302 gsl_wavelet2d_transform_forward (const gsl_wavelet * w,
303 double *data, size_t tda, size_t size1,
304 size_t size2, gsl_wavelet_workspace * work)
306 return gsl_wavelet2d_transform (w, data, tda, size1, size2, gsl_wavelet_forward, work);
310 gsl_wavelet2d_transform_inverse (const gsl_wavelet * w,
311 double *data, size_t tda, size_t size1,
312 size_t size2, gsl_wavelet_workspace * work)
314 return gsl_wavelet2d_transform (w, data, tda, size1, size2, gsl_wavelet_backward, work);
318 gsl_wavelet2d_nstransform_forward (const gsl_wavelet * w,
319 double *data, size_t tda, size_t size1,
320 size_t size2, gsl_wavelet_workspace * work)
322 return gsl_wavelet2d_nstransform (w, data, tda, size1, size2, gsl_wavelet_forward, work);
326 gsl_wavelet2d_nstransform_inverse (const gsl_wavelet * w,
327 double *data, size_t tda, size_t size1,
328 size_t size2, gsl_wavelet_workspace * work)
330 return gsl_wavelet2d_nstransform (w, data, tda, size1, size2, gsl_wavelet_backward, work);
335 gsl_wavelet2d_transform_matrix (const gsl_wavelet * w,
337 gsl_wavelet_direction dir,
338 gsl_wavelet_workspace * work)
340 return gsl_wavelet2d_transform (w, a->data,
341 a->tda, a->size1, a->size2,
346 gsl_wavelet2d_transform_matrix_forward (const gsl_wavelet * w,
348 gsl_wavelet_workspace * work)
350 return gsl_wavelet2d_transform (w, a->data,
351 a->tda, a->size1, a->size2,
352 gsl_wavelet_forward, work);
356 gsl_wavelet2d_transform_matrix_inverse (const gsl_wavelet * w,
358 gsl_wavelet_workspace * work)
360 return gsl_wavelet2d_transform (w, a->data,
361 a->tda, a->size1, a->size2,
362 gsl_wavelet_backward, work);
366 gsl_wavelet2d_nstransform_matrix (const gsl_wavelet * w,
368 gsl_wavelet_direction dir,
369 gsl_wavelet_workspace * work)
371 return gsl_wavelet2d_nstransform (w, a->data,
372 a->tda, a->size1, a->size2,
377 gsl_wavelet2d_nstransform_matrix_forward (const gsl_wavelet * w,
379 gsl_wavelet_workspace * work)
381 return gsl_wavelet2d_nstransform (w, a->data,
382 a->tda, a->size1, a->size2,
383 gsl_wavelet_forward, work);
387 gsl_wavelet2d_nstransform_matrix_inverse (const gsl_wavelet * w,
389 gsl_wavelet_workspace * work)
391 return gsl_wavelet2d_nstransform (w, a->data,
392 a->tda, a->size1, a->size2,
393 gsl_wavelet_backward, work);