numo-pocketfft 0.1.1 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 170eebc1e93586a62ba569d77a3a48bf8c1deb2a
4
- data.tar.gz: a40006057f6538de447002968f1e5d17d7f72ab3
2
+ SHA256:
3
+ metadata.gz: 556745bf510d218d861de24e22d3a29397ba1a3a257bbb1158c8304c41026961
4
+ data.tar.gz: cbacdc59578ef51926057807412f841f6871e2a5c3cb53e8b48bee6eef9c3a4e
5
5
  SHA512:
6
- metadata.gz: 2a93c018c1f75ad1c903d5235e874ed6e881cddf33523ac9be7ebff7c047e2767561db48204c2a5ec13f72d243cee1e49394bfa0362b63b20f395245801700d9
7
- data.tar.gz: 4c23f877e13768d2641f69ddf000b54603038df559b250179a320f395c0920f31a162cfb76b2bde310add0ea1ce8f8b5540da8429dfaf2b93b9c64dc5ca8539c
6
+ metadata.gz: e47fdf6864f08e0bd16dbe0b1b9651f6e83dd2a24e6be28e3490121fa15dd03629f6e6252c4b516da05265a5aab8fb7f275ccd5b11b278fe943922ec85406457
7
+ data.tar.gz: 575423a6d7b2cba2d087af77fa5106591c2bc7208b4cf0d569289b1dfe13eef6b5ed1e836b5dc69dc8a9d899000e48a14fc815685685eed0fd0469dfe1ed287a
data/.clang-format ADDED
@@ -0,0 +1,149 @@
1
+ ---
2
+ Language: Cpp
3
+ # BasedOnStyle: LLVM
4
+ AccessModifierOffset: -2
5
+ AlignAfterOpenBracket: Align
6
+ AlignConsecutiveMacros: false
7
+ AlignConsecutiveAssignments: false
8
+ AlignConsecutiveBitFields: false
9
+ AlignConsecutiveDeclarations: false
10
+ AlignEscapedNewlines: Right
11
+ AlignOperands: Align
12
+ AlignTrailingComments: true
13
+ AllowAllArgumentsOnNextLine: true
14
+ AllowAllConstructorInitializersOnNextLine: true
15
+ AllowAllParametersOfDeclarationOnNextLine: true
16
+ AllowShortEnumsOnASingleLine: true
17
+ AllowShortBlocksOnASingleLine: Never
18
+ AllowShortCaseLabelsOnASingleLine: false
19
+ AllowShortFunctionsOnASingleLine: All
20
+ AllowShortLambdasOnASingleLine: All
21
+ AllowShortIfStatementsOnASingleLine: Never
22
+ AllowShortLoopsOnASingleLine: false
23
+ AlwaysBreakAfterDefinitionReturnType: None
24
+ AlwaysBreakAfterReturnType: None
25
+ AlwaysBreakBeforeMultilineStrings: false
26
+ AlwaysBreakTemplateDeclarations: MultiLine
27
+ BinPackArguments: true
28
+ BinPackParameters: true
29
+ BraceWrapping:
30
+ AfterCaseLabel: false
31
+ AfterClass: false
32
+ AfterControlStatement: Never
33
+ AfterEnum: false
34
+ AfterFunction: false
35
+ AfterNamespace: false
36
+ AfterObjCDeclaration: false
37
+ AfterStruct: false
38
+ AfterUnion: false
39
+ AfterExternBlock: false
40
+ BeforeCatch: false
41
+ BeforeElse: false
42
+ BeforeLambdaBody: false
43
+ BeforeWhile: false
44
+ IndentBraces: false
45
+ SplitEmptyFunction: true
46
+ SplitEmptyRecord: true
47
+ SplitEmptyNamespace: true
48
+ BreakBeforeBinaryOperators: None
49
+ BreakBeforeBraces: Attach
50
+ BreakBeforeInheritanceComma: false
51
+ BreakInheritanceList: BeforeColon
52
+ BreakBeforeTernaryOperators: true
53
+ BreakConstructorInitializersBeforeComma: false
54
+ BreakConstructorInitializers: BeforeColon
55
+ BreakAfterJavaFieldAnnotations: false
56
+ BreakStringLiterals: true
57
+ ColumnLimit: 128
58
+ CommentPragmas: '^ IWYU pragma:'
59
+ CompactNamespaces: false
60
+ ConstructorInitializerAllOnOneLineOrOnePerLine: false
61
+ ConstructorInitializerIndentWidth: 4
62
+ ContinuationIndentWidth: 4
63
+ Cpp11BracedListStyle: true
64
+ DeriveLineEnding: true
65
+ DerivePointerAlignment: false
66
+ DisableFormat: false
67
+ ExperimentalAutoDetectBinPacking: false
68
+ FixNamespaceComments: true
69
+ ForEachMacros:
70
+ - foreach
71
+ - Q_FOREACH
72
+ - BOOST_FOREACH
73
+ IncludeBlocks: Preserve
74
+ IncludeCategories:
75
+ - Regex: '^"(llvm|llvm-c|clang|clang-c)/'
76
+ Priority: 2
77
+ SortPriority: 0
78
+ - Regex: '^(<|"(gtest|gmock|isl|json)/)'
79
+ Priority: 3
80
+ SortPriority: 0
81
+ - Regex: '.*'
82
+ Priority: 1
83
+ SortPriority: 0
84
+ IncludeIsMainRegex: '(Test)?$'
85
+ IncludeIsMainSourceRegex: ''
86
+ IndentCaseLabels: false
87
+ IndentCaseBlocks: false
88
+ IndentGotoLabels: true
89
+ IndentPPDirectives: None
90
+ IndentExternBlock: AfterExternBlock
91
+ IndentWidth: 2
92
+ IndentWrappedFunctionNames: false
93
+ InsertTrailingCommas: None
94
+ JavaScriptQuotes: Leave
95
+ JavaScriptWrapImports: true
96
+ KeepEmptyLinesAtTheStartOfBlocks: true
97
+ MacroBlockBegin: ''
98
+ MacroBlockEnd: ''
99
+ MaxEmptyLinesToKeep: 1
100
+ NamespaceIndentation: None
101
+ ObjCBinPackProtocolList: Auto
102
+ ObjCBlockIndentWidth: 2
103
+ ObjCBreakBeforeNestedBlockParam: true
104
+ ObjCSpaceAfterProperty: false
105
+ ObjCSpaceBeforeProtocolList: true
106
+ PenaltyBreakAssignment: 2
107
+ PenaltyBreakBeforeFirstCallParameter: 19
108
+ PenaltyBreakComment: 300
109
+ PenaltyBreakFirstLessLess: 120
110
+ PenaltyBreakString: 1000
111
+ PenaltyBreakTemplateDeclaration: 10
112
+ PenaltyExcessCharacter: 1000000
113
+ PenaltyReturnTypeOnItsOwnLine: 60
114
+ PointerAlignment: Left
115
+ ReflowComments: true
116
+ SortIncludes: true
117
+ SortUsingDeclarations: true
118
+ SpaceAfterCStyleCast: false
119
+ SpaceAfterLogicalNot: false
120
+ SpaceAfterTemplateKeyword: true
121
+ SpaceBeforeAssignmentOperators: true
122
+ SpaceBeforeCpp11BracedList: false
123
+ SpaceBeforeCtorInitializerColon: true
124
+ SpaceBeforeInheritanceColon: true
125
+ SpaceBeforeParens: ControlStatements
126
+ SpaceBeforeRangeBasedForLoopColon: true
127
+ SpaceInEmptyBlock: false
128
+ SpaceInEmptyParentheses: false
129
+ SpacesBeforeTrailingComments: 1
130
+ SpacesInAngles: false
131
+ SpacesInConditionalStatement: false
132
+ SpacesInContainerLiterals: true
133
+ SpacesInCStyleCastParentheses: false
134
+ SpacesInParentheses: false
135
+ SpacesInSquareBrackets: false
136
+ SpaceBeforeSquareBrackets: false
137
+ Standard: Latest
138
+ StatementMacros:
139
+ - Q_UNUSED
140
+ - QT_REQUIRE_VERSION
141
+ TabWidth: 8
142
+ UseCRLF: false
143
+ UseTab: Never
144
+ WhitespaceSensitiveMacros:
145
+ - STRINGIZE
146
+ - PP_STRINGIZE
147
+ - BOOST_PP_STRINGIZE
148
+ ...
149
+
data/.coveralls.yml CHANGED
@@ -1 +1 @@
1
- service_name: travis-ci
1
+ service_name: github-ci
@@ -0,0 +1,27 @@
1
+ name: build
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ build:
7
+ runs-on: ubuntu-20.04
8
+ strategy:
9
+ matrix:
10
+ ruby: [ '2.6', '2.7', '3.0' ]
11
+ steps:
12
+ - uses: actions/checkout@v2
13
+ - name: Checkout submodule
14
+ shell: bash
15
+ run: |
16
+ auth_header="$(git config --local --get http.https://github.com/.extraheader)"
17
+ git submodule sync --recursive
18
+ git submodule update --init --force --recursive
19
+ - name: Set up Ruby ${{ matrix.ruby }}
20
+ uses: actions/setup-ruby@v1
21
+ with:
22
+ ruby-version: ${{ matrix.ruby }}
23
+ - name: Build and test with Rake
24
+ run: |
25
+ gem install bundler
26
+ bundle install --jobs 4 --retry 3
27
+ bundle exec rake
@@ -0,0 +1,32 @@
1
+ name: coverage
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ pull_request:
7
+ branches: [ main ]
8
+
9
+ jobs:
10
+ coverage:
11
+ runs-on: ubuntu-20.04
12
+ steps:
13
+ - uses: actions/checkout@v2
14
+ - name: Checkout submodule
15
+ shell: bash
16
+ run: |
17
+ auth_header="$(git config --local --get http.https://github.com/.extraheader)"
18
+ git submodule sync --recursive
19
+ git submodule update --init --force --recursive
20
+ - name: Set up Ruby 2.7
21
+ uses: actions/setup-ruby@v1
22
+ with:
23
+ ruby-version: '2.7'
24
+ - name: Build and test with Rake
25
+ run: |
26
+ gem install bundler
27
+ bundle install
28
+ bundle exec rake
29
+ - name: Coveralls GitHub Action
30
+ uses: coverallsapp/github-action@v1.1.2
31
+ with:
32
+ github-token: ${{ secrets.GITHUB_TOKEN }}
data/CHANGELOG.md CHANGED
@@ -1,3 +1,21 @@
1
+ # 0.3.1
2
+ - Fix version specifier of runtime dependencies.
3
+
4
+ # 0.3.0
5
+ - Add type declaration file: sig/numo/pocketfft.rbs
6
+ - Refactor to avoid generating unnecessary arrays.
7
+
8
+ # 0.2.2
9
+ - Fix bug that caused segmentation fault due to garbage collection ([#4](https://github.com/yoshoku/numo-pocketfft/pull/4)).
10
+ - Fix some configuration files.
11
+
12
+ # 0.2.1
13
+ - Fix the link to the document.
14
+ - Several documentation improvements.
15
+
16
+ # 0.2.0
17
+ - Add fftconvolve method that convolves two arrays with FFT.
18
+
1
19
  # 0.1.1
2
20
  - Add input validation for empty array.
3
21
  - Add input validation for non-Numo::NArray object.
data/Gemfile CHANGED
@@ -2,3 +2,11 @@ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in numo-pocketfft.gemspec
4
4
  gemspec
5
+
6
+ gem 'rake', '~> 13.0'
7
+ gem 'rake-compiler', '~> 1.0'
8
+ gem 'rspec', '~> 3.0'
9
+ gem 'simplecov', '~> 0.19'
10
+ gem 'simplecov-lcov', '~> 0.8'
11
+ gem 'rbs', '~> 1.2'
12
+ gem 'steep', '~> 0.44'
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2019 Atsushi Tatsuma
1
+ Copyright (c) 2019-2021 Atsushi Tatsuma
2
2
  All rights reserved.
3
3
 
4
4
  Redistribution and use in source and binary forms, with or without
data/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # Numo::Pocketfft
2
2
 
3
+ [![Build Status](https://github.com/yoshoku/numo-pocketfft/workflows/build/badge.svg)](https://github.com/yoshoku/numo-pocketfft/actions?query=workflow%3Abuild)
4
+ [![Coverage Status](https://coveralls.io/repos/github/yoshoku/numo-pocketfft/badge.svg?branch=main)](https://coveralls.io/github/yoshoku/numo-pocketfft?branch=main)
3
5
  [![Gem Version](https://badge.fury.io/rb/numo-pocketfft.svg)](https://badge.fury.io/rb/numo-pocketfft)
4
- [![Build Status](https://travis-ci.org/yoshoku/numo-pocketfft.svg?branch=master)](https://travis-ci.org/yoshoku/numo-pocketfft)
5
- [![Coverage Status](https://coveralls.io/repos/github/yoshoku/numo-pocketfft/badge.svg?branch=master)](https://coveralls.io/github/yoshoku/numo-pocketfft?branch=master)
6
- [![BSD 3-Clause License](https://img.shields.io/badge/License-BSD%203--Clause-orange.svg)](https://github.com/yoshoku/numo-liblinear/blob/master/LICENSE.txt)
7
- [![Documentation](http://img.shields.io/badge/docs-rdoc.info-blue.svg)](http://www.rubydoc.info/gems/numo-pocketfft/0.1.1)
6
+ [![BSD 3-Clause License](https://img.shields.io/badge/License-BSD%203--Clause-orange.svg)](https://github.com/yoshoku/numo-pocketfft/blob/main/LICENSE.txt)
7
+ [![Documentation](http://img.shields.io/badge/docs-rdoc.info-blue.svg)](https://yoshoku.github.io/numo-pocketfft/doc/)
8
8
 
9
9
  Numo::Pocketfft provides functions for performing descrete Fourier Transform with
10
10
  [Numo::NArray](https://github.com/ruby-numo/numo-narray) by using
@@ -15,7 +15,7 @@ Note: There are other useful Ruby gems perform descrete Fourier Transform with N
15
15
 
16
16
  ## Installation
17
17
 
18
- Numo::Pocketfft bundles pocketfft codes, so there is no need to install the library in advance.
18
+ Numo::Pocketfft bundles pocketfft codes, so there is no need to install another external library in advance.
19
19
  Add this line to your application's Gemfile:
20
20
 
21
21
  ```ruby
@@ -75,4 +75,4 @@ The gem is available as open source under the terms of the [BSD-3-Clause License
75
75
 
76
76
  ## Code of Conduct
77
77
 
78
- Everyone interacting in the Numo::Pocketfft project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/yoshoku/numo-pocketfft/blob/master/CODE_OF_CONDUCT.md).
78
+ Everyone interacting in the Numo::Pocketfft project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/yoshoku/numo-pocketfft/blob/main/CODE_OF_CONDUCT.md).
data/Steepfile ADDED
@@ -0,0 +1,20 @@
1
+ target :lib do
2
+ signature "sig"
3
+ #
4
+ check "lib" # Directory name
5
+ # check "Gemfile" # File name
6
+ # check "app/models/**/*.rb" # Glob
7
+ # # ignore "lib/templates/*.rb"
8
+ #
9
+ # # library "pathname", "set" # Standard libraries
10
+ # library "numo-narray" # Gems
11
+ end
12
+
13
+ # target :spec do
14
+ # signature "sig", "sig-private"
15
+ #
16
+ # check "spec"
17
+ #
18
+ # # library "pathname", "set" # Standard libraries
19
+ # # library "rspec"
20
+ # end
@@ -3,8 +3,7 @@
3
3
  VALUE mNumo;
4
4
  VALUE mPocketfft;
5
5
 
6
- VALUE numo_pocketfft_fft(VALUE x_val, int is_forward)
7
- {
6
+ VALUE numo_pocketfft_fft(VALUE x_val, int is_forward) {
8
7
  narray_t* x_nary;
9
8
  double* x_pt;
10
9
  size_t length;
@@ -40,7 +39,7 @@ VALUE numo_pocketfft_fft(VALUE x_val, int is_forward)
40
39
  z_val = nary_s_new_like(numo_cDComplex, x_val);
41
40
  z_pt = (double*)na_get_pointer_for_write(z_val);
42
41
  GetNArray(z_val, z_nary);
43
- for (i = 0; i < (int)(NA_SIZE(z_nary) * 2); z_pt[i++] = 0.0);
42
+ memset(z_pt, 0, (NA_SIZE(z_nary) * 2) * sizeof(double));
44
43
 
45
44
  fail = 0;
46
45
  fct = is_forward == 1 ? 1.0 : 1.0 / length;
@@ -60,6 +59,8 @@ VALUE numo_pocketfft_fft(VALUE x_val, int is_forward)
60
59
  destroy_cfft_plan(plan);
61
60
  }
62
61
 
62
+ RB_GC_GUARD(x_val);
63
+
63
64
  if (fail) {
64
65
  rb_raise(rb_eNoMemError, "Failed to allocate memory in function of pocketfft.");
65
66
  rb_funcall(z_val, rb_intern("free"), 0);
@@ -72,24 +73,17 @@ VALUE numo_pocketfft_fft(VALUE x_val, int is_forward)
72
73
  /**
73
74
  * @!visibility private
74
75
  */
75
- static VALUE numo_pocketfft_cfft(VALUE self, VALUE x_val)
76
- {
77
- return numo_pocketfft_fft(x_val, 1);
78
- }
76
+ static VALUE numo_pocketfft_cfft(VALUE self, VALUE x_val) { return numo_pocketfft_fft(x_val, 1); }
79
77
 
80
78
  /**
81
79
  * @!visibility private
82
80
  */
83
- static VALUE numo_pocketfft_icfft(VALUE self, VALUE x_val)
84
- {
85
- return numo_pocketfft_fft(x_val, 0);
86
- }
81
+ static VALUE numo_pocketfft_icfft(VALUE self, VALUE x_val) { return numo_pocketfft_fft(x_val, 0); }
87
82
 
88
83
  /**
89
84
  * @!visibility private
90
85
  */
91
- static VALUE numo_pocketfft_rfft(VALUE self, VALUE x_val)
92
- {
86
+ static VALUE numo_pocketfft_rfft(VALUE self, VALUE x_val) {
93
87
  narray_t* x_nary;
94
88
  double* x_pt;
95
89
  int n_dims;
@@ -130,7 +124,7 @@ static VALUE numo_pocketfft_rfft(VALUE self, VALUE x_val)
130
124
  z_val = rb_narray_new(numo_cDComplex, n_dims, z_shape);
131
125
  z_pt = (double*)na_get_pointer_for_write(z_val);
132
126
  GetNArray(z_val, z_nary);
133
- for (i = 0; i < (int)(NA_SIZE(z_nary) * 2); z_pt[i++] = 0.0);
127
+ memset(z_pt, 0, (NA_SIZE(z_nary) * 2) * sizeof(double));
134
128
 
135
129
  fail = 0;
136
130
  z_step = (int)(NA_SHAPE(z_nary)[n_dims - 1]) * 2;
@@ -152,6 +146,8 @@ static VALUE numo_pocketfft_rfft(VALUE self, VALUE x_val)
152
146
  destroy_rfft_plan(plan);
153
147
  }
154
148
 
149
+ RB_GC_GUARD(x_val);
150
+
155
151
  if (fail) {
156
152
  rb_raise(rb_eNoMemError, "Failed to allocate memory in function of pocketfft.");
157
153
  rb_funcall(z_val, rb_intern("free"), 0);
@@ -164,8 +160,7 @@ static VALUE numo_pocketfft_rfft(VALUE self, VALUE x_val)
164
160
  /**
165
161
  * @!visibility private
166
162
  */
167
- static VALUE numo_pocketfft_irfft(VALUE self, VALUE x_val)
168
- {
163
+ static VALUE numo_pocketfft_irfft(VALUE self, VALUE x_val) {
169
164
  narray_t* x_nary;
170
165
  double* x_pt;
171
166
  size_t length;
@@ -206,7 +201,7 @@ static VALUE numo_pocketfft_irfft(VALUE self, VALUE x_val)
206
201
  z_val = rb_narray_new(numo_cDFloat, n_dims, z_shape);
207
202
  z_pt = (double*)na_get_pointer_for_write(z_val);
208
203
  GetNArray(z_val, z_nary);
209
- for (i = 0; i < (int)NA_SIZE(z_nary); z_pt[i++] = 0.0);
204
+ memset(z_pt, 0, NA_SIZE(z_nary) * sizeof(double));
210
205
 
211
206
  fail = 0;
212
207
  fct = 1.0 / length;
@@ -226,6 +221,8 @@ static VALUE numo_pocketfft_irfft(VALUE self, VALUE x_val)
226
221
  destroy_rfft_plan(plan);
227
222
  }
228
223
 
224
+ RB_GC_GUARD(x_val);
225
+
229
226
  if (fail) {
230
227
  rb_raise(rb_eNoMemError, "Failed to allocate memory in function of pocketfft.");
231
228
  rb_funcall(z_val, rb_intern("free"), 0);
@@ -235,8 +232,7 @@ static VALUE numo_pocketfft_irfft(VALUE self, VALUE x_val)
235
232
  return z_val;
236
233
  }
237
234
 
238
- void Init_pocketfftext()
239
- {
235
+ void Init_pocketfftext() {
240
236
  rb_require("numo/narray");
241
237
 
242
238
  mNumo = rb_define_module("Numo");
@@ -5,6 +5,7 @@
5
5
  #include <string.h>
6
6
 
7
7
  #include <ruby.h>
8
+
8
9
  #include <numo/narray.h>
9
10
  #include <numo/template.h>
10
11
 
@@ -10,6 +10,7 @@ module Numo
10
10
 
11
11
  # Compute the 1-dimensional discrete Fourier Transform.
12
12
  # @param a [Numo::DFloat/Numo::DComplex] Real or complex 1-dimensional input array.
13
+ # @raise [ArgumentError] This error is raised if input array is not Numo::NArray, is not one-dimensional array, or is empty.
13
14
  # @return [Numo::DComplex] Transformed data.
14
15
  def fft(a)
15
16
  raise ArgumentError, 'Expect class of input array to be Numo::NArray.' unless a.is_a?(Numo::NArray)
@@ -21,6 +22,7 @@ module Numo
21
22
 
22
23
  # Compute the 1-dimensional inverse discrete Fourier Transform.
23
24
  # @param a [Numo::DComplex] Complex 1-dimensional input array.
25
+ # @raise [ArgumentError] This error is raised if input array is not Numo::NArray, is not one-dimensional array, or is empty.
24
26
  # @return [Numo::DComplex] Inversed transformed data.
25
27
  def ifft(a)
26
28
  raise ArgumentError, 'Expect class of input array to be Numo::NArray.' unless a.is_a?(Numo::NArray)
@@ -32,6 +34,7 @@ module Numo
32
34
 
33
35
  # Compute the 2-dimensional discrete Fourier Transform.
34
36
  # @param a [Numo::DFloat/Numo::DComplex] Real or complex 2-dimensional input array.
37
+ # @raise [ArgumentError] This error is raised if input array is not Numo::NArray, is not two-dimensional array, or is empty.
35
38
  # @return [Numo::DComplex] Transformed data.
36
39
  def fft2(a)
37
40
  raise ArgumentError, 'Expect class of input array to be Numo::NArray.' unless a.is_a?(Numo::NArray)
@@ -43,6 +46,7 @@ module Numo
43
46
 
44
47
  # Compute the 2-dimensional inverse discrete Fourier Transform.
45
48
  # @param a [Numo::DComplex] Complex 2-dimensional input array.
49
+ # @raise [ArgumentError] This error is raised if input array is not Numo::NArray, is not two-dimensional array, or is empty.
46
50
  # @return [Numo::DComplex] Inversed transformed data.
47
51
  def ifft2(a)
48
52
  raise ArgumentError, 'Expect class of input array to be Numo::NArray.' unless a.is_a?(Numo::NArray)
@@ -54,30 +58,39 @@ module Numo
54
58
 
55
59
  # Compute the N-dimensional discrete Fourier Transform.
56
60
  # @param a [Numo::DFloat/Numo::DComplex] Real or complex input array with any-dimension.
61
+ # @raise [ArgumentError] This error is raised if input array is not Numo::NArray or is empty.
57
62
  # @return [Numo::DComplex] Transformed data.
58
63
  def fftn(a)
59
64
  raise ArgumentError, 'Expect class of input array to be Numo::NArray.' unless a.is_a?(Numo::NArray)
60
65
  raise ArgumentError, 'Expect input array to be non-empty.' if a.empty?
61
66
 
62
- b = a.dup
63
- (0...b.ndim).to_a.reverse.each { |ax_id| b = raw_fft(b, ax_id, inverse: false, real: false) }
67
+ return raw_fft(a, 0, inverse: false, real: false) if a.ndim == 1
68
+
69
+ last_axis_id = a.ndim - 1
70
+ b = raw_fft(a, last_axis_id, inverse: false, real: false)
71
+ (last_axis_id - 1).downto(0) { |ax_id| b = raw_fft(b, ax_id, inverse: false, real: false) }
64
72
  b
65
73
  end
66
74
 
67
75
  # Compute the N-dimensional inverse discrete Fourier Transform.
68
76
  # @param a [Numo::DComplex] Complex input array with any-dimension.
77
+ # @raise [ArgumentError] This error is raised if input array is not Numo::NArray or is empty.
69
78
  # @return [Numo::DComplex] Inversed transformed data.
70
79
  def ifftn(a)
71
80
  raise ArgumentError, 'Expect class of input array to be Numo::NArray.' unless a.is_a?(Numo::NArray)
72
81
  raise ArgumentError, 'Expect input array to be non-empty.' if a.empty?
73
82
 
74
- b = a.dup
75
- (0...b.ndim).to_a.each { |ax_id| b = raw_fft(b, ax_id, inverse: true, real: false) }
83
+ return raw_fft(a, 0, inverse: true, real: false) if a.ndim == 1
84
+
85
+ last_axis_id = a.ndim - 1
86
+ b = raw_fft(a, 0, inverse: true, real: false)
87
+ 1.upto(last_axis_id) { |ax_id| b = raw_fft(b, ax_id, inverse: true, real: false) }
76
88
  b
77
89
  end
78
90
 
79
91
  # Compute the 1-dimensional discrete Fourier Transform for real input.
80
92
  # @param a [Numo::DFloat] Real 1-dimensional input array.
93
+ # @raise [ArgumentError] This error is raised if input array is not Numo::NArray, is not one-dimensional array, or is empty.
81
94
  # @return [Numo::DComplex] Transformed data.
82
95
  def rfft(a)
83
96
  raise ArgumentError, 'Expect class of input array to be Numo::NArray.' unless a.is_a?(Numo::NArray)
@@ -89,6 +102,7 @@ module Numo
89
102
 
90
103
  # Compute the inverse of the 1-dimensional discrete Fourier Transform of real input.
91
104
  # @param a [Numo::DComplex] Complex 1-dimensional input array.
105
+ # @raise [ArgumentError] This error is raised if input array is not Numo::NArray, is not one-dimensional array, or is empty.
92
106
  # @return [Numo::DFloat] Inverse transformed data.
93
107
  def irfft(a)
94
108
  raise ArgumentError, 'Expect class of input array to be Numo::NArray.' unless a.is_a?(Numo::NArray)
@@ -100,6 +114,7 @@ module Numo
100
114
 
101
115
  # Compute the 2-dimensional discrete Fourier Transform for real input.
102
116
  # @param a [Numo::DFloat] Real 2-dimensional input array.
117
+ # @raise [ArgumentError] This error is raised if input array is not Numo::NArray, is not two-dimensional array, or is empty.
103
118
  # @return [Numo::DComplex] Transformed data.
104
119
  def rfft2(a)
105
120
  raise ArgumentError, 'Expect class of input array to be Numo::NArray.' unless a.is_a?(Numo::NArray)
@@ -111,6 +126,7 @@ module Numo
111
126
 
112
127
  # Compute the inverse of the 2-dimensional discrete Fourier Transform of real input.
113
128
  # @param a [Numo::DComplex] Complex 2-dimensional input array.
129
+ # @raise [ArgumentError] This error is raised if input array is not Numo::NArray, is not two-dimensional array, or is empty.
114
130
  # @return [Numo::DFloat] Inverse transformed data.
115
131
  def irfft2(a)
116
132
  raise ArgumentError, 'Expect class of input array to be Numo::NArray.' unless a.is_a?(Numo::NArray)
@@ -122,30 +138,77 @@ module Numo
122
138
 
123
139
  # Compute the N-dimensional discrete Fourier Transform for real input.
124
140
  # @param a [Numo::DFloat] Real input array with any-dimension.
141
+ # @raise [ArgumentError] This error is raised if input array is not Numo::NArray or is empty.
125
142
  # @return [Numo::DComplex] Transformed data.
126
143
  def rfftn(a)
127
144
  raise ArgumentError, 'Expect class of input array to be Numo::NArray.' unless a.is_a?(Numo::NArray)
128
145
  raise ArgumentError, 'Expect input array to be non-empty.' if a.empty?
129
146
 
147
+ return raw_fft(a, 0, inverse: false, real: true) if a.ndim == 1
148
+
130
149
  last_axis_id = a.ndim - 1
131
150
  b = raw_fft(a, last_axis_id, inverse: false, real: true)
132
- (0...last_axis_id).to_a.reverse.each { |ax_id| b = raw_fft(b, ax_id, inverse: false, real: false) }
151
+ (last_axis_id - 1).downto(0) { |ax_id| b = raw_fft(b, ax_id, inverse: false, real: false) }
133
152
  b
134
153
  end
135
154
 
136
155
  # Compute the inverse of the N-dimensional discrete Fourier Transform of real input.
137
156
  # @param a [Numo::DComplex] Complex input array with any-dimension.
157
+ # @raise [ArgumentError] This error is raised if input array is not Numo::NArray or is empty.
138
158
  # @return [Numo::DFloat] Inverse transformed data.
139
159
  def irfftn(a)
140
160
  raise ArgumentError, 'Expect class of input array to be Numo::NArray.' unless a.is_a?(Numo::NArray)
141
161
  raise ArgumentError, 'Expect input array to be non-empty.' if a.empty?
142
162
 
163
+ return raw_fft(a, 0, inverse: true, real: true) if a.ndim == 1
164
+
143
165
  last_axis_id = a.ndim - 1
144
- b = a.dup
145
- (0...last_axis_id).to_a.each { |ax_id| b = raw_fft(b, ax_id, inverse: true, real: false) }
166
+ b = raw_fft(a, 0, inverse: true, real: false)
167
+ 1.upto(last_axis_id - 1) { |ax_id| b = raw_fft(b, ax_id, inverse: true, real: false) }
146
168
  raw_fft(b, last_axis_id, inverse: true, real: true)
147
169
  end
148
170
 
171
+ # Convolve two N-dimensinal arrays using dscrete Fourier Transform.
172
+ # @example
173
+ # require 'numo/pocketfftw'
174
+ #
175
+ # a = Numo::DFloat[1, 2, 3]
176
+ # b = Numo::DFloat[4, 5]
177
+ # p Numo::Pocketfft.fftconvolve(a, b)
178
+ # # Numo::DFloat#shape=[4]
179
+ # # [4, 13, 22, 15]
180
+ #
181
+ # a = Numo::DFloat[[1, 2], [3, 4]]
182
+ # b = Numo::DFloat[[5, 6], [7, 8]]
183
+ # p Numo::Pocketfft.fftconvolve(a, b)
184
+ # # Numo::DFloat#shape=[3,3]
185
+ # # [[5, 16, 12],
186
+ # # [22, 60, 40],
187
+ # # [21, 52, 32]]
188
+ # @param a [Numo::DFloat/Numo::DComplex] Fisrt input array with any-dimension.
189
+ # @param b [Numo::DFloat/Numo::DComplex] Second input array with the same number of dimensions as first input array.
190
+ # @raise [ArgumentError] This error is raised if input arrays are not Numo::NArray, are not the same dimensionality, or are empty.
191
+ # @return [Numo::DFloat/Numo::DComplex] The discrete linear convolution of 'a' with 'b'.
192
+ def fftconvolve(a, b)
193
+ raise ArgumentError, 'Expect class of input array to be Numo::NArray.' unless a.is_a?(Numo::NArray) && b.is_a?(Numo::NArray)
194
+ raise ArgumentError, 'Expect input array to be non-empty.' if a.empty? || b.empty?
195
+ raise ArgumentError, 'Input arrays should have the same dimensionarity' if a.ndim != b.ndim
196
+
197
+ ashp = a.shape
198
+ bshp = b.shape
199
+
200
+ return a * b if (ashp + bshp).all? { |el| el == 1 }
201
+
202
+ retshp = Array.new(a.ndim) { |n| ashp[n] + bshp[n] - 1 }
203
+ a_zp = Numo::DComplex.zeros(*retshp).tap { |arr| arr[*ashp.map { |n| 0...n }] = a }
204
+ b_zp = Numo::DComplex.zeros(*retshp).tap { |arr| arr[*bshp.map { |n| 0...n }] = b }
205
+ ret = ifftn(fftn(a_zp) * fftn(b_zp))
206
+
207
+ return ret if a.is_a?(Numo::DComplex) || a.is_a?(Numo::SComplex) || b.is_a?(Numo::DComplex) || b.is_a?(Numo::SComplex)
208
+
209
+ ret.real
210
+ end
211
+
149
212
  # @!visibility private
150
213
  def raw_fft(a, axis_id, inverse:, real:)
151
214
  if axis_id == a.ndim - 1
@@ -156,8 +219,7 @@ module Numo
156
219
  b_shape = a.shape
157
220
  b_shape[-1] = n
158
221
  b = Numo::DComplex.zeros(*b_shape)
159
- b_range = [true] * b.ndim
160
- b_range[-1] = 0...a.shape[-1]
222
+ b_range = Array.new(b.ndim) { |idx| idx < b.ndim - 1 ? true : 0...a.shape[-1] }
161
223
  b[*b_range] = a
162
224
  # inverse of dft for real data
163
225
  ext_irfft(b)
@@ -5,6 +5,6 @@ module Numo
5
5
  # Numo::Pocketfft is the module that has functions for Fourier transform.
6
6
  module Pocketfft
7
7
  # The version of Numo::Pocketfft you are using.
8
- VERSION = '0.1.1'
8
+ VERSION = '0.3.1'
9
9
  end
10
10
  end
@@ -37,11 +37,13 @@ Gem::Specification.new do |spec|
37
37
  spec.require_paths = ['lib']
38
38
  spec.extensions = ['ext/numo/pocketfft/extconf.rb']
39
39
 
40
- spec.add_runtime_dependency 'numo-narray', '~> 0.9.1'
40
+ spec.metadata = {
41
+ 'homepage_uri' => 'https://github.com/yoshoku/numo-pocketfft',
42
+ 'changelog_uri' => 'https://github.com/yoshoku/numo-pocketfft/blob/main/CHANGELOG.md',
43
+ 'source_code_uri' => 'https://github.com/yoshoku/numo-pocketfft',
44
+ 'documentation_uri' => 'https://yoshoku.github.io/numo-pocketfft/doc/',
45
+ 'bug_tracker_uri' => 'https://github.com/yoshoku/numo-pocketfft/issues'
46
+ }
41
47
 
42
- spec.add_development_dependency 'bundler', '~> 2.0'
43
- spec.add_development_dependency 'coveralls', '~> 0.8'
44
- spec.add_development_dependency 'rake', '~> 10.0'
45
- spec.add_development_dependency 'rake-compiler', '~> 1.0'
46
- spec.add_development_dependency 'rspec', '~> 3.0'
48
+ spec.add_runtime_dependency 'numo-narray', '>= 0.9.1'
47
49
  end
@@ -0,0 +1,28 @@
1
+ module Numo
2
+ module Pocketfft
3
+ VERSION: String
4
+
5
+ def self?.fft: (Numo::DFloat | Numo::DComplex a) -> Numo::DComplex
6
+ def self?.fft2: (Numo::DFloat | Numo::DComplex a) -> Numo::DComplex
7
+ def self?.fftn: (Numo::DFloat | Numo::DComplex a) -> Numo::DComplex
8
+ def self?.ifft: (Numo::DComplex a) -> Numo::DComplex
9
+ def self?.ifft2: (Numo::DComplex a) -> Numo::DComplex
10
+ def self?.ifftn: (Numo::DComplex a) -> Numo::DComplex
11
+ def self?.rfft: (Numo::DFloat a) -> Numo::DComplex
12
+ def self?.rfft2: (Numo::DFloat a) -> Numo::DComplex
13
+ def self?.rfftn: (Numo::DFloat a) -> Numo::DComplex
14
+ def self?.irfft: (Numo::DComplex a) -> Numo::DFloat
15
+ def self?.irfft2: (Numo::DComplex a) -> Numo::DFloat
16
+ def self?.irfftn: (Numo::DComplex a) -> Numo::DFloat
17
+ def self?.fftconvolve: (Numo::DFloat | Numo::DComplex a, Numo::DFloat | Numo::DComplex b) -> Numo::DComplex
18
+ | (Numo::DFloat a, Numo::DFloat b) -> Numo::DFloat
19
+
20
+ private
21
+
22
+ def self?.ext_cfft: (untyped a) -> untyped
23
+ def self?.ext_icfft: (untyped a) -> untyped
24
+ def self?.ext_rfft: (untyped a) -> untyped
25
+ def self?.ext_irfft: (untyped a) -> untyped
26
+ def self?.raw_fft: (untyped a, Integer axis_id, inverse: bool inverse, real: bool real) -> untyped
27
+ end
28
+ end
data/sig/patch.rbs ADDED
@@ -0,0 +1,22 @@
1
+ module Numo
2
+ class NArray
3
+ def empty?: () -> bool
4
+ def ndim: () -> Integer
5
+ def shape: () -> Array[Integer]
6
+ def swapaxes: (Integer, Integer) -> untyped
7
+ end
8
+
9
+ class DFloat < NArray
10
+ def *: (untyped) -> untyped
11
+ def []: (*untyped) -> untyped
12
+ def []=: (*untyped) -> untyped
13
+ end
14
+
15
+ class DComplex < NArray
16
+ def self.zeros: (*untyped) -> Numo::DComplex
17
+ def *: (untyped) -> untyped
18
+ def []: (*untyped) -> untyped
19
+ def []=: (*untyped) -> untyped
20
+ def real: () -> Numo::DFloat
21
+ end
22
+ end
metadata CHANGED
@@ -1,99 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: numo-pocketfft
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - yoshoku
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-11 00:00:00.000000000 Z
11
+ date: 2021-06-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: numo-narray
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: 0.9.1
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.9.1
27
- - !ruby/object:Gem::Dependency
28
- name: bundler
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '2.0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '2.0'
41
- - !ruby/object:Gem::Dependency
42
- name: coveralls
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '0.8'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '0.8'
55
- - !ruby/object:Gem::Dependency
56
- name: rake
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '10.0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '10.0'
69
- - !ruby/object:Gem::Dependency
70
- name: rake-compiler
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: '1.0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '1.0'
83
- - !ruby/object:Gem::Dependency
84
- name: rspec
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: '3.0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: '3.0'
97
27
  description: 'Numo::Pocketfft provides functions for descrete Fourier Transform based
98
28
  on pocketfft.
99
29
 
@@ -105,19 +35,20 @@ extensions:
105
35
  - ext/numo/pocketfft/extconf.rb
106
36
  extra_rdoc_files: []
107
37
  files:
38
+ - ".clang-format"
108
39
  - ".coveralls.yml"
40
+ - ".github/workflows/build.yml"
41
+ - ".github/workflows/coverage.yml"
109
42
  - ".gitignore"
110
43
  - ".gitmodules"
111
44
  - ".rspec"
112
- - ".travis.yml"
113
45
  - CHANGELOG.md
114
46
  - CODE_OF_CONDUCT.md
115
47
  - Gemfile
116
48
  - LICENSE.txt
117
49
  - README.md
118
50
  - Rakefile
119
- - bin/console
120
- - bin/setup
51
+ - Steepfile
121
52
  - ext/numo/pocketfft/extconf.rb
122
53
  - ext/numo/pocketfft/pocketfft/.gitlab-ci.yml
123
54
  - ext/numo/pocketfft/pocketfft/LICENSE.md
@@ -131,10 +62,17 @@ files:
131
62
  - lib/numo/pocketfft.rb
132
63
  - lib/numo/pocketfft/version.rb
133
64
  - numo-pocketfft.gemspec
65
+ - sig/numo/pocketfft.rbs
66
+ - sig/patch.rbs
134
67
  homepage: https://github.com/yoshoku/numo-pocketfft
135
68
  licenses:
136
69
  - BSD-3-Clause
137
- metadata: {}
70
+ metadata:
71
+ homepage_uri: https://github.com/yoshoku/numo-pocketfft
72
+ changelog_uri: https://github.com/yoshoku/numo-pocketfft/blob/main/CHANGELOG.md
73
+ source_code_uri: https://github.com/yoshoku/numo-pocketfft
74
+ documentation_uri: https://yoshoku.github.io/numo-pocketfft/doc/
75
+ bug_tracker_uri: https://github.com/yoshoku/numo-pocketfft/issues
138
76
  post_install_message:
139
77
  rdoc_options: []
140
78
  require_paths:
@@ -150,8 +88,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
150
88
  - !ruby/object:Gem::Version
151
89
  version: '0'
152
90
  requirements: []
153
- rubyforge_project:
154
- rubygems_version: 2.6.14.4
91
+ rubygems_version: 3.2.21
155
92
  signing_key:
156
93
  specification_version: 4
157
94
  summary: Numo::Pocketfft provides functions for descrete Fourier Transform based on
data/.travis.yml DELETED
@@ -1,13 +0,0 @@
1
- ---
2
- sudo: true
3
- os: linux
4
- dist: bionic
5
- language: ruby
6
- cache: bundler
7
- rvm:
8
- - '2.4'
9
- - '2.5'
10
- - '2.6'
11
- before_install:
12
- - sudo apt-get install -y gcc
13
- - gem install bundler -v 2.0.2