nmatrix-gemv 0.0.3
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/.gitignore +29 -0
- data/.rspec +2 -0
- data/.travis.yml +14 -0
- data/Gemfile +7 -0
- data/README.md +29 -0
- data/Rakefile +225 -0
- data/ext/nmatrix_gemv/binary_format.txt +53 -0
- data/ext/nmatrix_gemv/data/complex.h +399 -0
- data/ext/nmatrix_gemv/data/data.cpp +298 -0
- data/ext/nmatrix_gemv/data/data.h +771 -0
- data/ext/nmatrix_gemv/data/meta.h +70 -0
- data/ext/nmatrix_gemv/data/rational.h +436 -0
- data/ext/nmatrix_gemv/data/ruby_object.h +471 -0
- data/ext/nmatrix_gemv/extconf.rb +254 -0
- data/ext/nmatrix_gemv/math.cpp +1639 -0
- data/ext/nmatrix_gemv/math/asum.h +143 -0
- data/ext/nmatrix_gemv/math/geev.h +82 -0
- data/ext/nmatrix_gemv/math/gemm.h +271 -0
- data/ext/nmatrix_gemv/math/gemv.h +212 -0
- data/ext/nmatrix_gemv/math/ger.h +96 -0
- data/ext/nmatrix_gemv/math/gesdd.h +80 -0
- data/ext/nmatrix_gemv/math/gesvd.h +78 -0
- data/ext/nmatrix_gemv/math/getf2.h +86 -0
- data/ext/nmatrix_gemv/math/getrf.h +240 -0
- data/ext/nmatrix_gemv/math/getri.h +108 -0
- data/ext/nmatrix_gemv/math/getrs.h +129 -0
- data/ext/nmatrix_gemv/math/idamax.h +86 -0
- data/ext/nmatrix_gemv/math/inc.h +47 -0
- data/ext/nmatrix_gemv/math/laswp.h +165 -0
- data/ext/nmatrix_gemv/math/long_dtype.h +52 -0
- data/ext/nmatrix_gemv/math/math.h +1069 -0
- data/ext/nmatrix_gemv/math/nrm2.h +181 -0
- data/ext/nmatrix_gemv/math/potrs.h +129 -0
- data/ext/nmatrix_gemv/math/rot.h +141 -0
- data/ext/nmatrix_gemv/math/rotg.h +115 -0
- data/ext/nmatrix_gemv/math/scal.h +73 -0
- data/ext/nmatrix_gemv/math/swap.h +73 -0
- data/ext/nmatrix_gemv/math/trsm.h +387 -0
- data/ext/nmatrix_gemv/nm_memory.h +60 -0
- data/ext/nmatrix_gemv/nmatrix_gemv.cpp +90 -0
- data/ext/nmatrix_gemv/nmatrix_gemv.h +374 -0
- data/ext/nmatrix_gemv/ruby_constants.cpp +153 -0
- data/ext/nmatrix_gemv/ruby_constants.h +107 -0
- data/ext/nmatrix_gemv/ruby_nmatrix.c +84 -0
- data/ext/nmatrix_gemv/ttable_helper.rb +122 -0
- data/ext/nmatrix_gemv/types.h +54 -0
- data/ext/nmatrix_gemv/util/util.h +78 -0
- data/lib/nmatrix-gemv.rb +43 -0
- data/lib/nmatrix_gemv/blas.rb +85 -0
- data/lib/nmatrix_gemv/nmatrix_gemv.rb +35 -0
- data/lib/nmatrix_gemv/rspec.rb +75 -0
- data/nmatrix-gemv.gemspec +31 -0
- data/spec/blas_spec.rb +154 -0
- data/spec/spec_helper.rb +128 -0
- metadata +186 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1ae23439e8353af4cb448484f3fbfda6b48b2298
|
4
|
+
data.tar.gz: 62438a8e9422b60195513cda83899d38996bba36
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: bd9f765529f35717cccdae8ecf222c0a04cddf60ff502ef2b4713ee470bb20f7e267a568d40802604c4796db4c2b68ada80b4156e1e7a82dd222fb32a387572f
|
7
|
+
data.tar.gz: 370c1440f3bae1bb28b85823e509204f35cb24db7a5eedcfd7538d4cf4a6eda8eb6238e38364ce16c43eac4b2bfacf58328e6241c35b82622502bc5a4ada997f
|
data/.gitignore
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
.idea
|
2
|
+
Gemfile.lock
|
3
|
+
ext/nmatrix/dense/daxpy.c
|
4
|
+
ext/nmatrix/dense/dgeco.c
|
5
|
+
ext/nmatrix/dense/dgefa.c
|
6
|
+
ext/nmatrix/dense/dgemm.c
|
7
|
+
ext/nmatrix/dense/dgemv.c
|
8
|
+
ext/nmatrix/dense/dscal.c
|
9
|
+
ext/nmatrix/dense/idamax.c
|
10
|
+
ext/nmatrix/dense/467.c
|
11
|
+
ext/nmatrix/dense/*.f
|
12
|
+
ext/nmatrix/dense/transpose.txt
|
13
|
+
ext/nmatrix/yale/aicm.tex
|
14
|
+
tmp/
|
15
|
+
test.c
|
16
|
+
spec/*.mtx
|
17
|
+
*.o
|
18
|
+
*.so
|
19
|
+
*.bundle
|
20
|
+
*.bundle.dSYM
|
21
|
+
*.log
|
22
|
+
/tags
|
23
|
+
*.gem
|
24
|
+
html/
|
25
|
+
doc/
|
26
|
+
docs/
|
27
|
+
pkg/
|
28
|
+
.autotest
|
29
|
+
tags
|
data/.rspec
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
language: ruby
|
2
|
+
cache: bundler
|
3
|
+
env:
|
4
|
+
- CPLUS_INCLUDE_PATH=/usr/include/atlas C_INCLUDE_PATH=/usr/include/atlas
|
5
|
+
rvm:
|
6
|
+
- "1.9.2"
|
7
|
+
- "1.9.3"
|
8
|
+
- "2.0.0"
|
9
|
+
- "2.1.0"
|
10
|
+
before_install:
|
11
|
+
- sudo apt-get update -qq
|
12
|
+
- sudo apt-get install -qq libatlas-base-dev
|
13
|
+
script: bundle exec rake compile && bundle exec rake spec
|
14
|
+
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# nmatrix-gemv #
|
2
|
+
|
3
|
+
## How to install ##
|
4
|
+
`bundle install`
|
5
|
+
|
6
|
+
`bundle exec rake compile`
|
7
|
+
|
8
|
+
`gem build nmatrix-gemv.gemspec`
|
9
|
+
|
10
|
+
`gem install ./nmatrix-gemv-0.0.2.gem`
|
11
|
+
|
12
|
+
## How to use ##
|
13
|
+
```
|
14
|
+
irb
|
15
|
+
>require 'nmatrix-gemv'
|
16
|
+
=> true
|
17
|
+
```
|
18
|
+
### In file: ###
|
19
|
+
Suppose you have [NMatrix](https://github.com/SciRuby/nmatrix) installed.
|
20
|
+
|
21
|
+
```{.ruby}
|
22
|
+
require 'nmatrix'
|
23
|
+
require 'nmatrix-gemv'
|
24
|
+
|
25
|
+
a = NMatrix.new([2,3], [1.0, 2.0, 3.0, 4.0, 5.0, 6.0], dtype: :float64)
|
26
|
+
x = NMatrix.new([1,4], [2.0, 3.0, 4.0, 5.0], dtype: :float64)
|
27
|
+
|
28
|
+
NMatrix::BLAS.gemv(a, x)
|
29
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,225 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'rubygems/package_task'
|
5
|
+
require 'bundler'
|
6
|
+
begin
|
7
|
+
Bundler.setup(:default, :development)
|
8
|
+
rescue Bundler::BundlerError => e
|
9
|
+
$stderr.puts e.message
|
10
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
11
|
+
exit e.status_code
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'rake'
|
15
|
+
require "rake/extensiontask"
|
16
|
+
Rake::ExtensionTask.new do |ext|
|
17
|
+
ext.name = 'nmatrix_gemv'
|
18
|
+
ext.ext_dir = 'ext/nmatrix_gemv'
|
19
|
+
ext.lib_dir = 'lib/'
|
20
|
+
ext.source_pattern = "**/*.{c,cpp, h}"
|
21
|
+
end
|
22
|
+
|
23
|
+
gemspec = eval(IO.read("nmatrix-gemv.gemspec"))
|
24
|
+
=begin
|
25
|
+
Gem::PackageTask.new(gemspec).define
|
26
|
+
|
27
|
+
desc "install the gem locally"
|
28
|
+
task :install => [:package] do
|
29
|
+
sh %{gem install pkg/nmatrix-#{NMatrix::VERSION}.gem}
|
30
|
+
end
|
31
|
+
=end
|
32
|
+
|
33
|
+
require 'rspec/core/rake_task'
|
34
|
+
require 'rspec/core'
|
35
|
+
require 'rspec/core/rake_task'
|
36
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
37
|
+
spec.pattern = FileList['spec/**/*_spec.rb'].uniq
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
BASEDIR = Pathname( __FILE__ ).dirname.relative_path_from( Pathname.pwd )
|
42
|
+
SPECDIR = BASEDIR + 'spec'
|
43
|
+
|
44
|
+
VALGRIND_OPTIONS = [
|
45
|
+
"--tool=memcheck",
|
46
|
+
#"--leak-check=yes",
|
47
|
+
"--num-callers=15",
|
48
|
+
#"--error-limit=no",
|
49
|
+
"--partial-loads-ok=yes",
|
50
|
+
"--undef-value-errors=no" #,
|
51
|
+
#"--dsymutil=yes"
|
52
|
+
]
|
53
|
+
|
54
|
+
CALLGRIND_OPTIONS = [
|
55
|
+
"--tool=callgrind",
|
56
|
+
"--dump-instr=yes",
|
57
|
+
"--simulate-cache=yes",
|
58
|
+
"--collect-jumps=yes"
|
59
|
+
]
|
60
|
+
|
61
|
+
VALGRIND_MEMORYFILL_OPTIONS = [
|
62
|
+
"--freelist-vol=100000000",
|
63
|
+
"--malloc-fill=6D",
|
64
|
+
"--free-fill=66 ",
|
65
|
+
]
|
66
|
+
|
67
|
+
GDB_OPTIONS = []
|
68
|
+
|
69
|
+
|
70
|
+
RSpec::Core::RakeTask.new(:spec)
|
71
|
+
|
72
|
+
task :console do |task|
|
73
|
+
cmd = [ 'irb', "-r './lib/nmatrix_gemv.rb'" ]
|
74
|
+
run *cmd
|
75
|
+
end
|
76
|
+
|
77
|
+
=begin
|
78
|
+
task :pry do |task|
|
79
|
+
cmd = [ 'pry', "-r './lib/nmatrix.rb'" ]
|
80
|
+
run *cmd
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
namespace :pry do
|
85
|
+
task :valgrind => [ :compile ] do |task|
|
86
|
+
cmd = [ 'valgrind' ] + VALGRIND_OPTIONS
|
87
|
+
cmd += ['ruby', '-Ilib:ext', "-r './lib/nmatrix.rb'", "-r 'pry'", "-e 'binding.pry'"]
|
88
|
+
run *cmd
|
89
|
+
end
|
90
|
+
end
|
91
|
+
=end
|
92
|
+
|
93
|
+
namespace :console do
|
94
|
+
CONSOLE_CMD = ['irb', "-r './lib/nmatrix_gemv.rb'"]
|
95
|
+
desc "Run console under GDB."
|
96
|
+
task :gdb => [ :compile ] do |task|
|
97
|
+
cmd = [ 'gdb' ] + GDB_OPTIONS
|
98
|
+
cmd += [ '--args' ]
|
99
|
+
cmd += CONSOLE_CMD
|
100
|
+
run( *cmd )
|
101
|
+
end
|
102
|
+
|
103
|
+
desc "Run console under Valgrind."
|
104
|
+
task :valgrind => [ :compile ] do |task|
|
105
|
+
cmd = [ 'valgrind' ] + VALGRIND_OPTIONS
|
106
|
+
cmd += CONSOLE_CMD
|
107
|
+
run( *cmd )
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
task :default => :spec
|
112
|
+
|
113
|
+
def run *cmd
|
114
|
+
sh(cmd.join(" "))
|
115
|
+
end
|
116
|
+
|
117
|
+
namespace :spec do
|
118
|
+
# partial-loads-ok and undef-value-errors necessary to ignore
|
119
|
+
# spurious (and eminently ignorable) warnings from the ruby
|
120
|
+
# interpreter
|
121
|
+
|
122
|
+
RSPEC_CMD = [ 'ruby', '-S', 'rspec', '-Ilib:ext', SPECDIR.to_s ]
|
123
|
+
|
124
|
+
#desc "Run the spec for generator.rb"
|
125
|
+
#task :generator do |task|
|
126
|
+
# run 'rspec spec/generator_spec.rb'
|
127
|
+
#end
|
128
|
+
|
129
|
+
desc "Run specs under GDB."
|
130
|
+
task :gdb => [ :compile ] do |task|
|
131
|
+
cmd = [ 'gdb' ] + GDB_OPTIONS
|
132
|
+
cmd += [ '--args' ]
|
133
|
+
cmd += RSPEC_CMD
|
134
|
+
run( *cmd )
|
135
|
+
end
|
136
|
+
|
137
|
+
desc "Run specs under cgdb."
|
138
|
+
task :cgdb => [ :compile ] do |task|
|
139
|
+
cmd = [ 'cgdb' ] + GDB_OPTIONS
|
140
|
+
cmd += [ '--args' ]
|
141
|
+
cmd += RSPEC_CMD
|
142
|
+
run( *cmd )
|
143
|
+
end
|
144
|
+
|
145
|
+
desc "Run specs under Valgrind."
|
146
|
+
task :valgrind => [ :compile ] do |task|
|
147
|
+
cmd = [ 'valgrind' ] + VALGRIND_OPTIONS
|
148
|
+
cmd += RSPEC_CMD
|
149
|
+
run( *cmd )
|
150
|
+
end
|
151
|
+
|
152
|
+
desc "Run specs under Callgrind."
|
153
|
+
task :callgrind => [ :compile ] do |task|
|
154
|
+
cmd = [ 'valgrind' ] + CALLGRIND_OPTIONS
|
155
|
+
cmd += RSPEC_CMD
|
156
|
+
run( *cmd )
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
|
161
|
+
=begin
|
162
|
+
LEAKCHECK_CMD = [ 'ruby', '-Ilib:ext', "#{SPECDIR}/leakcheck.rb" ]
|
163
|
+
|
164
|
+
|
165
|
+
desc "Run leakcheck script."
|
166
|
+
task :leakcheck => [ :compile ] do |task|
|
167
|
+
cmd = [ 'valgrind' ] + VALGRIND_OPTIONS
|
168
|
+
cmd += LEAKCHECK_CMD
|
169
|
+
run( *cmd )
|
170
|
+
end
|
171
|
+
=end
|
172
|
+
|
173
|
+
namespace :clean do
|
174
|
+
task :so do |task|
|
175
|
+
tmp_path = "tmp/#{RUBY_PLATFORM}/nmatrix-gemv/#{RUBY_VERSION}"
|
176
|
+
chdir tmp_path do
|
177
|
+
if RUBY_PLATFORM =~ /mswin/
|
178
|
+
`nmake soclean`
|
179
|
+
else
|
180
|
+
mkcmd = ENV['MAKE'] || %w[gmake make].find { |c| system("#{c} -v >> /dev/null 2>&1") }
|
181
|
+
`#{mkcmd} soclean`
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
=begin
|
188
|
+
desc "Check the manifest for correctness"
|
189
|
+
task :check_manifest do |task|
|
190
|
+
manifest_files = File.read("Manifest.txt").split
|
191
|
+
|
192
|
+
git_files = `git ls-files |grep -v 'spec/'`.split
|
193
|
+
ignore_files = %w{.gitignore .rspec ext/nmatrix/binary_format.txt ext/nmatrix/ttable_helper.rb scripts/mac-brew-gcc.sh}
|
194
|
+
|
195
|
+
possible_files = git_files - ignore_files
|
196
|
+
|
197
|
+
missing_files = possible_files - manifest_files
|
198
|
+
extra_files = manifest_files - possible_files
|
199
|
+
|
200
|
+
unless missing_files.empty?
|
201
|
+
STDERR.puts "The following files are in the git repo but not the Manifest:"
|
202
|
+
missing_files.each { |f| STDERR.puts " -- #{f}"}
|
203
|
+
end
|
204
|
+
|
205
|
+
unless extra_files.empty?
|
206
|
+
STDERR.puts "The following files are in the Manifest but may not be necessary:"
|
207
|
+
extra_files.each { |f| STDERR.puts " -- #{f}"}
|
208
|
+
end
|
209
|
+
|
210
|
+
if extra_files.empty? && missing_files.empty?
|
211
|
+
STDERR.puts "Manifest looks good!"
|
212
|
+
end
|
213
|
+
|
214
|
+
end
|
215
|
+
=end
|
216
|
+
|
217
|
+
=begin
|
218
|
+
require "rdoc/task"
|
219
|
+
RDoc::Task.new do |rdoc|
|
220
|
+
rdoc.main = "README.rdoc"
|
221
|
+
rdoc.rdoc_files.include(%w{README.rdoc History.txt LICENSE.txt CONTRIBUTING.md ext/nmatrix/binary_format.txt lib/nmatrix/**/*.rb ext/nmatrix/**/*.cpp ext/nmatrix/**/*.c ext/nmatrix/**/*.h})
|
222
|
+
end
|
223
|
+
=end
|
224
|
+
|
225
|
+
# vim: syntax=ruby
|
@@ -0,0 +1,53 @@
|
|
1
|
+
This is the proposed binary format for saving and loading NMatrix objects.
|
2
|
+
|
3
|
+
Order is little-endian.
|
4
|
+
|
5
|
+
List matrices should be converted to dense or yale matrices. There should be no serious need to load or save
|
6
|
+
linked-list matrices, since these exist primarily in order to construct efficient yale matrices.
|
7
|
+
|
8
|
+
|
9
|
+
First 64-bit block:
|
10
|
+
* ui16 major (version)
|
11
|
+
* ui16 minor
|
12
|
+
* ui16 release
|
13
|
+
* i16 NULL
|
14
|
+
|
15
|
+
|
16
|
+
Second 64-bit block:
|
17
|
+
* ui8 dtype
|
18
|
+
* ui8 stype
|
19
|
+
* ui8 itype # ui32 for dense
|
20
|
+
* ui8 symm
|
21
|
+
* i16 NULL
|
22
|
+
* ui16 dim # if 1, NVector; otherwise, NMatrix
|
23
|
+
|
24
|
+
|
25
|
+
3rd - nth 64-bit block: shape
|
26
|
+
|
27
|
+
itype sets the number of bytes allocated for each shape entry. Since only yale uses itype, dense will pretty
|
28
|
+
much always be the UINT32 itype (see nmatrix.h). If the total number of bytes occupied by the shape array is
|
29
|
+
less than 8, the rest of the 64-bit block will be padded with zeros.
|
30
|
+
|
31
|
+
|
32
|
+
(n+1)th 64-bit block: depends on stype, symm
|
33
|
+
|
34
|
+
symm is designed to reduce file size by allowing us to not save certain elements in symmetric, hermitian, skew-
|
35
|
+
symmetric, and triangular matrices. These values will be defined in nmatrix.h; 0 indicates standard (no symmetry).
|
36
|
+
In later versions, additional patterns may be defined which might even have less to do with symmetry than
|
37
|
+
upper/lower do.
|
38
|
+
|
39
|
+
When storing a symmetric matrix, we will only store the upper portion. If the matrix is lower triangular, only the
|
40
|
+
lower portion will be stored.
|
41
|
+
|
42
|
+
For dense, we simply store the contents of the matrix exactly as in memory (or just the upper-triangular part if
|
43
|
+
symm is set).
|
44
|
+
|
45
|
+
For yale, we store:
|
46
|
+
* ui32 ndnz
|
47
|
+
* ui32 length (AKA size, the number of elements in A/IJA that aren't nil/undefined)
|
48
|
+
|
49
|
+
The latter will serve as the capacity when we read a Yale matrix.
|
50
|
+
|
51
|
+
Then we store the a array, again padding with zeros so it's a multiple of 8 bytes.
|
52
|
+
|
53
|
+
Then we store the ija array, padding with zeros so it's a multiple of 8 bytes.
|
@@ -0,0 +1,399 @@
|
|
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
|
+
// == complex.h
|
25
|
+
//
|
26
|
+
// Functions and classes for dealing with complex numbers.
|
27
|
+
|
28
|
+
#ifndef COMPLEX_H
|
29
|
+
#define COMPLEX_H
|
30
|
+
|
31
|
+
/*
|
32
|
+
* Standard Includes
|
33
|
+
*/
|
34
|
+
|
35
|
+
#include <type_traits>
|
36
|
+
#include <iostream>
|
37
|
+
#include <cmath>
|
38
|
+
|
39
|
+
/*
|
40
|
+
* Project Includes
|
41
|
+
*/
|
42
|
+
|
43
|
+
#include "types.h"
|
44
|
+
|
45
|
+
/*
|
46
|
+
* Macros
|
47
|
+
*/
|
48
|
+
|
49
|
+
/*
|
50
|
+
* Types
|
51
|
+
*/
|
52
|
+
namespace nm {
|
53
|
+
|
54
|
+
class RubyObject;
|
55
|
+
template <typename IntType> class Rational;
|
56
|
+
template <typename Type> class Complex;
|
57
|
+
|
58
|
+
typedef Complex<float32_t> Complex64;
|
59
|
+
typedef Complex<float64_t> Complex128;
|
60
|
+
|
61
|
+
/*
|
62
|
+
* Data
|
63
|
+
*/
|
64
|
+
|
65
|
+
/*
|
66
|
+
* Classes and Functions
|
67
|
+
*/
|
68
|
+
|
69
|
+
template <typename Type>
|
70
|
+
class Complex {
|
71
|
+
public:
|
72
|
+
// The real and immaginary parts of the complex number.
|
73
|
+
Type r;
|
74
|
+
Type i;
|
75
|
+
|
76
|
+
/*
|
77
|
+
* Default constructor.
|
78
|
+
*/
|
79
|
+
inline Complex(Type real = 0, Type imaginary = 0) : r(real), i(imaginary) {}
|
80
|
+
|
81
|
+
/*
|
82
|
+
* Copy constructors.
|
83
|
+
*/
|
84
|
+
template <typename ComplexType>
|
85
|
+
inline Complex(const Complex<ComplexType>& other) : r(other.r), i(other.i) {}
|
86
|
+
|
87
|
+
template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
|
88
|
+
inline Complex(const Rational<IntType>& other) : r(Type(other.n) / Type(other.d)), i(0) {}
|
89
|
+
|
90
|
+
Complex(const RubyObject& other);
|
91
|
+
|
92
|
+
/*
|
93
|
+
* Complex conjugate function -- creates a copy, but inverted.
|
94
|
+
*/
|
95
|
+
inline Complex<Type> conjugate() const {
|
96
|
+
return Complex<Type>(this->r, -(this->i));
|
97
|
+
}
|
98
|
+
|
99
|
+
/*
|
100
|
+
* Complex inverse function -- creates a copy, but inverted.
|
101
|
+
*
|
102
|
+
* FIXME: Check that this doesn't duplicate functionality of NativeType / Complex<Type>
|
103
|
+
*/
|
104
|
+
inline Complex<Type> inverse() const {
|
105
|
+
Complex<Type> conj = conjugate();
|
106
|
+
Type denom = this->r * this->r + this->i * this->i;
|
107
|
+
return Complex<Type>(conj.r / denom, conj.i / denom);
|
108
|
+
}
|
109
|
+
|
110
|
+
|
111
|
+
|
112
|
+
/*
|
113
|
+
* Binary operator definitions for various types.
|
114
|
+
*/
|
115
|
+
|
116
|
+
////////////////////////////////
|
117
|
+
// Complex-Complex Operations //
|
118
|
+
////////////////////////////////
|
119
|
+
|
120
|
+
template <typename OtherType>
|
121
|
+
inline Complex<Type> operator+(const Complex<OtherType>& other) const {
|
122
|
+
return Complex<Type>(this->r + other.r, this->i + other.i);
|
123
|
+
}
|
124
|
+
|
125
|
+
template <typename OtherType>
|
126
|
+
inline Complex<Type>& operator+=(const Complex<OtherType>& other) {
|
127
|
+
this->r += other.r;
|
128
|
+
this->i += other.i;
|
129
|
+
return *this;
|
130
|
+
}
|
131
|
+
|
132
|
+
template <typename OtherType>
|
133
|
+
inline Complex<Type> operator-(const Complex<OtherType>& other) const {
|
134
|
+
return Complex<Type>(this->r - other.r, this->i - other.i);
|
135
|
+
}
|
136
|
+
|
137
|
+
template <typename OtherType>
|
138
|
+
inline Complex<Type> operator*(const Complex<OtherType>& other) const {
|
139
|
+
return Complex<Type>(this->r * other.r - this->i * other.i, this->r * other.i + this->i * other.r);
|
140
|
+
}
|
141
|
+
|
142
|
+
template <typename OtherType>
|
143
|
+
inline Complex<Type>& operator*=(const Complex<OtherType>& other) {
|
144
|
+
this->r = this->r * other.r - this->i * other.i;
|
145
|
+
this->i = this->r * other.i + this->i * other.r;
|
146
|
+
return *this;
|
147
|
+
}
|
148
|
+
|
149
|
+
template <typename OtherType>
|
150
|
+
inline Complex<Type> operator/(const Complex<OtherType>& other) const {
|
151
|
+
Type new_r, new_i;
|
152
|
+
Type denom = other.i * other.i + other.r * other.r;
|
153
|
+
|
154
|
+
new_r = (this->r * other.r + this->i * other.i) / denom;
|
155
|
+
new_i = (this->i * other.r - this->r * other.i) / denom;
|
156
|
+
|
157
|
+
return Complex<Type>(new_r, new_i);
|
158
|
+
}
|
159
|
+
|
160
|
+
template <typename OtherType>
|
161
|
+
inline bool operator<(const Complex<OtherType>& other) const {
|
162
|
+
return (this->r < other.r) || ((this->r <= other.r) && (this->i < other.i));
|
163
|
+
}
|
164
|
+
|
165
|
+
template <typename OtherType>
|
166
|
+
inline bool operator>(const Complex<OtherType>& other) const {
|
167
|
+
return (this->r > other.r) || ((this->r >= other.r) && (this->i > other.i));
|
168
|
+
}
|
169
|
+
|
170
|
+
template <typename OtherType>
|
171
|
+
inline bool operator==(const Complex<OtherType>& other) const {
|
172
|
+
return FP_EQUAL(this->r, other.r) && FP_EQUAL(this->i, other.i);
|
173
|
+
}
|
174
|
+
|
175
|
+
template <typename OtherType>
|
176
|
+
inline bool operator!=(const Complex<OtherType>& other) const {
|
177
|
+
return !(*this == other);
|
178
|
+
}
|
179
|
+
|
180
|
+
template <typename OtherType>
|
181
|
+
inline bool operator<=(const Complex<OtherType>& other) const {
|
182
|
+
return (*this < other) || (*this == other);
|
183
|
+
}
|
184
|
+
|
185
|
+
template <typename OtherType>
|
186
|
+
inline bool operator>=(const Complex<OtherType>& other) const {
|
187
|
+
return (*this > other) || (*this == other);
|
188
|
+
}
|
189
|
+
|
190
|
+
template <typename OtherType>
|
191
|
+
inline operator Complex<OtherType> () const {
|
192
|
+
return Complex<OtherType>((OtherType)this->r, (OtherType)this->i);
|
193
|
+
}
|
194
|
+
|
195
|
+
/////////////////////////////////
|
196
|
+
// Complex-Rational Operations //
|
197
|
+
/////////////////////////////////
|
198
|
+
|
199
|
+
template <typename RationalType>
|
200
|
+
inline Complex<Type> operator+(const Rational<RationalType>& other) const {
|
201
|
+
return *this + Complex<Type>(other);
|
202
|
+
}
|
203
|
+
|
204
|
+
template <typename RationalType>
|
205
|
+
inline Complex<Type> operator-(const Rational<RationalType>& other) const {
|
206
|
+
return *this - Complex<Type>(other);
|
207
|
+
}
|
208
|
+
|
209
|
+
template <typename RationalType>
|
210
|
+
inline Complex<Type> operator*(const Rational<RationalType>& other) const {
|
211
|
+
return *this * Complex<Type>(other);
|
212
|
+
}
|
213
|
+
|
214
|
+
template <typename RationalType>
|
215
|
+
inline Complex<Type> operator/(const Rational<RationalType>& other) const {
|
216
|
+
return *this / Complex<Type>(other);
|
217
|
+
}
|
218
|
+
|
219
|
+
template <typename RationalType, typename = typename std::enable_if<std::is_integral<RationalType>::value>::type>
|
220
|
+
inline bool operator!=(const Rational<RationalType>& other) const {
|
221
|
+
return *this != Complex<Type>(other);
|
222
|
+
}
|
223
|
+
|
224
|
+
template <typename RationalType, typename = typename std::enable_if<std::is_integral<RationalType>::value>::type>
|
225
|
+
inline bool operator==(const Rational<RationalType>& other) const {
|
226
|
+
return *this == Complex<Type>(other);
|
227
|
+
}
|
228
|
+
|
229
|
+
///////////////////////////////
|
230
|
+
// Complex-Native Operations //
|
231
|
+
///////////////////////////////
|
232
|
+
|
233
|
+
template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
234
|
+
inline Complex<Type> operator+(const NativeType& other) const {
|
235
|
+
return *this + Complex<Type>(other);
|
236
|
+
}
|
237
|
+
|
238
|
+
template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
239
|
+
inline Complex<Type> operator-(const NativeType& other) const {
|
240
|
+
return *this - Complex<Type>(other);
|
241
|
+
}
|
242
|
+
|
243
|
+
template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
244
|
+
inline Complex<Type> operator*(const NativeType& other) const {
|
245
|
+
return *this * Complex<Type>(other);
|
246
|
+
}
|
247
|
+
|
248
|
+
template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
249
|
+
inline Complex<Type> operator/(const NativeType& other) const {
|
250
|
+
return *this / Complex<Type>(other);
|
251
|
+
}
|
252
|
+
|
253
|
+
template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
254
|
+
inline bool operator<(const NativeType& other) const {
|
255
|
+
return *this < Complex<Type>(other);
|
256
|
+
}
|
257
|
+
|
258
|
+
template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
259
|
+
inline bool operator>(const NativeType& other) const {
|
260
|
+
return *this > Complex<Type>(other);
|
261
|
+
}
|
262
|
+
|
263
|
+
template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
264
|
+
inline bool operator==(const NativeType& other) const {
|
265
|
+
return *this == Complex<Type>(other);
|
266
|
+
}
|
267
|
+
|
268
|
+
template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
269
|
+
inline bool operator!=(const NativeType& other) const {
|
270
|
+
return *this != Complex<Type>(other);
|
271
|
+
}
|
272
|
+
|
273
|
+
template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
274
|
+
inline bool operator<=(const NativeType& other) const {
|
275
|
+
return *this <= Complex<Type>(other);
|
276
|
+
}
|
277
|
+
|
278
|
+
template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
279
|
+
inline bool operator>=(const NativeType& other) const {
|
280
|
+
return *this >= Complex<Type>(other);
|
281
|
+
}
|
282
|
+
|
283
|
+
template <typename NativeType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
284
|
+
inline operator NativeType () const {
|
285
|
+
return (NativeType)this->r;
|
286
|
+
}
|
287
|
+
};
|
288
|
+
|
289
|
+
|
290
|
+
/////////////////////////////////
|
291
|
+
// Rational-Complex Operations //
|
292
|
+
/////////////////////////////////
|
293
|
+
|
294
|
+
|
295
|
+
template <typename IntType, typename ComplexType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
|
296
|
+
inline bool operator==(const Rational<IntType>& left, const Complex<ComplexType>& right) {
|
297
|
+
return Complex<ComplexType>(left) == right;
|
298
|
+
}
|
299
|
+
|
300
|
+
template <typename IntType, typename ComplexType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
|
301
|
+
inline bool operator!=(const Rational<IntType>& left, const Complex<ComplexType>& right) {
|
302
|
+
return Complex<ComplexType>(left) != right;
|
303
|
+
}
|
304
|
+
|
305
|
+
|
306
|
+
///////////////////////////////
|
307
|
+
// Native-Complex Operations //
|
308
|
+
///////////////////////////////
|
309
|
+
|
310
|
+
template <typename NativeType, typename ComplexType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
311
|
+
inline Complex<ComplexType> operator+(const NativeType& left, const Complex<ComplexType>& right) {
|
312
|
+
return Complex<ComplexType>(left) + right;
|
313
|
+
}
|
314
|
+
|
315
|
+
template <typename NativeType, typename ComplexType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
316
|
+
inline Complex<ComplexType> operator-(const NativeType& left, const Complex<ComplexType>& right) {
|
317
|
+
return Complex<ComplexType>(left) - right;
|
318
|
+
}
|
319
|
+
|
320
|
+
template <typename NativeType, typename ComplexType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
321
|
+
inline Complex<ComplexType> operator*(const NativeType& left, const Complex<ComplexType>& right) {
|
322
|
+
return Complex<ComplexType>(left) * right;
|
323
|
+
}
|
324
|
+
|
325
|
+
template <typename NativeType, typename ComplexType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
326
|
+
inline Complex<ComplexType> operator/(const NativeType& left, const Complex<ComplexType>& right) {
|
327
|
+
return Complex<ComplexType>(left) / right;
|
328
|
+
}
|
329
|
+
|
330
|
+
template <typename NativeType, typename ComplexType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
331
|
+
inline bool operator<(const NativeType left, const Complex<ComplexType>& right) {
|
332
|
+
return Complex<ComplexType>(left) < right;
|
333
|
+
}
|
334
|
+
|
335
|
+
template <typename NativeType, typename ComplexType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
336
|
+
inline bool operator>(const NativeType left, const Complex<ComplexType>& right) {
|
337
|
+
return Complex<ComplexType>(left) > right;
|
338
|
+
}
|
339
|
+
|
340
|
+
template <typename NativeType, typename ComplexType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
341
|
+
inline bool operator==(const NativeType left, const Complex<ComplexType>& right) {
|
342
|
+
return Complex<ComplexType>(left) == right;
|
343
|
+
}
|
344
|
+
|
345
|
+
template <typename NativeType, typename ComplexType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
346
|
+
inline bool operator!=(const NativeType left, const Complex<ComplexType>& right) {
|
347
|
+
return Complex<ComplexType>(left) != right;
|
348
|
+
}
|
349
|
+
|
350
|
+
template <typename NativeType, typename ComplexType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
351
|
+
inline bool operator<=(const NativeType left, const Complex<ComplexType>& right) {
|
352
|
+
return Complex<ComplexType>(left) <= right;
|
353
|
+
}
|
354
|
+
|
355
|
+
template <typename NativeType, typename ComplexType, typename = typename std::enable_if<std::is_arithmetic<NativeType>::value>::type>
|
356
|
+
inline bool operator>=(const NativeType left, const Complex<ComplexType>& right) {
|
357
|
+
return Complex<ComplexType>(left) >= right;
|
358
|
+
}
|
359
|
+
|
360
|
+
template <typename Type>
|
361
|
+
inline std::ostream& operator<<(std::ostream& out, const Complex<Type>& rhs) {
|
362
|
+
out << "(" << rhs.r << "," << rhs.i << "i)" << std::flush;
|
363
|
+
return out;
|
364
|
+
}
|
365
|
+
|
366
|
+
// Negative operator
|
367
|
+
template <typename IntType, typename = typename std::enable_if<std::is_integral<IntType>::value>::type>
|
368
|
+
inline Complex<IntType> operator-(const Complex<IntType>& rhs) {
|
369
|
+
return Complex<IntType>(-rhs.r, -rhs.i);
|
370
|
+
}
|
371
|
+
|
372
|
+
} // end of namespace nm
|
373
|
+
|
374
|
+
namespace std {
|
375
|
+
template <typename FloatType, typename = typename std::enable_if<std::is_floating_point<FloatType>::value>::type>
|
376
|
+
nm::Complex<FloatType> piecewise_abs(const nm::Complex<FloatType>& value) {
|
377
|
+
return nm::Complex<FloatType>(value.r < 0 ? -value.r : value.r,
|
378
|
+
value.i < 0 ? -value.i : value.i);
|
379
|
+
}
|
380
|
+
|
381
|
+
template <typename FloatType, typename = typename std::enable_if<std::is_floating_point<FloatType>::value>::type>
|
382
|
+
nm::Complex<FloatType> real_abs(const nm::Complex<FloatType>& value) {
|
383
|
+
return nm::Complex<FloatType>(value.r < 0 ? -value.r : value.r,
|
384
|
+
value.i);
|
385
|
+
}
|
386
|
+
|
387
|
+
template <typename FloatType, typename = typename std::enable_if<std::is_floating_point<FloatType>::value>::type>
|
388
|
+
nm::Complex<FloatType> imag_abs(const nm::Complex<FloatType>& value) {
|
389
|
+
return nm::Complex<FloatType>(value.r,
|
390
|
+
value.i < 0 ? -value.i : value.i);
|
391
|
+
}
|
392
|
+
|
393
|
+
template <typename FloatType, typename = typename std::enable_if<std::is_floating_point<FloatType>::value>::type>
|
394
|
+
double abs(const nm::Complex<FloatType>& value) {
|
395
|
+
return std::sqrt(double(value.r)*double(value.r) + double(value.i)*double(value.i));
|
396
|
+
}
|
397
|
+
}
|
398
|
+
|
399
|
+
#endif // COMPLEX_H
|