
#line 1 "../gen/tmpl/lib.c"
/*
  gsl_Wavelet.c
  Ruby/Numo::GSL - GSL wrapper for Ruby/Numo::NArray

  created on: 2017-03-11
  Copyright (C) 2017 Masahiro Tanaka
*/

#include <ruby.h>
#include <assert.h>
#include "numo/narray.h"
#include "numo/template.h"
#include "../numo_gsl.h"
#line 15 "../gen/tmpl/lib.c"
#include <gsl/gsl_wavelet.h>
#include <gsl/gsl_wavelet2d.h>

static VALUE mG;



#line 1 "tmpl/wavelet_macro.c"
#define gsl_wavelet2d_free gsl_wavelet_free


#line 1 "tmpl/wavelet_array_check.c"
static int
power_of_two(size_t n)
{
    size_t k = 1;

    while (1) {
        if (n == k) return 1;
        k *= 2;
        if (n < k || k==0) break;
    }
    rb_raise(nary_eShapeError,"array size is not 2**n");
    return 0;
}

static VALUE
wavelet_array_check(VALUE v1, int nd, size_t *size)
{
    size_t    n1, n2;
    VALUE     tmp;
    narray_t *na;

    GetNArray(v1,na);
    if (na->ndim < nd) {
        rb_raise(nary_eDimensionError,"ndim(=%d) should >= %d", na->ndim, nd);
    }
    switch(nd) {
    case 2:
        n1 = na->shape[na->ndim-2];
        n2 = na->shape[na->ndim-1];
        if (n1 != n2) {
            rb_raise(nary_eShapeError,"not square 2d array");
        }
        power_of_two(n1);
        power_of_two(n2);
        *size = n2;
        break;
    case 1:
        n2 = na->shape[na->ndim-1];
        power_of_two(n2);
        *size = n2;
        break;
    default:
        rb_bug("invalid value for nd");
    }
    if (TEST_INPLACE(v1)) {
        v1 = rb_funcall(cDF, rb_intern("cast"), 1, v1);
        if (!RTEST(na_check_contiguous(v1))) {
            v1 = na_copy(v1);
        }
    } else {
        tmp = rb_narray_new(cDF, na->ndim, na->shape);
        rb_funcall(tmp, rb_intern("store"), 1, v1);
        v1 = tmp;
    }
    return v1;
}


#line 1 "../gen/tmpl/class.c"
/*
  class definition: Numo::GSL::WaveletWorkspace
*/

static VALUE cWaveletWorkspace;

static void
wavelet_workspace_free(void *ptr)
{
    gsl_wavelet_workspace_free(ptr);
}

static size_t
wavelet_workspace_memsize(const void *ptr)
{
    return sizeof(gsl_wavelet_workspace);
}

static const rb_data_type_t wavelet_workspace_data_type = {
    "Numo::GSL::WaveletWorkspace",
    {NULL, wavelet_workspace_free, wavelet_workspace_memsize,},
    0, 0, RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED
};



#line 1 "../gen/tmpl/c_new_sizet.c"

#line 5 "../gen/tmpl/c_new_sizet.c"
/*
  @overload new(n)
  @param  [Integer]  n parameter

  allocate instance of WaveletWorkspace class.

 This function allocates a workspace for the discrete wavelet transform.
To perform a one-dimensional transform on n elements, a workspace
of size n must be provided.  For two-dimensional transforms of
n-by-n matrices it is sufficient to allocate a workspace of
size n, since the transform operates on individual rows and
columns. A null pointer is returned if insufficient memory is available.
 */
static VALUE
wavelet_workspace_s_new(VALUE self, VALUE v1)
{
    gsl_wavelet_workspace *w;
    w = gsl_wavelet_workspace_alloc(NUM2SIZET(v1));
    if (!w) {
        rb_raise(rb_eNoMemError,"fail to allocate struct");
    }
    return TypedData_Wrap_Struct(cWaveletWorkspace, &wavelet_workspace_data_type, (void*)w);
}


#line 1 "../gen/tmpl/class.c"
/*
  class definition: Numo::GSL::Wavelet
*/

static VALUE cWavelet;

static void
wavelet_free(void *ptr)
{
    gsl_wavelet_free(ptr);
}

static size_t
wavelet_memsize(const void *ptr)
{
    return sizeof(gsl_wavelet);
}

static const rb_data_type_t wavelet_data_type = {
    "Numo::GSL::Wavelet",
    {NULL, wavelet_free, wavelet_memsize,},
    0, 0, RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED
};



#line 1 "tmpl/wavelet_new.c"

#line 5 "tmpl/wavelet_new.c"
/*
  :nodoc:
 */
static VALUE
wavelet_s_new(VALUE self, const gsl_wavelet_type *t, VALUE v1)
{
    gsl_wavelet *w;
    size_t k;

    k = NUM2SIZET(v1);
    w = gsl_wavelet_alloc(t, k);
    if (!w) {
        rb_raise(rb_eNoMemError,"fail to allocate struct");
    }
    return TypedData_Wrap_Struct(cWavelet, &wavelet_data_type, (void*)w);
}


#line 1 "tmpl/wavelet_type_new.c"
/*
  @overload new(k)
  @param  [DFloat]  k

  Generate an instance of Numo::GSL::Wavelet::Daubechies class,
  a subclass of Numo::GSL::Wavelet class with gsl_wavelet_daubechies type.

  This function allocates and initializes a wavelet object of type
T.  The parameter k selects the specific member of the
wavelet family.  A null pointer is returned if insufficient memory is
available or if a unsupported member is selected.

  */
static VALUE
wavelet_daubechies_s_new(VALUE self, VALUE v1)
{
    return wavelet_s_new(self, gsl_wavelet_daubechies, v1);
}


#line 1 "tmpl/wavelet_type_new.c"
/*
  @overload new(k)
  @param  [DFloat]  k

  Generate an instance of Numo::GSL::Wavelet::DaubechiesCentered class,
  a subclass of Numo::GSL::Wavelet class with gsl_wavelet_daubechies_centered type.

  This function allocates and initializes a wavelet object of type
T.  The parameter k selects the specific member of the
wavelet family.  A null pointer is returned if insufficient memory is
available or if a unsupported member is selected.

  */
static VALUE
wavelet_daubechies_centered_s_new(VALUE self, VALUE v1)
{
    return wavelet_s_new(self, gsl_wavelet_daubechies_centered, v1);
}


#line 1 "tmpl/wavelet_type_new.c"
/*
  @overload new(k)
  @param  [DFloat]  k

  Generate an instance of Numo::GSL::Wavelet::Haar class,
  a subclass of Numo::GSL::Wavelet class with gsl_wavelet_haar type.

  This function allocates and initializes a wavelet object of type
T.  The parameter k selects the specific member of the
wavelet family.  A null pointer is returned if insufficient memory is
available or if a unsupported member is selected.

  */
static VALUE
wavelet_haar_s_new(VALUE self, VALUE v1)
{
    return wavelet_s_new(self, gsl_wavelet_haar, v1);
}


#line 1 "tmpl/wavelet_type_new.c"
/*
  @overload new(k)
  @param  [DFloat]  k

  Generate an instance of Numo::GSL::Wavelet::HaarCentered class,
  a subclass of Numo::GSL::Wavelet class with gsl_wavelet_haar_centered type.

  This function allocates and initializes a wavelet object of type
T.  The parameter k selects the specific member of the
wavelet family.  A null pointer is returned if insufficient memory is
available or if a unsupported member is selected.

  */
static VALUE
wavelet_haar_centered_s_new(VALUE self, VALUE v1)
{
    return wavelet_s_new(self, gsl_wavelet_haar_centered, v1);
}


#line 1 "tmpl/wavelet_type_new.c"
/*
  @overload new(k)
  @param  [DFloat]  k

  Generate an instance of Numo::GSL::Wavelet::Bspline class,
  a subclass of Numo::GSL::Wavelet class with gsl_wavelet_bspline type.

  This function allocates and initializes a wavelet object of type
T.  The parameter k selects the specific member of the
wavelet family.  A null pointer is returned if insufficient memory is
available or if a unsupported member is selected.

  */
static VALUE
wavelet_bspline_s_new(VALUE self, VALUE v1)
{
    return wavelet_s_new(self, gsl_wavelet_bspline, v1);
}


#line 1 "tmpl/wavelet_type_new.c"
/*
  @overload new(k)
  @param  [DFloat]  k

  Generate an instance of Numo::GSL::Wavelet::BsplineCentered class,
  a subclass of Numo::GSL::Wavelet class with gsl_wavelet_bspline_centered type.

  This function allocates and initializes a wavelet object of type
T.  The parameter k selects the specific member of the
wavelet family.  A null pointer is returned if insufficient memory is
available or if a unsupported member is selected.

  */
static VALUE
wavelet_bspline_centered_s_new(VALUE self, VALUE v1)
{
    return wavelet_s_new(self, gsl_wavelet_bspline_centered, v1);
}


#line 1 "../gen/tmpl/c_str_f_void.c"
/*
  @overload name
  @return [String]

  This function returns a pointer to the name of the wavelet family for
w.
*/
static VALUE
wavelet_name(VALUE self)
{
    gsl_wavelet *w;

    TypedData_Get_Struct(self, gsl_wavelet, &wavelet_data_type, w);

    return rb_str_new_cstr(gsl_wavelet_name(w));
}


#line 1 "tmpl/wavelet_transform.c"
static void
iter_wavelet_transform(na_loop_t *const lp)
{
    size_t   n;
    double  *p;
    void   **opts;
    gsl_wavelet *w;
    gsl_wavelet_workspace *ws;
    int      dir;

    opts = (void **)(lp->opt_ptr);
    w    = (gsl_wavelet*)(opts[0]);
    ws   = (gsl_wavelet_workspace*)(opts[1]);
    dir  = *(int*)(opts[2]);

    p = (double*)(lp->args[0].ptr + lp->args[0].iter[0].pos);
    n = lp->args[0].shape[0];
    gsl_wavelet_transform(w, p, 1, n, dir, ws);
}

/*
  @overload transform(data,dir)
  @param  [DFloat]    data
  @param  [Integer]   dir
  @return [DFloat]    result

  
These functions compute in-place forward and inverse discrete wavelet
transforms of length n with stride stride on the array
data. The length of the transform n is restricted to powers
of two.  For the transform version of the function the argument
dir can be either forward (+1) or backward
(-1).  A workspace work of length n must be provided.

For the forward transform, the elements of the original array are 
replaced by the discrete wavelet
transform $f_i \rightarrow w_{j,k}$
f_i -> w_[j,k] 
in a packed triangular storage layout, 
where j is the index of the level 
$j = 0 \dots J-1$
j = 0 ... J-1
and
k is the index of the coefficient within each level,
$k = 0 \dots 2^j - 1$
k = 0 ... (2^j)-1.  
The total number of levels is J = \log_2(n).  The output data
has the following form,

(s_[-1,0], d_[0,0], d_[1,0], d_[1,1], d_[2,0], ..., 
  d_[j,k], ..., d_[J-1,2^[J-1]-1]) 

where the first element is the smoothing coefficient $s_{-1,0}$
s_[-1,0], followed by the detail coefficients $d_{j,k}$
d_[j,k] for each level
j.  The backward transform inverts these coefficients to obtain 
the original data.

These functions return a status of GSL_SUCCESS upon successful
completion.  GSL_EINVAL is returned if n is not an integer
power of 2 or if insufficient workspace is provided.
*/
static VALUE
wavelet_transform(VALUE self, VALUE v1, VALUE v2)
{
    ndfunc_arg_in_t ain[1] = {{OVERWRITE,1}};
    ndfunc_t ndf = {iter_wavelet_transform, NO_LOOP, 1,0, ain,0};
    gsl_wavelet *w;
    gsl_wavelet_workspace *ws;
    size_t    n;
    int       dir;
    void     *opts[3];
    VALUE     vws;

    TypedData_Get_Struct(self, gsl_wavelet, &wavelet_data_type, w);
    opts[0] = w;

    v1 = wavelet_array_check(v1, 1, &n);

    vws = wavelet_workspace_s_new(cWaveletWorkspace, SIZET2NUM(n));
    TypedData_Get_Struct(vws, gsl_wavelet_workspace, &wavelet_workspace_data_type, ws);
    opts[1] = ws;
    dir = NUM2INT(v2);
    opts[2] = &dir;

    na_ndloop3(&ndf, opts, 1, v1);
    RB_GC_GUARD(vws);
    return v1;
}


#line 1 "tmpl/wavelet_transform2.c"
/*
  @overload transform_forward(data)
  @param  [DFloat]    data
  @return [DFloat]    result

  
These functions compute in-place forward and inverse discrete wavelet
transforms of length n with stride stride on the array
data. The length of the transform n is restricted to powers
of two.  For the transform version of the function the argument
dir can be either forward (+1) or backward
(-1).  A workspace work of length n must be provided.

For the forward transform, the elements of the original array are 
replaced by the discrete wavelet
transform $f_i \rightarrow w_{j,k}$
f_i -> w_[j,k] 
in a packed triangular storage layout, 
where j is the index of the level 
$j = 0 \dots J-1$
j = 0 ... J-1
and
k is the index of the coefficient within each level,
$k = 0 \dots 2^j - 1$
k = 0 ... (2^j)-1.  
The total number of levels is J = \log_2(n).  The output data
has the following form,

(s_[-1,0], d_[0,0], d_[1,0], d_[1,1], d_[2,0], ..., 
  d_[j,k], ..., d_[J-1,2^[J-1]-1]) 

where the first element is the smoothing coefficient $s_{-1,0}$
s_[-1,0], followed by the detail coefficients $d_{j,k}$
d_[j,k] for each level
j.  The backward transform inverts these coefficients to obtain 
the original data.

These functions return a status of GSL_SUCCESS upon successful
completion.  GSL_EINVAL is returned if n is not an integer
power of 2 or if insufficient workspace is provided.
*/
static VALUE
wavelet_transform_forward(VALUE self, VALUE v1)
{
    int dir;
    VALUE v2;

    
    dir = gsl_wavelet_forward;
    
#line 19 "tmpl/wavelet_transform2.c"
    v2 = INT2FIX(dir);

    return wavelet_transform(self, v1, v2);
}


#line 1 "tmpl/wavelet_transform2.c"
/*
  @overload transform_inverse(data)
  @param  [DFloat]    data
  @return [DFloat]    result

  
These functions compute in-place forward and inverse discrete wavelet
transforms of length n with stride stride on the array
data. The length of the transform n is restricted to powers
of two.  For the transform version of the function the argument
dir can be either forward (+1) or backward
(-1).  A workspace work of length n must be provided.

For the forward transform, the elements of the original array are 
replaced by the discrete wavelet
transform $f_i \rightarrow w_{j,k}$
f_i -> w_[j,k] 
in a packed triangular storage layout, 
where j is the index of the level 
$j = 0 \dots J-1$
j = 0 ... J-1
and
k is the index of the coefficient within each level,
$k = 0 \dots 2^j - 1$
k = 0 ... (2^j)-1.  
The total number of levels is J = \log_2(n).  The output data
has the following form,

(s_[-1,0], d_[0,0], d_[1,0], d_[1,1], d_[2,0], ..., 
  d_[j,k], ..., d_[J-1,2^[J-1]-1]) 

where the first element is the smoothing coefficient $s_{-1,0}$
s_[-1,0], followed by the detail coefficients $d_{j,k}$
d_[j,k] for each level
j.  The backward transform inverts these coefficients to obtain 
the original data.

These functions return a status of GSL_SUCCESS upon successful
completion.  GSL_EINVAL is returned if n is not an integer
power of 2 or if insufficient workspace is provided.
*/
static VALUE
wavelet_transform_inverse(VALUE self, VALUE v1)
{
    int dir;
    VALUE v2;

    
#line 17 "tmpl/wavelet_transform2.c"
    dir = gsl_wavelet_backward;
    
    v2 = INT2FIX(dir);

    return wavelet_transform(self, v1, v2);
}


#line 1 "../gen/tmpl/class.c"
/*
  class definition: Numo::GSL::Wavelet2D
*/

static VALUE cWavelet2D;

static void
wavelet2d_free(void *ptr)
{
    gsl_wavelet2d_free(ptr);
}

static size_t
wavelet2d_memsize(const void *ptr)
{
    return sizeof(gsl_wavelet);
}

static const rb_data_type_t wavelet2d_data_type = {
    "Numo::GSL::Wavelet2D",
    {NULL, wavelet2d_free, wavelet2d_memsize,},
    0, 0, RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED
};



#line 1 "tmpl/wavelet2d_transform.c"
static void
iter_wavelet2d_transform(na_loop_t *const lp)
{
    size_t   n1, n2;
    double  *p;
    void   **opts;
    gsl_wavelet *w;
    gsl_wavelet_workspace *ws;
    int      dir;

    opts = (void **)(lp->opt_ptr);
    w    = (gsl_wavelet*)(opts[0]);
    ws   = (gsl_wavelet_workspace*)(opts[1]);
    dir  = *(int*)(opts[2]);

    p = (double*)(lp->args[0].ptr + lp->args[0].iter[0].pos);
    n1 = lp->args[0].shape[0];
    n2 = lp->args[0].shape[1];
    gsl_wavelet2d_transform(w, p, n2, n1, n2, dir, ws);
}

/*
  @overload transform(data,dir)
  @param  [DFloat]    data
  @param  [Integer]   dir
  @return [DFloat]    result

  
These functions compute two-dimensional in-place forward and inverse
discrete wavelet transforms in standard form on the
array data stored in row-major form with dimensions size1
and size2 and physical row length tda.  The dimensions must
be equal (square matrix) and are restricted to powers of two.  For the
transform version of the function the argument dir can be
either forward (+1) or backward (-1).  A
workspace work of the appropriate size must be provided.  On exit,
the appropriate elements of the array data are replaced by their
two-dimensional wavelet transform.

The functions return a status of GSL_SUCCESS upon successful
completion.  GSL_EINVAL is returned if size1 and
size2 are not equal and integer powers of 2, or if insufficient
workspace is provided.
*/
static VALUE
wavelet2d_transform(VALUE self, VALUE v1, VALUE v2)
{
    ndfunc_arg_in_t ain[1] = {{OVERWRITE,2}};
    ndfunc_t ndf = {iter_wavelet2d_transform, NO_LOOP, 1,0, ain,0};
    gsl_wavelet *w;
    gsl_wavelet_workspace *a;
    size_t    n;
    int       dir;
    void     *opts[3];
    VALUE     vws;

    TypedData_Get_Struct(self, gsl_wavelet, &wavelet2d_data_type, w);
    opts[0] = w;

    v1 = wavelet_array_check(v1, 2, &n);

    vws = wavelet_workspace_s_new(cWaveletWorkspace, SIZET2NUM(n));
    TypedData_Get_Struct(vws, gsl_wavelet_workspace, &wavelet_workspace_data_type, a);
    opts[1] = a;
    dir = NUM2INT(v2);
    opts[2] = &dir;

    na_ndloop3(&ndf, opts, 1, v1);
    RB_GC_GUARD(vws);
    return v1;
}


#line 1 "tmpl/wavelet_transform2.c"
/*
  @overload transform_forward(data)
  @param  [DFloat]    data
  @return [DFloat]    result

  
These functions compute two-dimensional in-place forward and inverse
discrete wavelet transforms in standard form on the
array data stored in row-major form with dimensions size1
and size2 and physical row length tda.  The dimensions must
be equal (square matrix) and are restricted to powers of two.  For the
transform version of the function the argument dir can be
either forward (+1) or backward (-1).  A
workspace work of the appropriate size must be provided.  On exit,
the appropriate elements of the array data are replaced by their
two-dimensional wavelet transform.

The functions return a status of GSL_SUCCESS upon successful
completion.  GSL_EINVAL is returned if size1 and
size2 are not equal and integer powers of 2, or if insufficient
workspace is provided.
*/
static VALUE
wavelet2d_transform_forward(VALUE self, VALUE v1)
{
    int dir;
    VALUE v2;

    
    dir = gsl_wavelet_forward;
    
#line 19 "tmpl/wavelet_transform2.c"
    v2 = INT2FIX(dir);

    return wavelet2d_transform(self, v1, v2);
}


#line 1 "tmpl/wavelet_transform2.c"
/*
  @overload transform_inverse(data)
  @param  [DFloat]    data
  @return [DFloat]    result

  
These functions compute two-dimensional in-place forward and inverse
discrete wavelet transforms in standard form on the
array data stored in row-major form with dimensions size1
and size2 and physical row length tda.  The dimensions must
be equal (square matrix) and are restricted to powers of two.  For the
transform version of the function the argument dir can be
either forward (+1) or backward (-1).  A
workspace work of the appropriate size must be provided.  On exit,
the appropriate elements of the array data are replaced by their
two-dimensional wavelet transform.

The functions return a status of GSL_SUCCESS upon successful
completion.  GSL_EINVAL is returned if size1 and
size2 are not equal and integer powers of 2, or if insufficient
workspace is provided.
*/
static VALUE
wavelet2d_transform_inverse(VALUE self, VALUE v1)
{
    int dir;
    VALUE v2;

    
#line 17 "tmpl/wavelet_transform2.c"
    dir = gsl_wavelet_backward;
    
    v2 = INT2FIX(dir);

    return wavelet2d_transform(self, v1, v2);
}


#line 1 "tmpl/wavelet2d_transform.c"
static void
iter_wavelet2d_nstransform(na_loop_t *const lp)
{
    size_t   n1, n2;
    double  *p;
    void   **opts;
    gsl_wavelet *w;
    gsl_wavelet_workspace *ws;
    int      dir;

    opts = (void **)(lp->opt_ptr);
    w    = (gsl_wavelet*)(opts[0]);
    ws   = (gsl_wavelet_workspace*)(opts[1]);
    dir  = *(int*)(opts[2]);

    p = (double*)(lp->args[0].ptr + lp->args[0].iter[0].pos);
    n1 = lp->args[0].shape[0];
    n2 = lp->args[0].shape[1];
    gsl_wavelet2d_nstransform(w, p, n2, n1, n2, dir, ws);
}

/*
  @overload nstransform(data,dir)
  @param  [DFloat]    data
  @param  [Integer]   dir
  @return [DFloat]    result

  These functions compute the two-dimensional wavelet transform in
non-standard form.
*/
static VALUE
wavelet2d_nstransform(VALUE self, VALUE v1, VALUE v2)
{
    ndfunc_arg_in_t ain[1] = {{OVERWRITE,2}};
    ndfunc_t ndf = {iter_wavelet2d_nstransform, NO_LOOP, 1,0, ain,0};
    gsl_wavelet *w;
    gsl_wavelet_workspace *a;
    size_t    n;
    int       dir;
    void     *opts[3];
    VALUE     vws;

    TypedData_Get_Struct(self, gsl_wavelet, &wavelet2d_data_type, w);
    opts[0] = w;

    v1 = wavelet_array_check(v1, 2, &n);

    vws = wavelet_workspace_s_new(cWaveletWorkspace, SIZET2NUM(n));
    TypedData_Get_Struct(vws, gsl_wavelet_workspace, &wavelet_workspace_data_type, a);
    opts[1] = a;
    dir = NUM2INT(v2);
    opts[2] = &dir;

    na_ndloop3(&ndf, opts, 1, v1);
    RB_GC_GUARD(vws);
    return v1;
}


#line 1 "tmpl/wavelet_transform2.c"
/*
  @overload nstransform_forward(data)
  @param  [DFloat]    data
  @return [DFloat]    result

  These functions compute the two-dimensional wavelet transform in
non-standard form.
*/
static VALUE
wavelet2d_nstransform_forward(VALUE self, VALUE v1)
{
    int dir;
    VALUE v2;

    
    dir = gsl_wavelet_forward;
    
#line 19 "tmpl/wavelet_transform2.c"
    v2 = INT2FIX(dir);

    return wavelet2d_nstransform(self, v1, v2);
}


#line 1 "tmpl/wavelet_transform2.c"
/*
  @overload nstransform_inverse(data)
  @param  [DFloat]    data
  @return [DFloat]    result

  These functions compute the two-dimensional wavelet transform in
non-standard form.
*/
static VALUE
wavelet2d_nstransform_inverse(VALUE self, VALUE v1)
{
    int dir;
    VALUE v2;

    
#line 17 "tmpl/wavelet_transform2.c"
    dir = gsl_wavelet_backward;
    
    v2 = INT2FIX(dir);

    return wavelet2d_nstransform(self, v1, v2);
}


#line 1 "tmpl/wavelet_new.c"

#line 5 "tmpl/wavelet_new.c"
/*
  :nodoc:
 */
static VALUE
wavelet2d_s_new(VALUE self, const gsl_wavelet_type *t, VALUE v1)
{
    gsl_wavelet *w;
    size_t k;

    k = NUM2SIZET(v1);
    w = gsl_wavelet_alloc(t, k);
    if (!w) {
        rb_raise(rb_eNoMemError,"fail to allocate struct");
    }
    return TypedData_Wrap_Struct(cWavelet2D, &wavelet2d_data_type, (void*)w);
}


#line 1 "tmpl/wavelet_type_new.c"
/*
  @overload new(k)
  @param  [DFloat]  k

  Generate an instance of Numo::GSL::Wavelet2D::GslWaveletDaubechies class,
  a subclass of Numo::GSL::Wavelet2D class with gsl_wavelet_daubechies type.

  This function allocates and initializes a wavelet object of type
T.  The parameter k selects the specific member of the
wavelet family.  A null pointer is returned if insufficient memory is
available or if a unsupported member is selected.

  */
static VALUE
wavelet2d_gsl_wavelet_daubechies_s_new(VALUE self, VALUE v1)
{
    return wavelet2d_s_new(self, gsl_wavelet_daubechies, v1);
}


#line 1 "tmpl/wavelet_type_new.c"
/*
  @overload new(k)
  @param  [DFloat]  k

  Generate an instance of Numo::GSL::Wavelet2D::GslWaveletDaubechiesCentered class,
  a subclass of Numo::GSL::Wavelet2D class with gsl_wavelet_daubechies_centered type.

  This function allocates and initializes a wavelet object of type
T.  The parameter k selects the specific member of the
wavelet family.  A null pointer is returned if insufficient memory is
available or if a unsupported member is selected.

  */
static VALUE
wavelet2d_gsl_wavelet_daubechies_centered_s_new(VALUE self, VALUE v1)
{
    return wavelet2d_s_new(self, gsl_wavelet_daubechies_centered, v1);
}


#line 1 "tmpl/wavelet_type_new.c"
/*
  @overload new(k)
  @param  [DFloat]  k

  Generate an instance of Numo::GSL::Wavelet2D::GslWaveletHaar class,
  a subclass of Numo::GSL::Wavelet2D class with gsl_wavelet_haar type.

  This function allocates and initializes a wavelet object of type
T.  The parameter k selects the specific member of the
wavelet family.  A null pointer is returned if insufficient memory is
available or if a unsupported member is selected.

  */
static VALUE
wavelet2d_gsl_wavelet_haar_s_new(VALUE self, VALUE v1)
{
    return wavelet2d_s_new(self, gsl_wavelet_haar, v1);
}


#line 1 "tmpl/wavelet_type_new.c"
/*
  @overload new(k)
  @param  [DFloat]  k

  Generate an instance of Numo::GSL::Wavelet2D::GslWaveletHaarCentered class,
  a subclass of Numo::GSL::Wavelet2D class with gsl_wavelet_haar_centered type.

  This function allocates and initializes a wavelet object of type
T.  The parameter k selects the specific member of the
wavelet family.  A null pointer is returned if insufficient memory is
available or if a unsupported member is selected.

  */
static VALUE
wavelet2d_gsl_wavelet_haar_centered_s_new(VALUE self, VALUE v1)
{
    return wavelet2d_s_new(self, gsl_wavelet_haar_centered, v1);
}


#line 1 "tmpl/wavelet_type_new.c"
/*
  @overload new(k)
  @param  [DFloat]  k

  Generate an instance of Numo::GSL::Wavelet2D::GslWaveletBspline class,
  a subclass of Numo::GSL::Wavelet2D class with gsl_wavelet_bspline type.

  This function allocates and initializes a wavelet object of type
T.  The parameter k selects the specific member of the
wavelet family.  A null pointer is returned if insufficient memory is
available or if a unsupported member is selected.

  */
static VALUE
wavelet2d_gsl_wavelet_bspline_s_new(VALUE self, VALUE v1)
{
    return wavelet2d_s_new(self, gsl_wavelet_bspline, v1);
}


#line 1 "tmpl/wavelet_type_new.c"
/*
  @overload new(k)
  @param  [DFloat]  k

  Generate an instance of Numo::GSL::Wavelet2D::GslWaveletBsplineCentered class,
  a subclass of Numo::GSL::Wavelet2D class with gsl_wavelet_bspline_centered type.

  This function allocates and initializes a wavelet object of type
T.  The parameter k selects the specific member of the
wavelet family.  A null pointer is returned if insufficient memory is
available or if a unsupported member is selected.

  */
static VALUE
wavelet2d_gsl_wavelet_bspline_centered_s_new(VALUE self, VALUE v1)
{
    return wavelet2d_s_new(self, gsl_wavelet_bspline_centered, v1);
}


#line 28 "../gen/tmpl/lib.c"
void
Init_wavelet(void)
{
    VALUE mN;
    mN = rb_define_module("Numo");
    mG = rb_define_module_under(mN, "GSL");

    


#line 1 "../gen/tmpl/init_class.c"

    /*
      Document-class: Numo::GSL::WaveletWorkspace
      
    */
    {
    cWaveletWorkspace = rb_define_class_under(mG, "WaveletWorkspace", rb_cObject);
    
    rb_undef_alloc_func(cWaveletWorkspace);
    rb_define_singleton_method(cWaveletWorkspace, "new", wavelet_workspace_s_new, 1);
#line 10 "../gen/tmpl/init_class.c"
    }

#line 1 "../gen/tmpl/init_class.c"

    /*
      Document-class: Numo::GSL::Wavelet
      
    */
    {
    cWavelet = rb_define_class_under(mG, "Wavelet", rb_cObject);
    
    rb_undef_alloc_func(cWavelet);
    
    { VALUE cDaubechies = rb_define_class_under(cWavelet, "Daubechies", cWavelet);
      rb_define_singleton_method(cDaubechies, "new", wavelet_daubechies_s_new, 1); }
    { VALUE cDaubechiesCentered = rb_define_class_under(cWavelet, "DaubechiesCentered", cWavelet);
      rb_define_singleton_method(cDaubechiesCentered, "new", wavelet_daubechies_centered_s_new, 1); }
    { VALUE cHaar = rb_define_class_under(cWavelet, "Haar", cWavelet);
      rb_define_singleton_method(cHaar, "new", wavelet_haar_s_new, 1); }
    { VALUE cHaarCentered = rb_define_class_under(cWavelet, "HaarCentered", cWavelet);
      rb_define_singleton_method(cHaarCentered, "new", wavelet_haar_centered_s_new, 1); }
    { VALUE cBspline = rb_define_class_under(cWavelet, "Bspline", cWavelet);
      rb_define_singleton_method(cBspline, "new", wavelet_bspline_s_new, 1); }
    { VALUE cBsplineCentered = rb_define_class_under(cWavelet, "BsplineCentered", cWavelet);
      rb_define_singleton_method(cBsplineCentered, "new", wavelet_bspline_centered_s_new, 1); }
    rb_define_method(cWavelet, "name", wavelet_name, 0);
    rb_define_method(cWavelet, "transform", wavelet_transform, 2);
    rb_define_method(cWavelet, "transform_forward", wavelet_transform_forward, 1);
    rb_define_method(cWavelet, "transform_inverse", wavelet_transform_inverse, 1);
#line 10 "../gen/tmpl/init_class.c"
    }

#line 1 "../gen/tmpl/init_class.c"

    /*
      Document-class: Numo::GSL::Wavelet2D
      
    */
    {
    cWavelet2D = rb_define_class_under(mG, "Wavelet2D", rb_cObject);
    
    rb_undef_alloc_func(cWavelet2D);
    rb_define_method(cWavelet2D, "transform", wavelet2d_transform, 2);
    rb_define_method(cWavelet2D, "transform_forward", wavelet2d_transform_forward, 1);
    rb_define_method(cWavelet2D, "transform_inverse", wavelet2d_transform_inverse, 1);
    rb_define_method(cWavelet2D, "nstransform", wavelet2d_nstransform, 2);
    rb_define_method(cWavelet2D, "nstransform_forward", wavelet2d_nstransform_forward, 1);
    rb_define_method(cWavelet2D, "nstransform_inverse", wavelet2d_nstransform_inverse, 1);
    
    { VALUE cGslWaveletDaubechies = rb_define_class_under(cWavelet2D, "GslWaveletDaubechies", cWavelet2D);
      rb_define_singleton_method(cGslWaveletDaubechies, "new", wavelet2d_gsl_wavelet_daubechies_s_new, 1); }
    { VALUE cGslWaveletDaubechiesCentered = rb_define_class_under(cWavelet2D, "GslWaveletDaubechiesCentered", cWavelet2D);
      rb_define_singleton_method(cGslWaveletDaubechiesCentered, "new", wavelet2d_gsl_wavelet_daubechies_centered_s_new, 1); }
    { VALUE cGslWaveletHaar = rb_define_class_under(cWavelet2D, "GslWaveletHaar", cWavelet2D);
      rb_define_singleton_method(cGslWaveletHaar, "new", wavelet2d_gsl_wavelet_haar_s_new, 1); }
    { VALUE cGslWaveletHaarCentered = rb_define_class_under(cWavelet2D, "GslWaveletHaarCentered", cWavelet2D);
      rb_define_singleton_method(cGslWaveletHaarCentered, "new", wavelet2d_gsl_wavelet_haar_centered_s_new, 1); }
    { VALUE cGslWaveletBspline = rb_define_class_under(cWavelet2D, "GslWaveletBspline", cWavelet2D);
      rb_define_singleton_method(cGslWaveletBspline, "new", wavelet2d_gsl_wavelet_bspline_s_new, 1); }
    { VALUE cGslWaveletBsplineCentered = rb_define_class_under(cWavelet2D, "GslWaveletBsplineCentered", cWavelet2D);
      rb_define_singleton_method(cGslWaveletBsplineCentered, "new", wavelet2d_gsl_wavelet_bspline_centered_s_new, 1); }
#line 10 "../gen/tmpl/init_class.c"
    }
#line 41 "../gen/tmpl/lib.c"
}
