nmatrix-fftw 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/ext/nmatrix/data/complex.h +388 -0
- data/ext/nmatrix/data/data.h +652 -0
- data/ext/nmatrix/data/meta.h +64 -0
- data/ext/nmatrix/data/ruby_object.h +389 -0
- data/ext/nmatrix/math/asum.h +120 -0
- data/ext/nmatrix/math/cblas_enums.h +36 -0
- data/ext/nmatrix/math/cblas_templates_core.h +507 -0
- data/ext/nmatrix/math/gemm.h +241 -0
- data/ext/nmatrix/math/gemv.h +178 -0
- data/ext/nmatrix/math/getrf.h +255 -0
- data/ext/nmatrix/math/getrs.h +121 -0
- data/ext/nmatrix/math/imax.h +79 -0
- data/ext/nmatrix/math/laswp.h +165 -0
- data/ext/nmatrix/math/long_dtype.h +49 -0
- data/ext/nmatrix/math/math.h +745 -0
- data/ext/nmatrix/math/nrm2.h +160 -0
- data/ext/nmatrix/math/rot.h +117 -0
- data/ext/nmatrix/math/rotg.h +106 -0
- data/ext/nmatrix/math/scal.h +71 -0
- data/ext/nmatrix/math/trsm.h +332 -0
- data/ext/nmatrix/math/util.h +148 -0
- data/ext/nmatrix/nm_memory.h +60 -0
- data/ext/nmatrix/nmatrix.h +438 -0
- data/ext/nmatrix/ruby_constants.h +106 -0
- data/ext/nmatrix/storage/common.h +177 -0
- data/ext/nmatrix/storage/dense/dense.h +129 -0
- data/ext/nmatrix/storage/list/list.h +138 -0
- data/ext/nmatrix/storage/storage.h +99 -0
- data/ext/nmatrix/storage/yale/class.h +1139 -0
- data/ext/nmatrix/storage/yale/iterators/base.h +143 -0
- data/ext/nmatrix/storage/yale/iterators/iterator.h +131 -0
- data/ext/nmatrix/storage/yale/iterators/row.h +450 -0
- data/ext/nmatrix/storage/yale/iterators/row_stored.h +140 -0
- data/ext/nmatrix/storage/yale/iterators/row_stored_nd.h +169 -0
- data/ext/nmatrix/storage/yale/iterators/stored_diagonal.h +124 -0
- data/ext/nmatrix/storage/yale/math/transpose.h +110 -0
- data/ext/nmatrix/storage/yale/yale.h +203 -0
- data/ext/nmatrix/types.h +55 -0
- data/ext/nmatrix/util/io.h +115 -0
- data/ext/nmatrix/util/sl_list.h +144 -0
- data/ext/nmatrix/util/util.h +78 -0
- data/ext/nmatrix_fftw/extconf.rb +122 -0
- data/ext/nmatrix_fftw/nmatrix_fftw.cpp +274 -0
- data/lib/nmatrix/fftw.rb +343 -0
- data/spec/00_nmatrix_spec.rb +736 -0
- data/spec/01_enum_spec.rb +190 -0
- data/spec/02_slice_spec.rb +389 -0
- data/spec/03_nmatrix_monkeys_spec.rb +78 -0
- data/spec/2x2_dense_double.mat +0 -0
- data/spec/4x4_sparse.mat +0 -0
- data/spec/4x5_dense.mat +0 -0
- data/spec/blas_spec.rb +193 -0
- data/spec/elementwise_spec.rb +303 -0
- data/spec/homogeneous_spec.rb +99 -0
- data/spec/io/fortran_format_spec.rb +88 -0
- data/spec/io/harwell_boeing_spec.rb +98 -0
- data/spec/io/test.rua +9 -0
- data/spec/io_spec.rb +149 -0
- data/spec/lapack_core_spec.rb +482 -0
- data/spec/leakcheck.rb +16 -0
- data/spec/math_spec.rb +807 -0
- data/spec/nmatrix_yale_resize_test_associations.yaml +2802 -0
- data/spec/nmatrix_yale_spec.rb +286 -0
- data/spec/plugins/fftw/fftw_spec.rb +348 -0
- data/spec/rspec_monkeys.rb +56 -0
- data/spec/rspec_spec.rb +34 -0
- data/spec/shortcuts_spec.rb +310 -0
- data/spec/slice_set_spec.rb +157 -0
- data/spec/spec_helper.rb +149 -0
- data/spec/stat_spec.rb +203 -0
- data/spec/test.pcd +20 -0
- data/spec/utm5940.mtx +83844 -0
- metadata +151 -0
@@ -0,0 +1,78 @@
|
|
1
|
+
/////////////////////////////////////////////////////////////////////
|
2
|
+
// = NMatrix
|
3
|
+
//
|
4
|
+
// A linear algebra library for scientific computation in Ruby.
|
5
|
+
// NMatrix is part of SciRuby.
|
6
|
+
//
|
7
|
+
// NMatrix was originally inspired by and derived from NArray, by
|
8
|
+
// Masahiro Tanaka: http://narray.rubyforge.org
|
9
|
+
//
|
10
|
+
// == Copyright Information
|
11
|
+
//
|
12
|
+
// SciRuby is Copyright (c) 2010 - 2014, Ruby Science Foundation
|
13
|
+
// NMatrix is Copyright (c) 2012 - 2014, John Woods and the Ruby Science Foundation
|
14
|
+
//
|
15
|
+
// Please see LICENSE.txt for additional copyright notices.
|
16
|
+
//
|
17
|
+
// == Contributing
|
18
|
+
//
|
19
|
+
// By contributing source code to SciRuby, you agree to be bound by
|
20
|
+
// our Contributor Agreement:
|
21
|
+
//
|
22
|
+
// * https://github.com/SciRuby/sciruby/wiki/Contributor-Agreement
|
23
|
+
//
|
24
|
+
// == util.h
|
25
|
+
//
|
26
|
+
// Header file for utility functions and data.
|
27
|
+
|
28
|
+
#ifndef UTIL_H
|
29
|
+
#define UTIL_H
|
30
|
+
|
31
|
+
/*
|
32
|
+
* Standard Includes
|
33
|
+
*/
|
34
|
+
|
35
|
+
/*
|
36
|
+
* Project Includes
|
37
|
+
*/
|
38
|
+
|
39
|
+
#include "types.h"
|
40
|
+
|
41
|
+
/*
|
42
|
+
* Macros
|
43
|
+
*/
|
44
|
+
|
45
|
+
/*
|
46
|
+
* Types
|
47
|
+
*/
|
48
|
+
|
49
|
+
/*
|
50
|
+
* Data
|
51
|
+
*/
|
52
|
+
|
53
|
+
/*
|
54
|
+
* Functions
|
55
|
+
*/
|
56
|
+
namespace nm {
|
57
|
+
template <typename Type>
|
58
|
+
inline Type gcf(Type x, Type y) {
|
59
|
+
Type t;
|
60
|
+
|
61
|
+
if (x < 0) x = -x;
|
62
|
+
if (y < 0) y = -y;
|
63
|
+
|
64
|
+
if (x == 0) return y;
|
65
|
+
if (y == 0) return x;
|
66
|
+
|
67
|
+
while (x > 0) {
|
68
|
+
t = x;
|
69
|
+
x = y % x;
|
70
|
+
y = t;
|
71
|
+
}
|
72
|
+
|
73
|
+
return y;
|
74
|
+
}
|
75
|
+
} // end of namespace nm
|
76
|
+
|
77
|
+
|
78
|
+
#endif // UTIL_H
|
@@ -0,0 +1,122 @@
|
|
1
|
+
# = NMatrix
|
2
|
+
#
|
3
|
+
# A linear algebra library for scientific computation in Ruby.
|
4
|
+
# NMatrix is part of SciRuby.
|
5
|
+
#
|
6
|
+
# NMatrix was originally inspired by and derived from NArray, by
|
7
|
+
# Masahiro Tanaka: http://narray.rubyforge.org
|
8
|
+
#
|
9
|
+
# == Copyright Information
|
10
|
+
#
|
11
|
+
# SciRuby is Copyright (c) 2010 - 2014, Ruby Science Foundation
|
12
|
+
# NMatrix is Copyright (c) 2012 - 2014, John Woods and the Ruby Science Foundation
|
13
|
+
#
|
14
|
+
# Please see LICENSE.txt for additional copyright notices.
|
15
|
+
#
|
16
|
+
# == Contributing
|
17
|
+
#
|
18
|
+
# By contributing source code to SciRuby, you agree to be bound by
|
19
|
+
# our Contributor Agreement:
|
20
|
+
#
|
21
|
+
# * https://github.com/SciRuby/sciruby/wiki/Contributor-Agreement
|
22
|
+
#
|
23
|
+
# == nmatrix_fftw/extconf.rb
|
24
|
+
#
|
25
|
+
# This file checks FFTW3 and other necessary headers/shared objects.
|
26
|
+
|
27
|
+
require 'mkmf'
|
28
|
+
|
29
|
+
# Function derived from NArray's extconf.rb.
|
30
|
+
def create_conf_h(file) #:nodoc:
|
31
|
+
print "creating #{file}\n"
|
32
|
+
File.open(file, 'w') do |hfile|
|
33
|
+
header_guard = file.upcase.sub(/\s|\./, '_')
|
34
|
+
|
35
|
+
hfile.puts "#ifndef #{header_guard}"
|
36
|
+
hfile.puts "#define #{header_guard}"
|
37
|
+
hfile.puts
|
38
|
+
|
39
|
+
# FIXME: Find a better way to do this:
|
40
|
+
hfile.puts "#define RUBY_2 1" if RUBY_VERSION >= '2.0'
|
41
|
+
|
42
|
+
for line in $defs
|
43
|
+
line =~ /^-D(.*)/
|
44
|
+
hfile.printf "#define %s 1\n", $1
|
45
|
+
end
|
46
|
+
|
47
|
+
hfile.puts
|
48
|
+
hfile.puts "#endif"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def find_newer_gplusplus #:nodoc:
|
53
|
+
print "checking for apparent GNU g++ binary with C++0x/C++11 support... "
|
54
|
+
[9,8,7,6,5,4,3].each do |minor|
|
55
|
+
ver = "4.#{minor}"
|
56
|
+
gpp = "g++-#{ver}"
|
57
|
+
result = `which #{gpp}`
|
58
|
+
next if result.empty?
|
59
|
+
CONFIG['CXX'] = gpp
|
60
|
+
puts ver
|
61
|
+
return CONFIG['CXX']
|
62
|
+
end
|
63
|
+
false
|
64
|
+
end
|
65
|
+
|
66
|
+
def gplusplus_version
|
67
|
+
cxxvar = proc { |n| `#{CONFIG['CXX']} -E -dM - </dev/null | grep #{n}`.chomp.split(' ')[2] }
|
68
|
+
major = cxxvar.call('__GNUC__')
|
69
|
+
minor = cxxvar.call('__GNUC_MINOR__')
|
70
|
+
patch = cxxvar.call('__GNUC_PATCHLEVEL__')
|
71
|
+
|
72
|
+
raise("unable to determine g++ version (match to get version was nil)") if major.nil? || minor.nil? || patch.nil?
|
73
|
+
|
74
|
+
"#{major}.#{minor}.#{patch}"
|
75
|
+
end
|
76
|
+
|
77
|
+
fftw_libdir = RbConfig::CONFIG['libdir']
|
78
|
+
fftw_incdir = RbConfig::CONFIG['includedir']
|
79
|
+
fftw_srcdir = RbConfig::CONFIG['srcdir']
|
80
|
+
|
81
|
+
$CFLAGS = ["-Wall -Werror=return-type -I$(srcdir)/../nmatrix -I$(srcdir)/lapacke/include",$CFLAGS].join(" ")
|
82
|
+
$CXXFLAGS = ["-Wall -Werror=return-type -I$(srcdir)/../nmatrix -I$(srcdir)/lapacke/include -std=c++11",$CXXFLAGS].join(" ")
|
83
|
+
$CPPFLAGS = ["-Wall -Werror=return-type -I$(srcdir)/../nmatrix -I$(srcdir)/lapacke/include -std=c++11",$CPPFLAGS].join(" ")
|
84
|
+
|
85
|
+
CONFIG['CXX'] = 'g++'
|
86
|
+
|
87
|
+
if CONFIG['CXX'] == 'clang++'
|
88
|
+
$CPP_STANDARD = 'c++11'
|
89
|
+
else
|
90
|
+
version = gplusplus_version
|
91
|
+
if version < '4.3.0' && CONFIG['CXX'] == 'g++' # see if we can find a newer G++, unless it's been overridden by user
|
92
|
+
if !find_newer_gplusplus
|
93
|
+
raise("You need a version of g++ which supports -std=c++0x or -std=c++11. If you're on a Mac and using Homebrew, we recommend using mac-brew-gcc.sh to install a more recent g++.")
|
94
|
+
end
|
95
|
+
version = gplusplus_version
|
96
|
+
end
|
97
|
+
|
98
|
+
if version < '4.7.0'
|
99
|
+
$CPP_STANDARD = 'c++0x'
|
100
|
+
else
|
101
|
+
$CPP_STANDARD = 'c++11'
|
102
|
+
end
|
103
|
+
puts "using C++ standard... #{$CPP_STANDARD}"
|
104
|
+
puts "g++ reports version... " + `#{CONFIG['CXX']} --version|head -n 1|cut -f 3 -d " "`
|
105
|
+
end
|
106
|
+
|
107
|
+
flags = " --include=#{fftw_incdir} --libdir=#{fftw_libdir}"
|
108
|
+
|
109
|
+
if have_library("fftw3")
|
110
|
+
$CFLAGS += [" -lfftw3 -lm #{$CFLAGS} #{$flags}"].join(" ")
|
111
|
+
dir_config('nmatrix_fftw', fftw_incdir, fftw_libdir)
|
112
|
+
dir_config('nmatrix_fftw')
|
113
|
+
end
|
114
|
+
|
115
|
+
create_conf_h("nmatrix_fftw_config.h")
|
116
|
+
create_makefile("nmatrix_fftw")
|
117
|
+
|
118
|
+
# to clean up object files in subdirectories:
|
119
|
+
open('Makefile', 'a') do |f|
|
120
|
+
clean_objs_paths = %w{ }.map { |d| "#{d}/*.#{CONFIG["OBJEXT"]}" }
|
121
|
+
f.write("CLEANOBJS := $(CLEANOBJS) #{clean_objs_paths.join(' ')}")
|
122
|
+
end
|
@@ -0,0 +1,274 @@
|
|
1
|
+
/////////////////////////////////////////////////////////////////////
|
2
|
+
// = NMatrix
|
3
|
+
//
|
4
|
+
// A linear algebra library for scientific computation in Ruby.
|
5
|
+
// NMatrix is part of SciRuby.
|
6
|
+
//
|
7
|
+
// NMatrix was originally inspired by and derived from NArray, by
|
8
|
+
// Masahiro Tanaka: http://narray.rubyforge.org
|
9
|
+
//
|
10
|
+
// == Copyright Information
|
11
|
+
//
|
12
|
+
// SciRuby is Copyright (c) 2010 - 2014, Ruby Science Foundation
|
13
|
+
// NMatrix is Copyright (c) 2012 - 2014, John Woods and the Ruby Science Foundation
|
14
|
+
//
|
15
|
+
// Please see LICENSE.txt for additional copyright notices.
|
16
|
+
//
|
17
|
+
// == Contributing
|
18
|
+
//
|
19
|
+
// By contributing source code to SciRuby, you agree to be bound by
|
20
|
+
// our Contributor Agreement:
|
21
|
+
//
|
22
|
+
// * https://github.com/SciRuby/sciruby/wiki/Contributor-Agreement
|
23
|
+
//
|
24
|
+
// == nmatrix_fftw.cpp
|
25
|
+
//
|
26
|
+
// Main file for nmatrix_fftw extension
|
27
|
+
//
|
28
|
+
|
29
|
+
#include <ruby.h>
|
30
|
+
#include <complex.h>
|
31
|
+
#include <fftw3.h>
|
32
|
+
#include "storage/common.h"
|
33
|
+
#include "nmatrix.h"
|
34
|
+
#include <iostream>
|
35
|
+
|
36
|
+
#define TYPE_COMPLEX_COMPLEX 0
|
37
|
+
#define TYPE_REAL_COMPLEX 1
|
38
|
+
#define TYPE_COMPLEX_REAL 2
|
39
|
+
#define TYPE_REAL_REAL 3
|
40
|
+
|
41
|
+
// @private Used internally by the C API.
|
42
|
+
static VALUE cNMatrix_FFTW_Plan_Data;
|
43
|
+
|
44
|
+
// @private Used internally by the C API.
|
45
|
+
//
|
46
|
+
// ADT for encapsulating various data structures required for sucessfully planning
|
47
|
+
// and executing a fourier transform with FFTW. Uses void* pointers because
|
48
|
+
// input/output can be either double or fftw_complex depending on the type of
|
49
|
+
// FFT being planned.
|
50
|
+
struct fftw_data {
|
51
|
+
void* input;
|
52
|
+
void* output;
|
53
|
+
fftw_plan plan;
|
54
|
+
};
|
55
|
+
|
56
|
+
// @private Used internally by the C API.
|
57
|
+
// Method used by Ruby GC for freeing memory allocated by FFTW.
|
58
|
+
static void nm_fftw_cleanup(fftw_data* d)
|
59
|
+
{
|
60
|
+
xfree(d->input);
|
61
|
+
xfree(d->output);
|
62
|
+
fftw_destroy_plan(d->plan);
|
63
|
+
xfree(d);
|
64
|
+
}
|
65
|
+
|
66
|
+
// @private Used internally by the C API.
|
67
|
+
// Used for converting a Ruby Array containing the shape to a C++ array of ints.
|
68
|
+
static int* nm_fftw_interpret_shape(VALUE rb_shape, const int dimensions)
|
69
|
+
{
|
70
|
+
Check_Type(rb_shape, T_ARRAY);
|
71
|
+
|
72
|
+
int *shape = new int[dimensions];
|
73
|
+
const VALUE *arr = RARRAY_CONST_PTR(rb_shape);
|
74
|
+
|
75
|
+
for (int i = 0; i < dimensions; ++i) {
|
76
|
+
shape[i] = FIX2INT(arr[i]);
|
77
|
+
}
|
78
|
+
|
79
|
+
return shape;
|
80
|
+
}
|
81
|
+
|
82
|
+
// @private Used internally by the C API.
|
83
|
+
// Convert values passed in Ruby Array containing kinds of real-real transforms
|
84
|
+
// to a C array of ints.
|
85
|
+
static void
|
86
|
+
nm_fftw_interpret_real_real_kind(VALUE real_real_kind, int *r2r_kinds)
|
87
|
+
{
|
88
|
+
int size = RARRAY_LEN(real_real_kind);
|
89
|
+
const VALUE *a = RARRAY_CONST_PTR(real_real_kind);
|
90
|
+
for (int i = 0; i < size; ++i) {
|
91
|
+
r2r_kinds[i] = FIX2INT(a[i]);
|
92
|
+
}
|
93
|
+
}
|
94
|
+
|
95
|
+
// @private Used internally by the C API.
|
96
|
+
// Actually calls the FFTW planner routines based on the input/output and the
|
97
|
+
// type of routine selected. Also allocates memory for input and output pointers.
|
98
|
+
static void nm_fftw_actually_create_plan(fftw_data* data,
|
99
|
+
size_t size, const int dimensions, const int* shape, int sign, unsigned flags,
|
100
|
+
VALUE rb_type, VALUE real_real_kind)
|
101
|
+
{
|
102
|
+
switch (FIX2INT(rb_type))
|
103
|
+
{
|
104
|
+
case TYPE_COMPLEX_COMPLEX:
|
105
|
+
data->input = ALLOC_N(fftw_complex, size);
|
106
|
+
data->output = ALLOC_N(fftw_complex, size);
|
107
|
+
data->plan = fftw_plan_dft(dimensions, shape, (fftw_complex*)data->input,
|
108
|
+
(fftw_complex*)data->output, sign, flags);
|
109
|
+
break;
|
110
|
+
case TYPE_REAL_COMPLEX:
|
111
|
+
data->input = ALLOC_N(double , size);
|
112
|
+
data->output = ALLOC_N(fftw_complex, size);
|
113
|
+
data->plan = fftw_plan_dft_r2c(dimensions, shape, (double*)data->input,
|
114
|
+
(fftw_complex*)data->output, flags);
|
115
|
+
break;
|
116
|
+
case TYPE_COMPLEX_REAL:
|
117
|
+
data->input = ALLOC_N(fftw_complex, size);
|
118
|
+
data->output = ALLOC_N(double , size);
|
119
|
+
data->plan = fftw_plan_dft_c2r(dimensions, shape, (fftw_complex*)data->input,
|
120
|
+
(double*)data->output, flags);
|
121
|
+
break;
|
122
|
+
case TYPE_REAL_REAL:
|
123
|
+
int* r2r_kinds = ALLOC_N(int, FIX2INT(real_real_kind));
|
124
|
+
nm_fftw_interpret_real_real_kind(real_real_kind, r2r_kinds);
|
125
|
+
data->input = ALLOC_N(double, size);
|
126
|
+
data->output = ALLOC_N(double, size);
|
127
|
+
data->plan = fftw_plan_r2r(dimensions, shape, (double*)data->input,
|
128
|
+
(double*)data->output, (fftw_r2r_kind*)r2r_kinds, flags);
|
129
|
+
xfree(r2r_kinds);
|
130
|
+
break;
|
131
|
+
}
|
132
|
+
}
|
133
|
+
|
134
|
+
/** \brief Create a plan for performing the fourier transform based on input,
|
135
|
+
* output pointers and the underlying hardware.
|
136
|
+
*
|
137
|
+
* @param[in] self Object on which the function is called
|
138
|
+
* @param[in] rb_shape Shape of the plan.
|
139
|
+
* @param[in] rb_size Size of the plan.
|
140
|
+
* @param[in] rb_dim Dimension of the FFT to be performed.
|
141
|
+
* @param[in] rb_flags Number denoting the planner flags.
|
142
|
+
* @param[in] rb_direction Direction of FFT (can be -1 or +1). Specifies the
|
143
|
+
* sign of the exponent.
|
144
|
+
* @param[in] rb_type Number specifying the type of FFT being planned (one
|
145
|
+
* of :complex_complex, :complex_real, :real_complex and :real_real)
|
146
|
+
* @param[in] rb_real_real_kind Ruby Array specifying the kind of DFT to perform over
|
147
|
+
* each axis in case of a real input/real output FFT.
|
148
|
+
*
|
149
|
+
* \returns An object of type NMatrix::FFTW::Plan::Data that encapsulates the
|
150
|
+
* plan and relevant input/output arrays.
|
151
|
+
*/
|
152
|
+
static VALUE nm_fftw_create_plan(VALUE self, VALUE rb_shape, VALUE rb_size,
|
153
|
+
VALUE rb_dim, VALUE rb_flags, VALUE rb_direction, VALUE rb_type, VALUE rb_real_real_kind)
|
154
|
+
{
|
155
|
+
const int dimensions = FIX2INT(rb_dim);
|
156
|
+
const int* shape = nm_fftw_interpret_shape(rb_shape, dimensions);
|
157
|
+
size_t size = FIX2INT(rb_size);
|
158
|
+
int sign = FIX2INT(rb_direction);
|
159
|
+
unsigned flags = FIX2INT(rb_flags);
|
160
|
+
fftw_data *data = ALLOC(fftw_data);
|
161
|
+
|
162
|
+
nm_fftw_actually_create_plan(data, size, dimensions, shape,
|
163
|
+
sign, flags, rb_type, rb_real_real_kind);
|
164
|
+
|
165
|
+
return Data_Wrap_Struct(cNMatrix_FFTW_Plan_Data, NULL, nm_fftw_cleanup, data);
|
166
|
+
}
|
167
|
+
|
168
|
+
// @private Used internally by the C API.
|
169
|
+
template <typename InputType>
|
170
|
+
static void nm_fftw_actually_set(VALUE nmatrix, VALUE plan_data)
|
171
|
+
{
|
172
|
+
fftw_data* data;
|
173
|
+
Data_Get_Struct(plan_data, fftw_data, data);
|
174
|
+
memcpy((InputType*)data->input, (InputType*)NM_DENSE_ELEMENTS(nmatrix),
|
175
|
+
sizeof(InputType)*NM_DENSE_COUNT(nmatrix));
|
176
|
+
}
|
177
|
+
|
178
|
+
/** \brief Here is a brief description of what this function does.
|
179
|
+
*
|
180
|
+
* @param[in,out] self Object on which the function is called.
|
181
|
+
* @param[in] plan_data An internal data structure of type
|
182
|
+
* NMatrix::FFTW::Plan::Data that is created by Data_Wrap_Struct in
|
183
|
+
* nm_fftw_create_plan and which encapsulates the FFTW plan in a Ruby object.
|
184
|
+
* @param[in] nmatrix An NMatrix object (pre-allocated) which contains the
|
185
|
+
* input elements for the fourier transform.
|
186
|
+
* @param[in] type A number representing the type of fourier transform
|
187
|
+
* being performed. (:complex_complex, :real_complex, :complex_real or :real_real).
|
188
|
+
*
|
189
|
+
* \returns self
|
190
|
+
*/
|
191
|
+
static VALUE nm_fftw_set_input(VALUE self, VALUE nmatrix, VALUE plan_data,
|
192
|
+
VALUE type)
|
193
|
+
{
|
194
|
+
switch(FIX2INT(type))
|
195
|
+
{
|
196
|
+
case TYPE_COMPLEX_COMPLEX:
|
197
|
+
case TYPE_COMPLEX_REAL:
|
198
|
+
nm_fftw_actually_set<fftw_complex>(nmatrix, plan_data);
|
199
|
+
break;
|
200
|
+
case TYPE_REAL_COMPLEX:
|
201
|
+
case TYPE_REAL_REAL:
|
202
|
+
nm_fftw_actually_set<double>(nmatrix, plan_data);
|
203
|
+
break;
|
204
|
+
default:
|
205
|
+
rb_raise(rb_eArgError, "Invalid type of DFT.");
|
206
|
+
}
|
207
|
+
|
208
|
+
return self;
|
209
|
+
}
|
210
|
+
|
211
|
+
// @private Used internally by the C API.
|
212
|
+
// Call fftw_execute and copy the resulting data into the nmatrix object.
|
213
|
+
template <typename OutputType>
|
214
|
+
static void nm_fftw_actually_execute(VALUE nmatrix, VALUE plan_data)
|
215
|
+
{
|
216
|
+
fftw_data *data;
|
217
|
+
Data_Get_Struct(plan_data, fftw_data, data);
|
218
|
+
fftw_execute(data->plan);
|
219
|
+
memcpy((OutputType*)NM_DENSE_ELEMENTS(nmatrix), (OutputType*)data->output,
|
220
|
+
sizeof(OutputType)*NM_DENSE_COUNT(nmatrix));
|
221
|
+
}
|
222
|
+
|
223
|
+
/** \brief Executes the fourier transform by calling the fftw_execute function
|
224
|
+
* and copies the output to the output nmatrix object, which can be accessed from
|
225
|
+
* Ruby.
|
226
|
+
*
|
227
|
+
* @param[in] self Object on which the function is called.
|
228
|
+
* @param[in] plan_data An internal data structure of type
|
229
|
+
* NMatrix::FFTW::Plan::Data that is created by Data_Wrap_Struct in
|
230
|
+
* nm_fftw_create_plan and which encapsulates the FFTW plan in a Ruby object.
|
231
|
+
* @param[in] nmatrix An NMatrix object (pre-allocated) into which the computed
|
232
|
+
* data will be copied.
|
233
|
+
* @param[in] type A number representing the type of fourier transform being
|
234
|
+
* performed. (:complex_complex, :real_complex, :complex_real or :real_real).
|
235
|
+
*
|
236
|
+
* \returns TrueClass if computation completed without errors.
|
237
|
+
*/
|
238
|
+
static VALUE nm_fftw_execute(VALUE self, VALUE nmatrix, VALUE plan_data, VALUE type)
|
239
|
+
{
|
240
|
+
switch(FIX2INT(type))
|
241
|
+
{
|
242
|
+
case TYPE_COMPLEX_COMPLEX:
|
243
|
+
case TYPE_REAL_COMPLEX:
|
244
|
+
nm_fftw_actually_execute<fftw_complex>(nmatrix, plan_data);
|
245
|
+
break;
|
246
|
+
case TYPE_COMPLEX_REAL:
|
247
|
+
case TYPE_REAL_REAL:
|
248
|
+
nm_fftw_actually_execute<double>(nmatrix, plan_data);
|
249
|
+
break;
|
250
|
+
default:
|
251
|
+
rb_raise(rb_eTypeError, "Invalid type of DFT.");
|
252
|
+
}
|
253
|
+
|
254
|
+
return Qtrue;
|
255
|
+
}
|
256
|
+
|
257
|
+
extern "C" {
|
258
|
+
void Init_nmatrix_fftw()
|
259
|
+
{
|
260
|
+
VALUE cNMatrix = rb_define_class("NMatrix", rb_cObject);
|
261
|
+
VALUE cNMatrix_FFTW = rb_define_module_under(cNMatrix, "FFTW");
|
262
|
+
VALUE cNMatrix_FFTW_Plan = rb_define_class_under(cNMatrix_FFTW, "Plan",
|
263
|
+
rb_cObject);
|
264
|
+
VALUE cNMatrix_FFTW_Plan_Data = rb_define_class_under(
|
265
|
+
cNMatrix_FFTW_Plan, "Data", rb_cObject);
|
266
|
+
|
267
|
+
rb_define_private_method(cNMatrix_FFTW_Plan, "c_create_plan",
|
268
|
+
(METHOD)nm_fftw_create_plan, 7);
|
269
|
+
rb_define_private_method(cNMatrix_FFTW_Plan, "c_set_input",
|
270
|
+
(METHOD)nm_fftw_set_input, 3);
|
271
|
+
rb_define_private_method(cNMatrix_FFTW_Plan, "c_execute",
|
272
|
+
(METHOD)nm_fftw_execute, 3);
|
273
|
+
}
|
274
|
+
}
|