/*
fft.c
Ruby/GSL: Ruby extension library for GSL (GNU Scientific Library)
(C) Copyright 2004 by Yoshiki Tsunesada
Ruby/GSL is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License.
This library is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY.
*/
#include "rb_gsl_config.h"
#include "rb_gsl_fft.h"
VALUE mgsl_fft_complex;
VALUE mgsl_fft, mgsl_fft_real, mgsl_fft_halfcomplex;
VALUE cgsl_cparray;
VALUE cgsl_fft_wavetable, cgsl_fft_workspace;
VALUE cgsl_fft_wavetable_factor;
VALUE cgsl_fft_complex_wavetable, cgsl_fft_complex_workspace;
VALUE cgsl_fft_real_wavetable, cgsl_fft_halfcomplex_wavetable;
VALUE cgsl_fft_real_workspace;
VALUE cgsl_vector_halfcomplex;
static GSL_FFT_Workspace* GSL_FFT_Workspace_new(size_t n);
static void GSL_FFT_Workspace_free(GSL_FFT_Workspace *space);
static VALUE rb_gsl_fft_complex_wavetable_new(VALUE klass, VALUE n)
{
CHECK_FIXNUM(n);
return Data_Wrap_Struct(cgsl_fft_complex_wavetable, 0,
gsl_fft_complex_wavetable_free,
gsl_fft_complex_wavetable_alloc(FIX2INT(n)));
}
static VALUE rb_gsl_fft_real_wavetable_new(VALUE klass, VALUE n)
{
CHECK_FIXNUM(n);
return Data_Wrap_Struct(klass, 0, gsl_fft_real_wavetable_free,
gsl_fft_real_wavetable_alloc(FIX2INT(n)));
}
static VALUE rb_gsl_fft_halfcomplex_wavetable_new(VALUE klass, VALUE n)
{
CHECK_FIXNUM(n);
return Data_Wrap_Struct(klass, 0, gsl_fft_halfcomplex_wavetable_free,
gsl_fft_halfcomplex_wavetable_alloc(FIX2INT(n)));
}
static void GSL_FFT_Wavetable_free(GSL_FFT_Wavetable *table)
{
gsl_fft_complex_wavetable_free((gsl_fft_complex_wavetable *) table);
}
static GSL_FFT_Workspace* GSL_FFT_Workspace_new(size_t n)
{
CHECK_FIXNUM(n);
return (GSL_FFT_Workspace *) gsl_fft_complex_workspace_alloc(n);
}
static VALUE rb_gsl_fft_complex_workspace_new(VALUE klass, VALUE n)
{
CHECK_FIXNUM(n);
return Data_Wrap_Struct(klass, 0, gsl_fft_complex_workspace_free,
gsl_fft_complex_workspace_alloc(FIX2INT(n)));
}
static VALUE rb_gsl_fft_real_workspace_new(VALUE klass, VALUE n)
{
CHECK_FIXNUM(n);
return Data_Wrap_Struct(klass, 0, gsl_fft_real_workspace_free,
gsl_fft_real_workspace_alloc(FIX2INT(n)));
}
static void GSL_FFT_Workspace_free(GSL_FFT_Workspace *space)
{
gsl_fft_complex_workspace_free((gsl_fft_complex_workspace *) space);
}
VALUE rb_gsl_vector_new(int argc, VALUE *argv, VALUE klass);
VALUE rb_gsl_permutation_new(VALUE klass, VALUE nn);
static void get_stride_n(int argc, VALUE *argv, int argstart, gsl_vector *v,
size_t *stride, size_t *n);
static VALUE cparray_get(VALUE obj, VALUE ii)
{
gsl_vector *v = NULL;
gsl_complex *c = NULL;
size_t i;
CHECK_FIXNUM(ii);
CHECK_VECTOR(obj);
Data_Get_Struct(obj, gsl_vector, v);
i = FIX2INT(ii);
c = ALLOC(gsl_complex);
GSL_SET_REAL(c, gsl_vector_get(v, 2*i));
GSL_SET_IMAG(c, gsl_vector_get(v, 2*i+1));
return Data_Wrap_Struct(cgsl_complex, 0, free, c);
}
static VALUE cparray_set(int argc, VALUE *argv, VALUE obj)
{
gsl_vector *v = NULL;
gsl_complex *c = NULL;
size_t i;
if (argc < 2) rb_raise(rb_eArgError, "too few arguments");
CHECK_VECTOR(obj);
CHECK_FIXNUM(argv[0]);
i = FIX2INT(argv[0]);
Data_Get_Struct(obj, gsl_vector, v);
if (rb_obj_is_kind_of(argv[1], cgsl_complex)) {
Data_Get_Struct(argv[1], gsl_complex, c);
gsl_vector_set(v, 2*i, GSL_REAL(*c));
gsl_vector_set(v, 2*i+1, GSL_IMAG(*c));
return obj;
}
switch (TYPE(argv[1])) {
case T_ARRAY:
gsl_vector_set(v, 2*i, NUM2DBL(rb_ary_entry(argv[1], 0)));
gsl_vector_set(v, 2*i+1, NUM2DBL(rb_ary_entry(argv[1], 1)));
break;
case T_FLOAT:
case T_FIXNUM:
case T_BIGNUM:
gsl_vector_set(v, 2*i, NUM2DBL(argv[1]));
break;
default:
rb_raise(rb_eTypeError, "wrong type arguments");
break;
}
return obj;
}
static VALUE cparray_real(VALUE obj, VALUE ii)
{
gsl_vector *v = NULL;
CHECK_VECTOR(obj);
CHECK_FIXNUM(ii);
Data_Get_Struct(obj, gsl_vector, v);
return rb_float_new(gsl_vector_get(v, 2*FIX2INT(ii)));
}
static VALUE cparray_re(VALUE obj)
{
gsl_vector *v = NULL;
gsl_vector_view *vv = NULL;
Data_Get_Struct(obj, gsl_vector, v);
vv = gsl_vector_view_alloc();
*vv = gsl_vector_subvector_with_stride(v, 0, 2, v->size/2);
return Data_Wrap_Struct(cgsl_vector_view, 0, gsl_vector_view_free, vv);
}
static VALUE cparray_im(VALUE obj)
{
gsl_vector *v = NULL;
gsl_vector_view *vv = NULL;
Data_Get_Struct(obj, gsl_vector, v);
vv = gsl_vector_view_alloc();
*vv = gsl_vector_subvector_with_stride(v, 1, 2, v->size/2);
return Data_Wrap_Struct(cgsl_vector_view, 0, gsl_vector_view_free, vv);
}
static VALUE cparray_set_real(VALUE obj, VALUE ii, VALUE val)
{
gsl_vector *v = NULL;
CHECK_VECTOR(obj);
CHECK_FIXNUM(ii);
Need_Float(val);
Data_Get_Struct(obj, gsl_vector, v);
gsl_vector_set(v, 2*FIX2INT(ii), NUM2DBL(val));
return obj;
}
static VALUE cparray_imag(VALUE obj, VALUE ii)
{
gsl_vector *v = NULL;
CHECK_VECTOR(obj);
CHECK_FIXNUM(ii);
Data_Get_Struct(obj, gsl_vector, v);
return rb_float_new(gsl_vector_get(v, 2*FIX2INT(ii)+1));
}
static VALUE cparray_set_imag(VALUE obj, VALUE ii, VALUE val)
{
gsl_vector *v = NULL;
CHECK_VECTOR(obj);
CHECK_FIXNUM(ii);
Need_Float(val);
Data_Get_Struct(obj, gsl_vector, v);
gsl_vector_set(v, 2*FIX2INT(ii)+1, NUM2DBL(val));
return obj;
}
static VALUE get_cpary_stride_n(int argc, VALUE *argv, VALUE obj,
gsl_complex_packed_array *data, size_t *stride, size_t *n)
{
gsl_vector *v = NULL;
int itmp = 0;
VALUE ary;
switch (TYPE(obj)) {
case T_MODULE:
case T_CLASS:
case T_OBJECT:
if (argc < 1) rb_raise(rb_eArgError, "wrong number of arguments (%d for >= 1)",
argc);
if (obj == mgsl_fft_complex) {
if (CLASS_OF(argv[0]) != cgsl_cparray)
rb_raise(rb_eTypeError, "wrong argument type %s (expected PackedArray)",
rb_class2name(CLASS_OF(argv[0])));
}
CHECK_VECTOR(argv[0]);
Data_Get_Struct(argv[0], gsl_vector, v);
ary = argv[0];
itmp = 1;
break;
default:
CHECK_VECTOR(obj);
Data_Get_Struct(obj, gsl_vector, v);
ary = obj;
itmp = 0;
break;
}
*data = (gsl_complex_packed_array) v->data;
switch (argc-itmp) {
case 0:
*stride = v->stride;
*n = v->size/2;
break;
case 1:
CHECK_FIXNUM(argv[itmp]);
*n = FIX2INT(argv[itmp]);
*stride = v->stride;
break;
default:
CHECK_FIXNUM(argv[itmp]);
CHECK_FIXNUM(argv[itmp+1]);
*stride = FIX2INT(argv[itmp]);
*n = FIX2INT(argv[itmp+1]);
break;
}
return ary;
}
static void get_stride_n(int argc, VALUE *argv, int argstart, gsl_vector *v,
size_t *stride, size_t *n)
{
switch (argc-argstart) {
case 0:
*stride = v->stride;
*n = v->size;
break;
case 1:
CHECK_FIXNUM(argv[argstart]);
*stride = v->stride;
*n = FIX2INT(argv[argstart]);
break;
default:
CHECK_FIXNUM(argv[argstart]);
CHECK_FIXNUM(argv[argstart+1]);
*stride = FIX2INT(argv[argstart]);
*n = FIX2INT(argv[argstart+1]);
break;
}
return;
}
static VALUE rb_fft_complex_radix2(int argc, VALUE *argv, VALUE obj,
int (*trans)(gsl_complex_packed_array,
size_t, size_t), int flag)
{
size_t stride, n;
gsl_complex_packed_array data;
gsl_vector *v;
VALUE ary;
ary = get_cpary_stride_n(argc, argv, obj, &data, &stride, &n);
if (flag == RB_GSL_FFT_COPY) {
v = gsl_vector_alloc(2*n);
memcpy(v->data, data, sizeof(double)*2*n);
(*trans)(v->data, stride, n);
return Data_Wrap_Struct(cgsl_cparray, 0, gsl_vector_free, v);
} else { /* in-place */
(*trans)(data, stride, n);
return ary;
}
}
static VALUE rb_gsl_fft_complex_radix2_forward(int argc, VALUE *argv, VALUE obj)
{
return rb_fft_complex_radix2(argc, argv, obj, gsl_fft_complex_radix2_forward,
RB_GSL_FFT_COPY);
}
static VALUE rb_gsl_fft_complex_radix2_forward2(int argc, VALUE *argv, VALUE obj)
{
return rb_fft_complex_radix2(argc, argv, obj, gsl_fft_complex_radix2_forward,
RB_GSL_FFT_INPLACE);
}
static VALUE rb_gsl_fft_complex_radix2_transform(int argc, VALUE *argv, VALUE obj)
{
size_t stride, n;
gsl_complex_packed_array data;
gsl_fft_direction sign;
gsl_vector *v;
CHECK_FIXNUM(argv[argc-1]);
sign = FIX2INT(argv[argc-1]);
get_cpary_stride_n(argc-1, argv, obj, &data, &stride, &n);
v = gsl_vector_alloc(2*n);
memcpy(v->data, data, sizeof(double)*2*n);
gsl_fft_complex_radix2_transform(v->data, stride, n, sign);
return Data_Wrap_Struct(cgsl_cparray, 0, gsl_vector_free, v);
}
static VALUE rb_gsl_fft_complex_radix2_transform2(int argc, VALUE *argv, VALUE obj)
{
size_t stride, n;
gsl_complex_packed_array data;
gsl_fft_direction sign;
VALUE ary;
CHECK_FIXNUM(argv[argc-1]);
sign = FIX2INT(argv[argc-1]);
ary = get_cpary_stride_n(argc-1, argv, obj, &data, &stride, &n);
gsl_fft_complex_radix2_transform(data, stride, n, sign);
return ary;
}
static VALUE rb_gsl_fft_complex_radix2_backward(int argc, VALUE *argv, VALUE obj)
{
return rb_fft_complex_radix2(argc, argv, obj, gsl_fft_complex_radix2_backward,
RB_GSL_FFT_COPY);
}
static VALUE rb_gsl_fft_complex_radix2_inverse(int argc, VALUE *argv, VALUE obj)
{
return rb_fft_complex_radix2(argc, argv, obj, gsl_fft_complex_radix2_inverse,
RB_GSL_FFT_COPY);
}
static VALUE rb_gsl_fft_complex_radix2_dif_forward(int argc, VALUE *argv, VALUE obj)
{
return rb_fft_complex_radix2(argc, argv, obj,
gsl_fft_complex_radix2_dif_forward,
RB_GSL_FFT_COPY);
}
static VALUE rb_gsl_fft_complex_radix2_backward2(int argc, VALUE *argv, VALUE obj)
{
return rb_fft_complex_radix2(argc, argv, obj, gsl_fft_complex_radix2_backward,
RB_GSL_FFT_INPLACE);
}
static VALUE rb_gsl_fft_complex_radix2_inverse2(int argc, VALUE *argv, VALUE obj)
{
return rb_fft_complex_radix2(argc, argv, obj, gsl_fft_complex_radix2_inverse,
RB_GSL_FFT_INPLACE);
}
static VALUE rb_gsl_fft_complex_radix2_dif_forward2(int argc, VALUE *argv, VALUE obj)
{
return rb_fft_complex_radix2(argc, argv, obj,
gsl_fft_complex_radix2_dif_forward,
RB_GSL_FFT_INPLACE);
}
static VALUE rb_gsl_fft_complex_radix2_dif_transform(int argc, VALUE *argv, VALUE obj)
{
size_t stride, n;
gsl_complex_packed_array data;
gsl_vector *v;
gsl_fft_direction sign;
CHECK_FIXNUM(argv[argc-1]);
sign = FIX2INT(argv[argc-1]);
get_cpary_stride_n(argc-1, argv, obj, &data, &stride, &n);
v = gsl_vector_alloc(2*n);
memcpy(v->data, data, sizeof(double)*2*n);
gsl_fft_complex_radix2_dif_transform(v->data, stride, n, sign);
return Data_Wrap_Struct(cgsl_cparray, 0, gsl_vector_free, v);
}
/* in-place */
static VALUE rb_gsl_fft_complex_radix2_dif_transform2(int argc, VALUE *argv, VALUE obj)
{
size_t stride, n;
gsl_complex_packed_array data;
gsl_fft_direction sign;
VALUE ary;
CHECK_FIXNUM(argv[argc-1]);
sign = FIX2INT(argv[argc-1]);
ary = get_cpary_stride_n(argc-1, argv, obj, &data, &stride, &n);
gsl_fft_complex_radix2_dif_transform(data, stride, n, sign);
return ary;
}
static VALUE rb_gsl_fft_complex_radix2_dif_backward(int argc, VALUE *argv, VALUE obj)
{
return rb_fft_complex_radix2(argc, argv, obj,
gsl_fft_complex_radix2_dif_backward,
RB_GSL_FFT_COPY);
}
static VALUE rb_gsl_fft_complex_radix2_dif_inverse(int argc, VALUE *argv, VALUE obj)
{
return rb_fft_complex_radix2(argc, argv, obj,
gsl_fft_complex_radix2_dif_inverse,
RB_GSL_FFT_COPY);
}
static VALUE rb_gsl_fft_complex_radix2_dif_backward2(int argc, VALUE *argv, VALUE obj)
{
return rb_fft_complex_radix2(argc, argv, obj,
gsl_fft_complex_radix2_dif_backward,
RB_GSL_FFT_INPLACE);
}
static VALUE rb_gsl_fft_complex_radix2_dif_inverse2(int argc, VALUE *argv, VALUE obj)
{
return rb_fft_complex_radix2(argc, argv, obj,
gsl_fft_complex_radix2_dif_inverse,
RB_GSL_FFT_INPLACE);
}
static VALUE rb_GSL_FFT_Wavetable_new(VALUE klass, VALUE n)
{
GSL_FFT_Wavetable *table;
CHECK_FIXNUM(n);
table = (GSL_FFT_Wavetable *) gsl_fft_complex_wavetable_alloc(FIX2INT(n));
return Data_Wrap_Struct(klass, 0, GSL_FFT_Wavetable_free, table);
}
static VALUE rb_GSL_FFT_Wavetable_n(VALUE obj)
{
GSL_FFT_Wavetable *table;
Data_Get_Struct(obj, GSL_FFT_Wavetable, table);
return INT2FIX(table->n);
}
static VALUE rb_GSL_FFT_Wavetable_nf(VALUE obj)
{
GSL_FFT_Wavetable *table;
Data_Get_Struct(obj, GSL_FFT_Wavetable, table);
return INT2FIX(table->nf);
}
static VALUE rb_GSL_FFT_Wavetable_factor(VALUE obj)
{
GSL_FFT_Wavetable *table;
gsl_permutation *p;
size_t i;
Data_Get_Struct(obj, GSL_FFT_Wavetable, table);
p = gsl_permutation_alloc(64);
for (i = 0; i < table->nf; i++) p->data[i] = table->factor[i];
return Data_Wrap_Struct(cgsl_fft_wavetable_factor, 0, gsl_permutation_free, p);
}
static VALUE rb_GSL_FFT_Workspace_new(VALUE klass, VALUE n)
{
GSL_FFT_Workspace *space;
CHECK_FIXNUM(n);
space = GSL_FFT_Workspace_new(FIX2INT(n));
return Data_Wrap_Struct(klass, 0, GSL_FFT_Workspace_free, space);
}
enum {
NONE_OF_TWO = 0,
ALLOC_SPACE = 1,
ALLOC_TABLE = 2,
BOTH_OF_TWO = 3,
} FFTComplexStructAllocFlag;
static void gsl_fft_free(int flag, GSL_FFT_Wavetable *table,
GSL_FFT_Workspace *space);
static int gsl_fft_get_argv(int argc, VALUE *argv, VALUE obj,
gsl_complex_packed_array *data, size_t *stride,
size_t *n, gsl_fft_complex_wavetable **table,
gsl_fft_complex_workspace **space);
static int gsl_fft_get_argv(int argc, VALUE *argv, VALUE obj,
gsl_complex_packed_array *data, size_t *stride,
size_t *n, gsl_fft_complex_wavetable **table,
gsl_fft_complex_workspace **space)
{
int flag = NONE_OF_TWO, flagtmp, i, itmp = argc, itmp2 = 0, ccc;
int flagw = 0;
gsl_vector *v = NULL;
switch (TYPE(obj)) {
case T_MODULE:
case T_CLASS:
case T_OBJECT:
if (argc < 1) rb_raise(rb_eArgError, "wrong number of arguments (%d for >= 1)",
argc);
if (obj == mgsl_fft_complex) {
if (CLASS_OF(argv[0]) != cgsl_cparray)
rb_raise(rb_eTypeError, "wrong argument type %s (expected PackedArray)",
rb_class2name(CLASS_OF(argv[0])));
}
CHECK_VECTOR(argv[0]);
Data_Get_Struct(argv[0], gsl_vector, v);
itmp2 = 1;
break;
default:
CHECK_VECTOR(obj);
Data_Get_Struct(obj, gsl_vector, v);
break;
}
ccc = argc;
flagtmp = 0;
flagw = 0;
for (i = argc-1; i >= itmp2; i--) {
if (rb_obj_is_kind_of(argv[i], cgsl_fft_workspace)
|| rb_obj_is_kind_of(argv[i], cgsl_fft_complex_workspace)) {
Data_Get_Struct(argv[i], gsl_fft_complex_workspace, *space);
flagtmp = 1;
flagw = 1;
itmp = i;
ccc--;
break;
}
}
flagtmp = 0;
for (i = itmp-1; i >= itmp2; i--) {
if (rb_obj_is_kind_of(argv[i], cgsl_fft_wavetable)
|| rb_obj_is_kind_of(argv[i], cgsl_fft_complex_wavetable)) {
Data_Get_Struct(argv[i], gsl_fft_complex_wavetable, *table);
flagtmp = 1;
ccc--;
break;
}
}
get_cpary_stride_n(ccc, argv, obj, data, stride, n);
if (flagw == 0) {
*space = gsl_fft_complex_workspace_alloc(*n);
flag += ALLOC_SPACE;
}
if (flagtmp == 0) {
*table = gsl_fft_complex_wavetable_alloc(*n);
flag += ALLOC_TABLE;
}
if (*table == NULL) {
rb_raise(rb_eRuntimeError, "something wrong with wavetable");
}
if (*space == NULL) {
rb_raise(rb_eRuntimeError, "something wrong with workspace");
}
return flag;
}
static int gsl_fft_get_argv2(int argc, VALUE *argv, VALUE obj,
double **ptr, size_t *stride,
size_t *n, gsl_fft_real_wavetable **table,
gsl_fft_real_workspace **space, int *naflag)
{
int flag = NONE_OF_TWO, flagtmp, i, itmp = argc, itmp2 = 0, ccc;
int flagw = 0;
*naflag = 0;
switch (TYPE(obj)) {
case T_MODULE:
case T_CLASS:
case T_OBJECT:
if (argc < 1) rb_raise(rb_eArgError, "wrong number of arguments (%d for >= 1)",
argc);
if (obj == mgsl_fft_complex) {
if (CLASS_OF(argv[0]) != cgsl_cparray)
rb_raise(rb_eTypeError, "wrong argument type %s (expected PackedArray)",
rb_class2name(CLASS_OF(argv[0])));
}
*ptr = get_ptr_double3(argv[0], n, stride, naflag);
itmp2 = 1;
break;
default:
*ptr = get_ptr_double3(obj, n, stride, naflag);
break;
}
ccc = argc;
flagtmp = 0;
flagw = 0;
for (i = argc-1; i >= itmp2; i--) {
if (rb_obj_is_kind_of(argv[i], cgsl_fft_real_workspace)) {
Data_Get_Struct(argv[i], gsl_fft_real_workspace, *space);
flagtmp = 1;
flagw = 1;
itmp = i;
ccc--;
break;
}
}
flagtmp = 0;
for (i = itmp-1; i >= itmp2; i--) {
if (rb_obj_is_kind_of(argv[i], cgsl_fft_real_wavetable)) {
Data_Get_Struct(argv[i], gsl_fft_real_wavetable, *table);
flagtmp = 1;
ccc--;
break;
}
}
if (flagw == 0) {
*space = gsl_fft_real_workspace_alloc(*n);
flag += ALLOC_SPACE;
}
if (flagtmp == 0) {
*table = gsl_fft_real_wavetable_alloc(*n);
flag += ALLOC_TABLE;
}
if (*table == NULL) {
rb_raise(rb_eRuntimeError, "something wrong with wavetable");
}
if (*space == NULL) {
rb_raise(rb_eRuntimeError, "something wrong with workspace");
}
return flag;
}
static int gsl_fft_get_argv3(int argc, VALUE *argv, VALUE obj,
double **ptr, size_t *stride,
size_t *n, gsl_fft_halfcomplex_wavetable **table,
gsl_fft_real_workspace **space, int *naflag)
{
int flag = NONE_OF_TWO, flagtmp, i, itmp = argc, itmp2 = 0, ccc;
int flagw = 0;
switch (TYPE(obj)) {
case T_MODULE:
case T_CLASS:
case T_OBJECT:
if (argc < 1) rb_raise(rb_eArgError, "wrong number of arguments (%d for >= 1)",
argc);
if (obj == mgsl_fft_complex) {
if (CLASS_OF(argv[0]) != cgsl_cparray)
rb_raise(rb_eTypeError, "wrong argument type %s (expected PackedArray)",
rb_class2name(CLASS_OF(argv[0])));
}
*ptr = get_ptr_double3(argv[0], n, stride, naflag);
itmp2 = 1;
break;
default:
*ptr = get_ptr_double3(obj, n, stride, naflag);
break;
}
ccc = argc;
flagtmp = 0;
flagw = 0;
for (i = argc-1; i >= itmp2; i--) {
if (rb_obj_is_kind_of(argv[i], cgsl_fft_real_workspace)) {
Data_Get_Struct(argv[i], gsl_fft_real_workspace, *space);
flagtmp = 1;
flagw = 1;
itmp = i;
ccc--;
break;
}
}
flagtmp = 0;
for (i = itmp-1; i >= itmp2; i--) {
if (rb_obj_is_kind_of(argv[i], cgsl_fft_halfcomplex_wavetable)) {
Data_Get_Struct(argv[i], gsl_fft_halfcomplex_wavetable, *table);
flagtmp = 1;
ccc--;
break;
}
}
if (flagw == 0) {
*space = gsl_fft_real_workspace_alloc(*n);
flag += ALLOC_SPACE;
}
if (flagtmp == 0) {
*table = gsl_fft_halfcomplex_wavetable_alloc(*n);
flag += ALLOC_TABLE;
}
if (*table == NULL) {
rb_raise(rb_eRuntimeError, "something wrong with wavetable");
}
if (*space == NULL) {
rb_raise(rb_eRuntimeError, "something wrong with workspace");
}
return flag;
}
static void gsl_fft_free(int flag, GSL_FFT_Wavetable *table,
GSL_FFT_Workspace *space)
{
switch (flag) {
case ALLOC_TABLE:
GSL_FFT_Wavetable_free(table);
break;
case ALLOC_SPACE:
GSL_FFT_Workspace_free(space);
break;
case BOTH_OF_TWO:
GSL_FFT_Wavetable_free(table);
GSL_FFT_Workspace_free(space);
break;
default:
/* never happens */
break;
}
}
static VALUE rb_gsl_fft_getary(int argc, VALUE *argv, VALUE obj)
{
switch (TYPE(obj)) {
case T_MODULE: case T_CLASS: case T_OBJECT:
return argv[0];
break;
default:
return obj;
break;
}
}
static VALUE rb_fft_complex_trans(int argc, VALUE *argv, VALUE obj,
int (*transform)(gsl_complex_packed_array,
size_t, size_t,
const gsl_fft_complex_wavetable *,
gsl_fft_complex_workspace *),
int sss)
{
int flag = 0, status;
size_t stride, n;
gsl_complex_packed_array data;
gsl_vector *v;
gsl_fft_complex_wavetable *table = NULL;
gsl_fft_complex_workspace *space = NULL;
flag = gsl_fft_get_argv(argc, argv, obj, &data, &stride, &n, &table, &space);
if (sss == RB_GSL_FFT_COPY) {
v = gsl_vector_alloc(2*n);
memcpy(v->data, data, sizeof(double)*2*n);
status = (*transform)(v->data, stride, n, table, space);
gsl_fft_free(flag, (GSL_FFT_Wavetable *) table, (GSL_FFT_Workspace *) space);
return Data_Wrap_Struct(cgsl_cparray, 0, gsl_vector_free, v);
} else { /* in-place */
status = (*transform)(data, stride, n, table, space);
gsl_fft_free(flag, (GSL_FFT_Wavetable *) table, (GSL_FFT_Workspace *) space);
return rb_gsl_fft_getary(argc, argv, obj);
}
}
static VALUE rb_gsl_fft_complex_forward(int argc, VALUE *argv, VALUE obj)
{
return rb_fft_complex_trans(argc, argv, obj, gsl_fft_complex_forward,
RB_GSL_FFT_COPY);
}
static VALUE rb_gsl_fft_complex_forward2(int argc, VALUE *argv, VALUE obj)
{
return rb_fft_complex_trans(argc, argv, obj, gsl_fft_complex_forward,
RB_GSL_FFT_INPLACE);
}
static VALUE rb_gsl_fft_complex_transform(int argc, VALUE *argv, VALUE obj)
{
int flag = 0, status;
size_t stride, n;
gsl_vector *v;
gsl_fft_direction sign;
gsl_complex_packed_array data;
gsl_fft_complex_wavetable *table = NULL;
gsl_fft_complex_workspace *space = NULL;
CHECK_FIXNUM(argv[argc-1]);
sign = FIX2INT(argv[argc-1]);
flag = gsl_fft_get_argv(argc-1, argv, obj, &data, &stride, &n, &table, &space);
v = gsl_vector_alloc(2*n);
memcpy(v->data, data, sizeof(double)*2*n);
status = gsl_fft_complex_transform(v->data, stride, n, table, space, sign);
gsl_fft_free(flag, (GSL_FFT_Wavetable *) table, (GSL_FFT_Workspace *) space);
return Data_Wrap_Struct(cgsl_cparray, 0, gsl_vector_free, v);
}
/* in-place */
static VALUE rb_gsl_fft_complex_transform2(int argc, VALUE *argv, VALUE obj)
{
int flag = 0, status;
size_t stride, n;
gsl_fft_direction sign;
gsl_complex_packed_array data;
gsl_fft_complex_wavetable *table = NULL;
gsl_fft_complex_workspace *space = NULL;
CHECK_FIXNUM(argv[argc-1]);
sign = FIX2INT(argv[argc-1]);
flag = gsl_fft_get_argv(argc-1, argv, obj, &data, &stride, &n, &table, &space);
status = gsl_fft_complex_transform(data, stride, n, table, space, sign);
gsl_fft_free(flag, (GSL_FFT_Wavetable *) table, (GSL_FFT_Workspace *) space);
return rb_gsl_fft_getary(argc, argv, obj);
}
static VALUE rb_gsl_fft_complex_backward(int argc, VALUE *argv, VALUE obj)
{
return rb_fft_complex_trans(argc, argv, obj, gsl_fft_complex_backward,
RB_GSL_FFT_COPY);
}
static VALUE rb_gsl_fft_complex_backward2(int argc, VALUE *argv, VALUE obj)
{
return rb_fft_complex_trans(argc, argv, obj, gsl_fft_complex_backward,
RB_GSL_FFT_INPLACE);
}
static VALUE rb_gsl_fft_complex_inverse(int argc, VALUE *argv, VALUE obj)
{
return rb_fft_complex_trans(argc, argv, obj, gsl_fft_complex_inverse,
RB_GSL_FFT_COPY);
}
static VALUE rb_gsl_fft_complex_inverse2(int argc, VALUE *argv, VALUE obj)
{
return rb_fft_complex_trans(argc, argv, obj, gsl_fft_complex_inverse,
RB_GSL_FFT_INPLACE);
}
static VALUE get_ptr_stride_n(int argc, VALUE *argv, VALUE obj,
double **ptr, size_t *stride, size_t *n, int *flag)
{
int itmp = 0;
VALUE ary;
*flag = 0;
switch (TYPE(obj)) {
case T_MODULE:
case T_CLASS:
case T_OBJECT:
if (argc < 1) rb_raise(rb_eArgError, "wrong number of arguments (%d for >= 1)",
argc);
if (obj == mgsl_fft_complex) {
if (CLASS_OF(argv[0]) != cgsl_cparray)
rb_raise(rb_eTypeError, "wrong argument type %s (expected PackedArray)",
rb_class2name(CLASS_OF(argv[0])));
}
*ptr = get_ptr_double3(argv[0], n, stride, flag);
itmp = 1;
ary = argv[0];
break;
default:
*ptr = get_ptr_double3(obj, n, stride, flag);
ary = obj;
itmp = 0;
break;
}
switch (argc-itmp) {
case 0:
/* do nothing */
break;
case 1:
CHECK_FIXNUM(argv[itmp]);
*n = FIX2INT(argv[itmp]);
break;
default:
CHECK_FIXNUM(argv[itmp]);
CHECK_FIXNUM(argv[itmp+1]);
*stride = FIX2INT(argv[itmp]);
*n = FIX2INT(argv[itmp+1]);
break;
}
return ary;
}
static VALUE rb_fft_radix2(int argc, VALUE *argv, VALUE obj,
int (*trans)(double [], size_t, size_t),
int sss)
{
size_t stride, n;
gsl_vector *vnew;
gsl_vector_view vv;
double *ptr1, *ptr2;
int flag;
#ifdef HAVE_NARRAY_H
int shape[1];
#endif
VALUE ary;
get_ptr_stride_n(argc, argv, obj, &ptr1, &stride, &n, &flag);
if (flag == 0) {
if (sss == RB_GSL_FFT_COPY) {
vnew = gsl_vector_alloc(n);
vv.vector.data = ptr1;
vv.vector.stride = stride;
vv.vector.size = n;
gsl_vector_memcpy(vnew, &vv.vector);
ptr2 = vnew->data;
ary = Data_Wrap_Struct(cgsl_vector, 0, gsl_vector_free, vnew);
} else {
ary = rb_gsl_fft_getary(argc, argv, obj);
ptr2 = ptr1;
}
#ifdef HAVE_NARRAY_H
} else if (flag == 1) {
if (sss == RB_GSL_FFT_COPY) {
shape[0] = n;
ary = na_make_object(NA_DFLOAT, 1, shape, cNArray);
ptr2 = NA_PTR_TYPE(ary, double*);
memcpy(ptr2, ptr1, sizeof(double)*n);
} else {
ary = rb_gsl_fft_getary(argc, argv, obj);
ptr2 = NA_PTR_TYPE(ary, double*);
}
#endif
} else {
rb_raise(rb_eRuntimeError, "something wrong");
}
(*trans)(ptr2, stride, n);
return ary;
}
static void rb_fft_radix2_check_arg(int argc, VALUE obj)
{
switch (TYPE(obj)) {
case T_MODULE:
case T_CLASS:
case T_OBJECT:
if (argc != 1 && argc != 3) rb_raise(rb_eArgError,
"wrong number of arguments (%d for 1 or 3)", argc);
break;
default:
/* CHECK_VECTOR(obj);*/
if (argc != 0 && argc != 2) rb_raise(rb_eArgError,
"wrong number of arguments (%d for 0 or 2)", argc);
break;
}
return;
}
static VALUE rb_gsl_fft_real_radix2_transform(int argc, VALUE *argv, VALUE obj)
{
rb_fft_radix2_check_arg(argc, obj);
return rb_fft_radix2(argc, argv, obj, gsl_fft_real_radix2_transform,
RB_GSL_FFT_COPY);
}
static VALUE rb_gsl_fft_real_radix2_transform2(int argc, VALUE *argv, VALUE obj)
{
rb_fft_radix2_check_arg(argc, obj);
return rb_fft_radix2(argc, argv, obj, gsl_fft_real_radix2_transform,
RB_GSL_FFT_INPLACE);
}
static VALUE rb_gsl_fft_halfcomplex_radix2_inverse(int argc, VALUE *argv, VALUE obj)
{
rb_fft_radix2_check_arg(argc, obj);
return rb_fft_radix2(argc, argv, obj, gsl_fft_halfcomplex_radix2_inverse,
RB_GSL_FFT_COPY);
}
static VALUE rb_gsl_fft_halfcomplex_radix2_inverse2(int argc, VALUE *argv, VALUE obj)
{
rb_fft_radix2_check_arg(argc, obj);
return rb_fft_radix2(argc, argv, obj, gsl_fft_halfcomplex_radix2_inverse,
RB_GSL_FFT_INPLACE);
}
static VALUE rb_gsl_fft_halfcomplex_radix2_backward(int argc, VALUE *argv, VALUE obj)
{
rb_fft_radix2_check_arg(argc, obj);
return rb_fft_radix2(argc, argv, obj, gsl_fft_halfcomplex_radix2_backward,
RB_GSL_FFT_COPY);
}
static VALUE rb_gsl_fft_halfcomplex_radix2_backward2(int argc, VALUE *argv, VALUE obj)
{
rb_fft_radix2_check_arg(argc, obj);
return rb_fft_radix2(argc, argv, obj, gsl_fft_halfcomplex_radix2_backward,
RB_GSL_FFT_INPLACE);
}
/*****/
static VALUE rb_fft_real_trans(int argc, VALUE *argv, VALUE obj,
int (*trans)(double [], size_t, size_t,
const gsl_fft_real_wavetable *,
gsl_fft_real_workspace *),
int sss)
{
int flag = 0, status, naflag = 0;
size_t stride, n;
gsl_vector *vnew;
gsl_vector_view vv;
double *ptr1, *ptr2;
#ifdef HAVE_NARRAY_H
int shape[1];
#endif
gsl_fft_real_wavetable *table = NULL;
gsl_fft_real_workspace *space = NULL;
VALUE ary;
flag = gsl_fft_get_argv2(argc, argv, obj, &ptr1, &stride, &n, &table, &space, &naflag);
if (naflag == 0) {
if (sss == RB_GSL_FFT_COPY) {
vnew = gsl_vector_alloc(n);
vv.vector.data = ptr1;
vv.vector.stride = stride;
vv.vector.size = n;
gsl_vector_memcpy(vnew, &vv.vector);
ptr2 = vnew->data;
ary = Data_Wrap_Struct(cgsl_vector_halfcomplex, 0, gsl_vector_free, vnew);
} else {
ptr2 = ptr1;
ary = rb_gsl_fft_getary(argc, argv, obj);
}
#ifdef HAVE_NARRAY_H
} else if (naflag == 1) {
if (sss == RB_GSL_FFT_COPY) {
shape[0] = n;
ary = na_make_object(NA_DFLOAT, 1, shape, cNArray);
ptr2 = NA_PTR_TYPE(ary, double*);
memcpy(ptr2, ptr1, sizeof(double)*n);
} else {
ptr2 = ptr1;
ary = rb_gsl_fft_getary(argc, argv, obj);
}
#endif
} else {
rb_raise(rb_eRuntimeError, "something wrong");
}
status = (*trans)(ptr2, stride, n, table, space);
gsl_fft_free(flag, (GSL_FFT_Wavetable *) table, (GSL_FFT_Workspace *) space);
return ary;
}
static VALUE rb_gsl_fft_real_transform(int argc, VALUE *argv, VALUE obj)
{
return rb_fft_real_trans(argc, argv, obj, gsl_fft_real_transform,
RB_GSL_FFT_COPY);
}
static VALUE rb_gsl_fft_real_transform2(int argc, VALUE *argv, VALUE obj)
{
return rb_fft_real_trans(argc, argv, obj, gsl_fft_real_transform,
RB_GSL_FFT_INPLACE);
}
static VALUE rb_fft_halfcomplex_trans(int argc, VALUE *argv, VALUE obj,
int (*trans)(double [], size_t, size_t,
const gsl_fft_halfcomplex_wavetable *, gsl_fft_real_workspace *),
int sss)
{
int flag = 0, status, naflag = 0;
size_t stride, n;
gsl_vector *vnew;
gsl_vector_view vv;
double *ptr1, *ptr2;
#ifdef HAVE_NARRAY_H
int shape[1];
#endif
gsl_fft_halfcomplex_wavetable *table = NULL;
gsl_fft_real_workspace *space = NULL;
VALUE ary;
flag = gsl_fft_get_argv3(argc, argv, obj, &ptr1, &stride, &n,
&table, &space, &naflag);
if (naflag == 0) {
if (sss == RB_GSL_FFT_COPY) {
vnew = gsl_vector_alloc(n);
vv.vector.data = ptr1;
vv.vector.stride = stride;
vv.vector.size = n;
gsl_vector_memcpy(vnew, &vv.vector);
ptr2 = vnew->data;
ary = Data_Wrap_Struct(cgsl_vector, 0, gsl_vector_free, vnew);
} else {
ptr2 = ptr1;
ary = rb_gsl_fft_getary(argc, argv, obj);
}
#ifdef HAVE_NARRAY_H
} else if (naflag == 1) {
if (sss == RB_GSL_FFT_COPY) {
shape[0] = n;
ary = na_make_object(NA_DFLOAT, 1, shape, cNArray);
ptr2 = NA_PTR_TYPE(ary, double*);
memcpy(ptr2, ptr1, sizeof(double)*n);
} else {
ptr2 = ptr1;
ary = rb_gsl_fft_getary(argc, argv, obj);
}
#endif
} else {
rb_raise(rb_eRuntimeError, "something wrong");
}
status = (*trans)(ptr2, stride, n, table, space);
gsl_fft_free(flag, (GSL_FFT_Wavetable *) table, (GSL_FFT_Workspace *) space);
return ary;
}
static VALUE rb_gsl_fft_halfcomplex_transform(int argc, VALUE *argv, VALUE obj)
{
return rb_fft_halfcomplex_trans(argc, argv, obj,
gsl_fft_halfcomplex_transform,
RB_GSL_FFT_COPY);
}
static VALUE rb_gsl_fft_halfcomplex_transform2(int argc, VALUE *argv, VALUE obj)
{
return rb_fft_halfcomplex_trans(argc, argv, obj,
gsl_fft_halfcomplex_transform,
RB_GSL_FFT_INPLACE);
}
static VALUE rb_gsl_fft_halfcomplex_backward(int argc, VALUE *argv, VALUE obj)
{
return rb_fft_halfcomplex_trans(argc, argv, obj,
gsl_fft_halfcomplex_backward,
RB_GSL_FFT_COPY);
}
static VALUE rb_gsl_fft_halfcomplex_backward2(int argc, VALUE *argv, VALUE obj)
{
return rb_fft_halfcomplex_trans(argc, argv, obj,
gsl_fft_halfcomplex_backward,
RB_GSL_FFT_INPLACE);
}
static VALUE rb_gsl_fft_halfcomplex_inverse(int argc, VALUE *argv, VALUE obj)
{
return rb_fft_halfcomplex_trans(argc, argv, obj,
gsl_fft_halfcomplex_inverse,
RB_GSL_FFT_COPY);
}
static VALUE rb_gsl_fft_halfcomplex_inverse2(int argc, VALUE *argv, VALUE obj)
{
return rb_fft_halfcomplex_trans(argc, argv, obj,
gsl_fft_halfcomplex_inverse,
RB_GSL_FFT_INPLACE);
}
static VALUE rb_gsl_fft_real_unpack(int argc, VALUE *argv, VALUE obj)
{
gsl_vector *v, *cpary;
size_t stride, n;
switch (TYPE(obj)) {
case T_MODULE:
case T_CLASS:
case T_OBJECT:
if (argc < 1) rb_raise(rb_eArgError, "wrong number of arguments (%d for >= 1)",
argc);
CHECK_VECTOR(argv[0]);
Data_Get_Struct(argv[0], gsl_vector, v);
get_stride_n(argc-1, argv, 1, v, &stride, &n);
break;
default:
CHECK_VECTOR(obj);
Data_Get_Struct(obj, gsl_vector, v);
get_stride_n(argc, argv, 0, v, &stride, &n);
break;
}
cpary = gsl_vector_alloc(2*n);
gsl_fft_real_unpack(v->data, (gsl_complex_packed_array) cpary->data, stride, n);
return Data_Wrap_Struct(cgsl_cparray, 0, gsl_vector_free, cpary);
}
static VALUE rb_gsl_fft_halfcomplex_unpack(int argc, VALUE *argv, VALUE obj)
{
gsl_vector *v, *cpary;
size_t stride, n;
switch (TYPE(obj)) {
case T_MODULE:
case T_CLASS:
case T_OBJECT:
if (argc < 1) rb_raise(rb_eArgError, "wrong number of arguments (%d for >= 1)",
argc);
CHECK_VECTOR(argv[0]);
Data_Get_Struct(argv[0], gsl_vector, v);
get_stride_n(argc-1, argv, 1, v, &stride, &n);
break;
default:
Data_Get_Struct(obj, gsl_vector, v);
get_stride_n(argc, argv, 0, v, &stride, &n);
break;
}
cpary = gsl_vector_alloc(2*n);
gsl_fft_halfcomplex_unpack(v->data, (gsl_complex_packed_array) cpary->data, stride, n);
return Data_Wrap_Struct(cgsl_cparray, 0, gsl_vector_free, cpary);
}
/* Convert a halfcomplex data to Numerical Recipes style */
static VALUE rb_gsl_fft_halfcomplex_to_nrc(int argc, VALUE *argv, VALUE obj)
{
gsl_vector *v, *vnew;
size_t i, k;
switch (TYPE(obj)) {
case T_MODULE:
case T_CLASS:
case T_OBJECT:
if (argc != 1) rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)",
argc);
CHECK_VECTOR(argv[0]);
Data_Get_Struct(argv[0], gsl_vector, v);
break;
default:
if (argc != 0) rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)",
argc);
CHECK_VECTOR(obj);
Data_Get_Struct(obj, gsl_vector, v);
break;
}
vnew = gsl_vector_alloc(v->size);
gsl_vector_set(vnew, 0, gsl_vector_get(v, 0)); /* DC */
gsl_vector_set(vnew, 1, gsl_vector_get(v, v->size/2)); /* Nyquist freq */
for (i = 2, k = 1; i < vnew->size; i+=2, k++) {
gsl_vector_set(vnew, i, gsl_vector_get(v, k));
gsl_vector_set(vnew, i+1, -gsl_vector_get(v, v->size-k));
}
return Data_Wrap_Struct(cgsl_vector, 0, gsl_vector_free, vnew);
}
void Init_gsl_fft(VALUE module)
{
VALUE mgsl_fft_complex_radix2, mgsl_fft_real_radix2;
VALUE mgsl_fft_halfcomplex_radix2;
mgsl_fft = rb_define_module_under(module, "FFT");
mgsl_fft_complex = rb_define_module_under(mgsl_fft, "Complex");
mgsl_fft_complex_radix2 = rb_define_module_under(mgsl_fft_complex, "Radix2");
mgsl_fft_real = rb_define_module_under(mgsl_fft, "Real");
mgsl_fft_real_radix2 = rb_define_module_under(mgsl_fft_real, "Radix2");
mgsl_fft_halfcomplex = rb_define_module_under(mgsl_fft, "HalfComplex");
mgsl_fft_halfcomplex_radix2 = rb_define_module_under(mgsl_fft_halfcomplex, "Radix2");
cgsl_vector_halfcomplex = rb_define_class_under(cgsl_vector, "HalfComplex",
cgsl_vector);
/*****/
rb_define_const(mgsl_fft, "Forward", INT2FIX(forward));
rb_define_const(mgsl_fft, "FORWARD", INT2FIX(forward));
rb_define_const(mgsl_fft, "Backward", INT2FIX(backward));
rb_define_const(mgsl_fft, "BACKWARD", INT2FIX(backward));
cgsl_cparray = rb_define_class_under(mgsl_fft_complex, "PackedArray", cgsl_vector);
rb_define_singleton_method(cgsl_cparray, "alloc", rb_gsl_vector_new, -1);
rb_define_method(cgsl_cparray, "get", cparray_get, 1);
rb_define_alias(cgsl_cparray, "[]", "get");
rb_define_method(cgsl_cparray, "real", cparray_real, 1);
rb_define_method(cgsl_cparray, "re", cparray_re, 0);
rb_define_method(cgsl_cparray, "imag", cparray_imag, 1);
rb_define_method(cgsl_cparray, "im", cparray_im, 0);
rb_define_method(cgsl_cparray, "set", cparray_set, -1);
rb_define_alias(cgsl_cparray, "[]=", "set");
rb_define_method(cgsl_cparray, "set_real", cparray_set_real, 2);
rb_define_method(cgsl_cparray, "set_imag", cparray_set_imag, 2);
rb_define_method(cgsl_cparray, "radix2_forward",
rb_gsl_fft_complex_radix2_forward, -1);
rb_define_method(cgsl_cparray, "radix2_transform",
rb_gsl_fft_complex_radix2_transform, -1);
rb_define_method(cgsl_cparray, "radix2_backward",
rb_gsl_fft_complex_radix2_backward, -1);
rb_define_method(cgsl_cparray, "radix2_inverse",
rb_gsl_fft_complex_radix2_inverse, -1);
rb_define_method(cgsl_cparray, "radix2_dif_forward",
rb_gsl_fft_complex_radix2_dif_forward, -1);
rb_define_method(cgsl_cparray, "radix2_dif_transform",
rb_gsl_fft_complex_radix2_dif_transform, -1);
rb_define_method(cgsl_cparray, "radix2_dif_backward",
rb_gsl_fft_complex_radix2_dif_backward, -1);
rb_define_method(cgsl_cparray, "radix2_dif_inverse",
rb_gsl_fft_complex_radix2_dif_inverse, -1);
rb_define_method(cgsl_cparray, "radix2_forward!",
rb_gsl_fft_complex_radix2_forward2, -1);
rb_define_method(cgsl_cparray, "radix2_transform!",
rb_gsl_fft_complex_radix2_transform2, -1);
rb_define_method(cgsl_cparray, "radix2_backward!",
rb_gsl_fft_complex_radix2_backward2, -1);
rb_define_method(cgsl_cparray, "radix2_inverse!",
rb_gsl_fft_complex_radix2_inverse2, -1);
rb_define_method(cgsl_cparray, "radix2_dif_forward!",
rb_gsl_fft_complex_radix2_dif_forward2, -1);
rb_define_method(cgsl_cparray, "radix2_dif_transform!",
rb_gsl_fft_complex_radix2_dif_transform2, -1);
rb_define_method(cgsl_cparray, "radix2_dif_backward!",
rb_gsl_fft_complex_radix2_dif_backward2, -1);
rb_define_method(cgsl_cparray, "radix2_dif_inverse!",
rb_gsl_fft_complex_radix2_dif_inverse2, -1);
cgsl_fft_wavetable = rb_define_class_under(mgsl_fft, "Wavetable", cGSL_Object);
rb_define_singleton_method(cgsl_fft_wavetable, "alloc",
rb_GSL_FFT_Wavetable_new, 1);
rb_define_method(cgsl_fft_wavetable, "n",
rb_GSL_FFT_Wavetable_n, 0);
rb_define_method(cgsl_fft_wavetable, "nf",
rb_GSL_FFT_Wavetable_nf, 0);
rb_define_method(cgsl_fft_wavetable, "factor",
rb_GSL_FFT_Wavetable_factor, 0);
cgsl_fft_wavetable_factor = rb_define_class_under(mgsl_fft,
"WavetableFactor",
cgsl_permutation);
cgsl_fft_complex_wavetable = rb_define_class_under(mgsl_fft_complex, "Wavetable",
cgsl_fft_wavetable);
rb_define_singleton_method(cgsl_fft_complex_wavetable, "alloc",
rb_gsl_fft_complex_wavetable_new, 1);
cgsl_fft_workspace = rb_define_class_under(mgsl_fft, "Workspace", cGSL_Object);
rb_define_singleton_method(cgsl_fft_workspace, "alloc",
rb_GSL_FFT_Workspace_new, 1);
cgsl_fft_complex_workspace = rb_define_class_under(mgsl_fft_complex, "Workspace",
cgsl_fft_workspace);
rb_define_singleton_method(cgsl_fft_complex_workspace, "alloc",
rb_gsl_fft_complex_workspace_new, 1);
rb_define_method(cgsl_cparray, "forward", rb_gsl_fft_complex_forward, -1);
rb_define_method(cgsl_cparray, "transform", rb_gsl_fft_complex_transform, -1);
rb_define_method(cgsl_cparray, "backward", rb_gsl_fft_complex_backward, -1);
rb_define_method(cgsl_cparray, "inverse", rb_gsl_fft_complex_inverse, -1);
rb_define_method(cgsl_cparray, "forward!", rb_gsl_fft_complex_forward2, -1);
rb_define_method(cgsl_cparray, "transform!", rb_gsl_fft_complex_transform2, -1);
rb_define_method(cgsl_cparray, "backward!", rb_gsl_fft_complex_backward2, -1);
rb_define_method(cgsl_cparray, "inverse!", rb_gsl_fft_complex_inverse2, -1);
/*****/
rb_define_method(cgsl_vector, "real_radix2_transform",
rb_gsl_fft_real_radix2_transform, -1);
rb_define_alias(cgsl_vector, "radix2_transform", "real_radix2_transform");
rb_define_alias(cgsl_vector, "radix2_forward", "real_radix2_transform");
rb_define_method(cgsl_vector, "real_radix2_inverse",
rb_gsl_fft_halfcomplex_radix2_inverse, -1);
rb_define_alias(cgsl_vector, "radix2_inverse", "real_radix2_inverse");
rb_define_alias(cgsl_vector, "halfcomplex_radix2_inverse",
"real_radix2_inverse");
rb_define_method(cgsl_vector, "real_radix2_backward",
rb_gsl_fft_halfcomplex_radix2_backward, -1);
rb_define_alias(cgsl_vector, "radix2_backward", "real_radix2_backward");
rb_define_alias(cgsl_vector, "halfcomplex_radix2_backward",
"real_radix2_backward");
rb_define_method(cgsl_vector, "real_radix2_transform!",
rb_gsl_fft_real_radix2_transform2, -1);
rb_define_alias(cgsl_vector, "radix2_transform!", "real_radix2_transform!");
rb_define_alias(cgsl_vector, "radix2_forward!", "real_radix2_transform!");
rb_define_method(cgsl_vector, "real_radix2_inverse!",
rb_gsl_fft_halfcomplex_radix2_inverse2, -1);
rb_define_alias(cgsl_vector, "radix2_inverse!", "real_radix2_inverse!");
rb_define_alias(cgsl_vector, "halfcomplex_radix2_inverse!",
"real_radix2_inverse!");
rb_define_method(cgsl_vector, "real_radix2_backward!",
rb_gsl_fft_halfcomplex_radix2_backward2, -1);
rb_define_alias(cgsl_vector, "radix2_backward!", "real_radix2_backward!");
rb_define_alias(cgsl_vector, "halfcomplex_radix2_backward!",
"real_radix2_backward!");
/*****/
cgsl_fft_real_wavetable = rb_define_class_under(mgsl_fft_real, "Wavetable",
cgsl_fft_wavetable);
rb_define_singleton_method(cgsl_fft_real_wavetable, "alloc",
rb_gsl_fft_real_wavetable_new, 1);
cgsl_fft_halfcomplex_wavetable = rb_define_class_under(mgsl_fft_halfcomplex,
"Wavetable", cgsl_fft_wavetable);
rb_define_singleton_method(cgsl_fft_halfcomplex_wavetable, "alloc",
rb_gsl_fft_halfcomplex_wavetable_new, 1);
/*****/
cgsl_fft_real_workspace = rb_define_class_under(mgsl_fft_real, "Workspace",
cgsl_fft_workspace);
rb_define_singleton_method(cgsl_fft_real_workspace, "alloc",
rb_gsl_fft_real_workspace_new, 1);
/*****/
rb_define_method(cgsl_vector, "real_transform", rb_gsl_fft_real_transform, -1);
rb_define_alias(cgsl_vector, "transform", "real_transform");
rb_define_alias(cgsl_vector, "forward", "real_transform");
rb_define_alias(cgsl_vector, "fft_forward", "real_transform");
rb_define_alias(cgsl_vector, "fft", "real_transform");
rb_define_method(cgsl_vector, "halfcomplex_transform",
rb_gsl_fft_halfcomplex_transform, -1);
rb_define_method(cgsl_vector, "halfcomplex_backward",
rb_gsl_fft_halfcomplex_backward, -1);
rb_define_alias(cgsl_vector, "backward", "halfcomplex_backward");
rb_define_alias(cgsl_vector, "fft_backward", "halfcomplex_backward");
rb_define_method(cgsl_vector, "halfcomplex_inverse",
rb_gsl_fft_halfcomplex_inverse, -1);
rb_define_alias(cgsl_vector, "fft_inverse", "halfcomplex_inverse");
rb_define_alias(cgsl_vector, "ifft", "halfcomplex_inverse");
rb_define_alias(cgsl_vector, "inverse", "halfcomplex_inverse");
rb_define_method(cgsl_vector, "real_transform!", rb_gsl_fft_real_transform2, -1);
rb_define_alias(cgsl_vector, "transform!", "real_transform!");
rb_define_alias(cgsl_vector, "forward!", "real_transform!");
rb_define_alias(cgsl_vector, "fft_forward!", "real_transform!");
rb_define_alias(cgsl_vector, "fft!", "real_transform!");
rb_define_method(cgsl_vector, "halfcomplex_transform!",
rb_gsl_fft_halfcomplex_transform2, -1);
rb_define_method(cgsl_vector, "halfcomplex_backward!",
rb_gsl_fft_halfcomplex_backward2, -1);
rb_define_alias(cgsl_vector, "backward!", "halfcomplex_backward!");
rb_define_alias(cgsl_vector, "fft_backward!", "halfcomplex_backward!");
rb_define_method(cgsl_vector, "halfcomplex_inverse!",
rb_gsl_fft_halfcomplex_inverse2, -1);
rb_define_alias(cgsl_vector, "fft_inverse!", "halfcomplex_inverse!");
rb_define_alias(cgsl_vector, "ifft!", "halfcomplex_inverse!");
rb_define_alias(cgsl_vector, "inverse!", "halfcomplex_inverse!");
/***/
rb_define_method(cgsl_vector, "fft_real_unpack", rb_gsl_fft_real_unpack, -1);
rb_define_alias(cgsl_vector, "real_unpack", "fft_real_unpack");
rb_define_method(cgsl_vector, "fft_halfcomplex_unpack",
rb_gsl_fft_halfcomplex_unpack, -1);
rb_define_alias(cgsl_vector, "halfcomplex_unpack", "fft_halfcomplex_unpack");
/*****/
rb_define_singleton_method(mgsl_fft_complex, "radix2_forward",
rb_gsl_fft_complex_radix2_forward, -1);
rb_define_singleton_method(mgsl_fft_complex, "radix2_transform",
rb_gsl_fft_complex_radix2_transform, -1);
rb_define_singleton_method(mgsl_fft_complex, "radix2_backward",
rb_gsl_fft_complex_radix2_backward, -1);
rb_define_singleton_method(mgsl_fft_complex, "radix2_inverse",
rb_gsl_fft_complex_radix2_inverse, -1);
rb_define_singleton_method(mgsl_fft_complex, "radix2_dif_forward",
rb_gsl_fft_complex_radix2_dif_forward, -1);
rb_define_singleton_method(mgsl_fft_complex, "radix2_dif_transform",
rb_gsl_fft_complex_radix2_dif_transform, -1);
rb_define_singleton_method(mgsl_fft_complex, "radix2_dif_backward",
rb_gsl_fft_complex_radix2_dif_backward, -1);
rb_define_singleton_method(mgsl_fft_complex, "radix2_dif_inverse",
rb_gsl_fft_complex_radix2_dif_inverse, -1);
rb_define_singleton_method(mgsl_fft_complex_radix2, "forward",
rb_gsl_fft_complex_radix2_forward, -1);
rb_define_singleton_method(mgsl_fft_complex_radix2, "transform",
rb_gsl_fft_complex_radix2_transform, -1);
rb_define_singleton_method(mgsl_fft_complex_radix2, "backward",
rb_gsl_fft_complex_radix2_backward, -1);
rb_define_singleton_method(mgsl_fft_complex_radix2, "inverse",
rb_gsl_fft_complex_radix2_inverse, -1);
rb_define_singleton_method(mgsl_fft_complex_radix2, "dif_forward",
rb_gsl_fft_complex_radix2_dif_forward, -1);
rb_define_singleton_method(mgsl_fft_complex_radix2, "dif_transform",
rb_gsl_fft_complex_radix2_dif_transform, -1);
rb_define_singleton_method(mgsl_fft_complex_radix2, "dif_backward",
rb_gsl_fft_complex_radix2_dif_backward, -1);
rb_define_singleton_method(mgsl_fft_complex_radix2, "dif_inverse",
rb_gsl_fft_complex_radix2_dif_inverse, -1);
rb_define_singleton_method(mgsl_fft_complex, "forward",
rb_gsl_fft_complex_forward, -1);
rb_define_singleton_method(mgsl_fft_complex, "transform",
rb_gsl_fft_complex_transform, -1);
rb_define_singleton_method(mgsl_fft_complex, "backward",
rb_gsl_fft_complex_backward, -1);
rb_define_singleton_method(mgsl_fft_complex, "inverse",
rb_gsl_fft_complex_inverse, -1);
rb_define_singleton_method(mgsl_fft_real, "radix2_transform",
rb_gsl_fft_real_radix2_transform, -1);
rb_define_singleton_method(mgsl_fft_real, "radix2_forward",
rb_gsl_fft_real_radix2_transform, -1);
rb_define_singleton_method(mgsl_fft_halfcomplex, "radix2_inverse",
rb_gsl_fft_halfcomplex_radix2_inverse, -1);
rb_define_singleton_method(mgsl_fft_halfcomplex, "radix2_backward",
rb_gsl_fft_halfcomplex_radix2_backward, -1);
rb_define_singleton_method(mgsl_fft_real_radix2, "transform",
rb_gsl_fft_real_radix2_transform, -1);
rb_define_singleton_method(mgsl_fft_real_radix2, "forward",
rb_gsl_fft_real_radix2_transform, -1);
rb_define_singleton_method(mgsl_fft_halfcomplex_radix2, "inverse",
rb_gsl_fft_halfcomplex_radix2_inverse, -1);
rb_define_singleton_method(mgsl_fft_halfcomplex_radix2, "backward",
rb_gsl_fft_halfcomplex_radix2_backward, -1);
rb_define_singleton_method(mgsl_fft_real, "transform",
rb_gsl_fft_real_transform, -1);
rb_define_singleton_method(mgsl_fft_halfcomplex, "transform",
rb_gsl_fft_halfcomplex_transform, -1);
rb_define_singleton_method(mgsl_fft_halfcomplex, "inverse",
rb_gsl_fft_halfcomplex_inverse, -1);
rb_define_singleton_method(mgsl_fft_halfcomplex, "backward",
rb_gsl_fft_halfcomplex_backward, -1);
/***/
rb_define_singleton_method(mgsl_fft_complex, "radix2_forward!",
rb_gsl_fft_complex_radix2_forward2, -1);
rb_define_singleton_method(mgsl_fft_complex, "radix2_transform!",
rb_gsl_fft_complex_radix2_transform2, -1);
rb_define_singleton_method(mgsl_fft_complex, "radix2_backward!",
rb_gsl_fft_complex_radix2_backward2, -1);
rb_define_singleton_method(mgsl_fft_complex, "radix2_inverse!",
rb_gsl_fft_complex_radix2_inverse2, -1);
rb_define_singleton_method(mgsl_fft_complex, "radix2_dif_forward!",
rb_gsl_fft_complex_radix2_dif_forward2, -1);
rb_define_singleton_method(mgsl_fft_complex, "radix2_dif_transform!",
rb_gsl_fft_complex_radix2_dif_transform2, -1);
rb_define_singleton_method(mgsl_fft_complex, "radix2_dif_backward!",
rb_gsl_fft_complex_radix2_dif_backward2, -1);
rb_define_singleton_method(mgsl_fft_complex, "radix2_dif_inverse!",
rb_gsl_fft_complex_radix2_dif_inverse2, -1);
rb_define_singleton_method(mgsl_fft_complex_radix2, "forward!",
rb_gsl_fft_complex_radix2_forward2, -1);
rb_define_singleton_method(mgsl_fft_complex_radix2, "transform!",
rb_gsl_fft_complex_radix2_transform2, -1);
rb_define_singleton_method(mgsl_fft_complex_radix2, "backward!",
rb_gsl_fft_complex_radix2_backward2, -1);
rb_define_singleton_method(mgsl_fft_complex_radix2, "inverse!",
rb_gsl_fft_complex_radix2_inverse2, -1);
rb_define_singleton_method(mgsl_fft_complex_radix2, "dif_forward!",
rb_gsl_fft_complex_radix2_dif_forward2, -1);
rb_define_singleton_method(mgsl_fft_complex_radix2, "dif_transform!",
rb_gsl_fft_complex_radix2_dif_transform2, -1);
rb_define_singleton_method(mgsl_fft_complex_radix2, "dif_backward!",
rb_gsl_fft_complex_radix2_dif_backward2, -1);
rb_define_singleton_method(mgsl_fft_complex_radix2, "dif_inverse!",
rb_gsl_fft_complex_radix2_dif_inverse2, -1);
rb_define_singleton_method(mgsl_fft_complex, "forward!",
rb_gsl_fft_complex_forward2, -1);
rb_define_singleton_method(mgsl_fft_complex, "transform!",
rb_gsl_fft_complex_transform2, -1);
rb_define_singleton_method(mgsl_fft_complex, "backward!",
rb_gsl_fft_complex_backward2, -1);
rb_define_singleton_method(mgsl_fft_complex, "inverse!",
rb_gsl_fft_complex_inverse2, -1);
rb_define_singleton_method(mgsl_fft_real, "radix2_transform!",
rb_gsl_fft_real_radix2_transform2, -1);
rb_define_singleton_method(mgsl_fft_real, "radix2_forward!",
rb_gsl_fft_real_radix2_transform2, -1);
rb_define_singleton_method(mgsl_fft_halfcomplex, "radix2_inverse!",
rb_gsl_fft_halfcomplex_radix2_inverse2, -1);
rb_define_singleton_method(mgsl_fft_halfcomplex, "radix2_backward!",
rb_gsl_fft_halfcomplex_radix2_backward2, -1);
rb_define_singleton_method(mgsl_fft_real_radix2, "transform!",
rb_gsl_fft_real_radix2_transform2, -1);
rb_define_singleton_method(mgsl_fft_real_radix2, "forward!",
rb_gsl_fft_real_radix2_transform2, -1);
rb_define_singleton_method(mgsl_fft_halfcomplex_radix2, "inverse!",
rb_gsl_fft_halfcomplex_radix2_inverse2, -1);
rb_define_singleton_method(mgsl_fft_halfcomplex_radix2, "backward!",
rb_gsl_fft_halfcomplex_radix2_backward2, -1);
rb_define_singleton_method(mgsl_fft_real, "transform!",
rb_gsl_fft_real_transform2, -1);
rb_define_singleton_method(mgsl_fft_halfcomplex, "transform!",
rb_gsl_fft_halfcomplex_transform2, -1);
rb_define_singleton_method(mgsl_fft_halfcomplex, "inverse!",
rb_gsl_fft_halfcomplex_inverse2, -1);
rb_define_singleton_method(mgsl_fft_halfcomplex, "backward!",
rb_gsl_fft_halfcomplex_backward2, -1);
/***/
rb_define_singleton_method(mgsl_fft_real, "unpack",
rb_gsl_fft_real_unpack, -1);
rb_define_singleton_method(mgsl_fft_halfcomplex, "unpack",
rb_gsl_fft_halfcomplex_unpack, -1);
/*****/
rb_define_singleton_method(mgsl_fft_halfcomplex, "to_nrc_order",
rb_gsl_fft_halfcomplex_to_nrc, -1);
rb_define_method(cgsl_vector, "to_nrc_order",
rb_gsl_fft_halfcomplex_to_nrc, -1);
}
syntax highlighted by Code2HTML, v. 0.9.1