nmatrix 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/CONTRIBUTING.md +66 -0
- data/Gemfile +1 -1
- data/History.txt +68 -10
- data/LICENSE.txt +2 -2
- data/Manifest.txt +2 -0
- data/README.rdoc +90 -69
- data/Rakefile +18 -9
- data/ext/nmatrix/data/complex.h +7 -7
- data/ext/nmatrix/data/data.cpp +2 -7
- data/ext/nmatrix/data/data.h +7 -4
- data/ext/nmatrix/data/rational.h +2 -2
- data/ext/nmatrix/data/ruby_object.h +3 -10
- data/ext/nmatrix/extconf.rb +79 -54
- data/ext/nmatrix/new_extconf.rb +11 -12
- data/ext/nmatrix/nmatrix.cpp +94 -125
- data/ext/nmatrix/nmatrix.h +38 -17
- data/ext/nmatrix/ruby_constants.cpp +2 -15
- data/ext/nmatrix/ruby_constants.h +2 -14
- data/ext/nmatrix/storage/common.cpp +2 -2
- data/ext/nmatrix/storage/common.h +2 -2
- data/ext/nmatrix/storage/dense.cpp +206 -31
- data/ext/nmatrix/storage/dense.h +5 -2
- data/ext/nmatrix/storage/list.cpp +52 -4
- data/ext/nmatrix/storage/list.h +3 -2
- data/ext/nmatrix/storage/storage.cpp +6 -6
- data/ext/nmatrix/storage/storage.h +2 -2
- data/ext/nmatrix/storage/yale.cpp +202 -49
- data/ext/nmatrix/storage/yale.h +5 -4
- data/ext/nmatrix/ttable_helper.rb +108 -108
- data/ext/nmatrix/types.h +2 -15
- data/ext/nmatrix/util/io.cpp +2 -2
- data/ext/nmatrix/util/io.h +2 -2
- data/ext/nmatrix/util/lapack.h +2 -2
- data/ext/nmatrix/util/math.cpp +14 -14
- data/ext/nmatrix/util/math.h +2 -2
- data/ext/nmatrix/util/sl_list.cpp +2 -2
- data/ext/nmatrix/util/sl_list.h +2 -2
- data/ext/nmatrix/util/util.h +2 -2
- data/lib/nmatrix.rb +13 -35
- data/lib/nmatrix/blas.rb +182 -56
- data/lib/nmatrix/io/market.rb +38 -14
- data/lib/nmatrix/io/mat5_reader.rb +393 -278
- data/lib/nmatrix/io/mat_reader.rb +121 -107
- data/lib/nmatrix/lapack.rb +59 -14
- data/lib/nmatrix/monkeys.rb +32 -30
- data/lib/nmatrix/nmatrix.rb +204 -100
- data/lib/nmatrix/nvector.rb +166 -57
- data/lib/nmatrix/shortcuts.rb +364 -231
- data/lib/nmatrix/version.rb +8 -4
- data/nmatrix.gemspec +5 -3
- data/scripts/mac-brew-gcc.sh +1 -1
- data/spec/blas_spec.rb +80 -2
- data/spec/math_spec.rb +78 -32
- data/spec/nmatrix_list_spec.rb +55 -55
- data/spec/nmatrix_spec.rb +60 -117
- data/spec/nmatrix_yale_resize_test_associations.yaml +2802 -0
- data/spec/nmatrix_yale_spec.rb +214 -198
- data/spec/nvector_spec.rb +58 -2
- data/spec/shortcuts_spec.rb +156 -32
- data/spec/slice_spec.rb +229 -178
- data/spec/spec_helper.rb +2 -2
- metadata +71 -21
data/ext/nmatrix/data/complex.h
CHANGED
@@ -9,8 +9,8 @@
|
|
9
9
|
//
|
10
10
|
// == Copyright Information
|
11
11
|
//
|
12
|
-
// SciRuby is Copyright (c) 2010 -
|
13
|
-
// NMatrix is Copyright (c)
|
12
|
+
// SciRuby is Copyright (c) 2010 - 2013, Ruby Science Foundation
|
13
|
+
// NMatrix is Copyright (c) 2013, Ruby Science Foundation
|
14
14
|
//
|
15
15
|
// Please see LICENSE.txt for additional copyright notices.
|
16
16
|
//
|
@@ -132,23 +132,23 @@ class Complex {
|
|
132
132
|
|
133
133
|
template <typename OtherType>
|
134
134
|
inline Complex<Type> operator*(const Complex<OtherType>& other) const {
|
135
|
-
return Complex<Type>(this->r * other.r - this->i * other.i, this->r * other.i
|
135
|
+
return Complex<Type>(this->r * other.r - this->i * other.i, this->r * other.i + this->i * other.r);
|
136
136
|
}
|
137
137
|
|
138
138
|
template <typename OtherType>
|
139
139
|
inline Complex<Type>& operator*=(const Complex<OtherType>& other) {
|
140
140
|
this->r = this->r * other.r - this->i * other.i;
|
141
|
-
this->i = this->r * other.i
|
141
|
+
this->i = this->r * other.i + this->i * other.r;
|
142
142
|
return *this;
|
143
143
|
}
|
144
144
|
|
145
145
|
template <typename OtherType>
|
146
146
|
inline Complex<Type> operator/(const Complex<OtherType>& other) const {
|
147
147
|
Type new_r, new_i;
|
148
|
-
Type denom =
|
148
|
+
Type denom = other.i * other.i + other.r * other.r;
|
149
149
|
|
150
150
|
new_r = (this->r * other.r + this->i * other.i) / denom;
|
151
|
-
new_i = (this->
|
151
|
+
new_i = (this->i * other.r - this->r * other.i) / denom;
|
152
152
|
|
153
153
|
return Complex<Type>(new_r, new_i);
|
154
154
|
}
|
@@ -199,7 +199,7 @@ class Complex {
|
|
199
199
|
|
200
200
|
template <typename RationalType>
|
201
201
|
inline Complex<Type> operator-(const Rational<RationalType>& other) const {
|
202
|
-
return *this
|
202
|
+
return *this - Complex<Type>(other);
|
203
203
|
}
|
204
204
|
|
205
205
|
template <typename RationalType>
|
data/ext/nmatrix/data/data.cpp
CHANGED
@@ -9,8 +9,8 @@
|
|
9
9
|
//
|
10
10
|
// == Copyright Information
|
11
11
|
//
|
12
|
-
// SciRuby is Copyright (c) 2010 -
|
13
|
-
// NMatrix is Copyright (c)
|
12
|
+
// SciRuby is Copyright (c) 2010 - 2013, Ruby Science Foundation
|
13
|
+
// NMatrix is Copyright (c) 2013, Ruby Science Foundation
|
14
14
|
//
|
15
15
|
// Please see LICENSE.txt for additional copyright notices.
|
16
16
|
//
|
@@ -36,13 +36,8 @@
|
|
36
36
|
*/
|
37
37
|
|
38
38
|
#include "types.h"
|
39
|
-
|
40
39
|
#include "data.h"
|
41
40
|
|
42
|
-
/*
|
43
|
-
* Macros
|
44
|
-
*/
|
45
|
-
|
46
41
|
/*
|
47
42
|
* Global Variables
|
48
43
|
*/
|
data/ext/nmatrix/data/data.h
CHANGED
@@ -9,8 +9,8 @@
|
|
9
9
|
//
|
10
10
|
// == Copyright Information
|
11
11
|
//
|
12
|
-
// SciRuby is Copyright (c) 2010 -
|
13
|
-
// NMatrix is Copyright (c)
|
12
|
+
// SciRuby is Copyright (c) 2010 - 2013, Ruby Science Foundation
|
13
|
+
// NMatrix is Copyright (c) 2013, Ruby Science Foundation
|
14
14
|
//
|
15
15
|
// Please see LICENSE.txt for additional copyright notices.
|
16
16
|
//
|
@@ -107,7 +107,8 @@ namespace nm {
|
|
107
107
|
fun<nm::Complex128>, \
|
108
108
|
fun<nm::Rational32>, \
|
109
109
|
fun<nm::Rational64>, \
|
110
|
-
fun<nm::Rational128
|
110
|
+
fun<nm::Rational128>, \
|
111
|
+
fun<nm::RubyObject> \
|
111
112
|
};
|
112
113
|
|
113
114
|
#define NAMED_DTYPE_TEMPLATE_TABLE_NO_ROBJ(name, fun, ret, ...) \
|
@@ -123,7 +124,7 @@ namespace nm {
|
|
123
124
|
fun<nm::Complex128>, \
|
124
125
|
fun<nm::Rational32>, \
|
125
126
|
fun<nm::Rational64>, \
|
126
|
-
fun<nm::Rational128
|
127
|
+
fun<nm::Rational128> \
|
127
128
|
};
|
128
129
|
|
129
130
|
/*
|
@@ -615,6 +616,8 @@ namespace nm {
|
|
615
616
|
{fun<nm::EW_GEQ, uint32_t, uint8_t>,fun<nm::EW_GEQ, uint32_t, int8_t>,fun<nm::EW_GEQ, uint32_t, int16_t>,fun<nm::EW_GEQ, uint32_t, int32_t>,fun<nm::EW_GEQ, uint32_t, int64_t>,fun<nm::EW_GEQ, uint32_t, float32_t>,fun<nm::EW_GEQ, uint32_t, float64_t>,fun<nm::EW_GEQ, uint32_t, nm::Complex64>,fun<nm::EW_GEQ, uint32_t, nm::Complex128>,fun<nm::EW_GEQ, uint32_t, nm::Rational32>,fun<nm::EW_GEQ, uint32_t, nm::Rational64>,fun<nm::EW_GEQ, uint32_t, nm::Rational128>,fun<nm::EW_GEQ, uint32_t, nm::RubyObject>},\
|
616
617
|
{fun<nm::EW_GEQ, uint64_t, uint8_t>,fun<nm::EW_GEQ, uint64_t, int8_t>,fun<nm::EW_GEQ, uint64_t, int16_t>,fun<nm::EW_GEQ, uint64_t, int32_t>,fun<nm::EW_GEQ, uint64_t, int64_t>,fun<nm::EW_GEQ, uint64_t, float32_t>,fun<nm::EW_GEQ, uint64_t, float64_t>,fun<nm::EW_GEQ, uint64_t, nm::Complex64>,fun<nm::EW_GEQ, uint64_t, nm::Complex128>,fun<nm::EW_GEQ, uint64_t, nm::Rational32>,fun<nm::EW_GEQ, uint64_t, nm::Rational64>,fun<nm::EW_GEQ, uint64_t, nm::Rational128>,fun<nm::EW_GEQ, uint64_t, nm::RubyObject>}}};
|
617
618
|
|
619
|
+
|
620
|
+
|
618
621
|
/*
|
619
622
|
* Defines a static array that holds function pointers to left dtype, right
|
620
623
|
* dtype, and itype templated versions of the specified function.
|
data/ext/nmatrix/data/rational.h
CHANGED
@@ -9,8 +9,8 @@
|
|
9
9
|
//
|
10
10
|
// == Copyright Information
|
11
11
|
//
|
12
|
-
// SciRuby is Copyright (c) 2010 -
|
13
|
-
// NMatrix is Copyright (c)
|
12
|
+
// SciRuby is Copyright (c) 2010 - 2013, Ruby Science Foundation
|
13
|
+
// NMatrix is Copyright (c) 2013, Ruby Science Foundation
|
14
14
|
//
|
15
15
|
// Please see LICENSE.txt for additional copyright notices.
|
16
16
|
//
|
@@ -9,8 +9,8 @@
|
|
9
9
|
//
|
10
10
|
// == Copyright Information
|
11
11
|
//
|
12
|
-
// SciRuby is Copyright (c) 2010 -
|
13
|
-
// NMatrix is Copyright (c)
|
12
|
+
// SciRuby is Copyright (c) 2010 - 2013, Ruby Science Foundation
|
13
|
+
// NMatrix is Copyright (c) 2013, Ruby Science Foundation
|
14
14
|
//
|
15
15
|
// Please see LICENSE.txt for additional copyright notices.
|
16
16
|
//
|
@@ -50,17 +50,10 @@
|
|
50
50
|
if (TYPE(val) != T_DATA || (RDATA(val)->dfree != (RUBY_DATA_FUNC)nm_delete && RDATA(val)->dfree != (RUBY_DATA_FUNC)nm_delete_ref)) \
|
51
51
|
rb_raise(rb_eTypeError, "Expected NMatrix on left-hand side of operation.");
|
52
52
|
|
53
|
-
/*
|
54
|
-
* Types
|
55
|
-
*/
|
56
|
-
|
57
|
-
/*
|
58
|
-
* Data
|
59
|
-
*/
|
60
|
-
|
61
53
|
/*
|
62
54
|
* Classes and Functions
|
63
55
|
*/
|
56
|
+
|
64
57
|
namespace nm {
|
65
58
|
template<typename T, typename U>
|
66
59
|
struct made_from_same_template : std::false_type {};
|
data/ext/nmatrix/extconf.rb
CHANGED
@@ -8,8 +8,8 @@
|
|
8
8
|
#
|
9
9
|
# == Copyright Information
|
10
10
|
#
|
11
|
-
# SciRuby is Copyright (c) 2010 -
|
12
|
-
# NMatrix is Copyright (c)
|
11
|
+
# SciRuby is Copyright (c) 2010 - 2013, Ruby Science Foundation
|
12
|
+
# NMatrix is Copyright (c) 2013, Ruby Science Foundation
|
13
13
|
#
|
14
14
|
# Please see LICENSE.txt for additional copyright notices.
|
15
15
|
#
|
@@ -29,7 +29,7 @@ require "mkmf"
|
|
29
29
|
|
30
30
|
|
31
31
|
# Function derived from NArray's extconf.rb.
|
32
|
-
def have_type(type, header=nil)
|
32
|
+
def have_type(type, header=nil) #:nodoc:
|
33
33
|
printf "checking for %s... ", type
|
34
34
|
STDOUT.flush
|
35
35
|
|
@@ -60,31 +60,36 @@ SRC
|
|
60
60
|
end
|
61
61
|
|
62
62
|
# Function derived from NArray's extconf.rb.
|
63
|
-
def create_conf_h(file)
|
63
|
+
def create_conf_h(file) #:nodoc:
|
64
64
|
print "creating #{file}\n"
|
65
65
|
File.open(file, 'w') do |hfile|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
66
|
+
header_guard = file.upcase.sub(/\s|\./, '_')
|
67
|
+
|
68
|
+
hfile.puts "#ifndef #{header_guard}"
|
69
|
+
hfile.puts "#define #{header_guard}"
|
70
|
+
hfile.puts
|
71
|
+
|
72
|
+
# FIXME: Find a better way to do this:
|
73
|
+
if RUBY_VERSION >= '2.0'
|
74
|
+
hfile.puts "#define RUBY_2 1"
|
75
|
+
end
|
76
|
+
|
77
|
+
for line in $defs
|
78
|
+
line =~ /^-D(.*)/
|
79
|
+
hfile.printf "#define %s 1\n", $1
|
80
|
+
end
|
81
|
+
|
82
|
+
hfile.puts
|
83
|
+
hfile.puts "#endif"
|
79
84
|
end
|
80
85
|
end
|
81
86
|
|
82
87
|
if RUBY_VERSION < '1.9'
|
83
|
-
raise(NotImplementedError, "Sorry, you need Ruby 1.9!")
|
88
|
+
raise(NotImplementedError, "Sorry, you need at least Ruby 1.9!")
|
84
89
|
else
|
85
90
|
$INSTALLFILES = [['nmatrix.h', '$(archdir)'], ['nmatrix.hpp', '$(archdir)'], ['nmatrix_config.h', '$(archdir)']]
|
86
91
|
if /cygwin|mingw/ =~ RUBY_PLATFORM
|
87
|
-
|
92
|
+
$INSTALLFILES << ['libnmatrix.a', '$(archdir)']
|
88
93
|
end
|
89
94
|
end
|
90
95
|
|
@@ -96,24 +101,28 @@ $DEBUG = true
|
|
96
101
|
$CFLAGS = ["-Wall ",$CFLAGS].join(" ")
|
97
102
|
|
98
103
|
$srcs = [
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
]
|
104
|
+
'nmatrix.cpp',
|
105
|
+
'ruby_constants.cpp',
|
106
|
+
|
107
|
+
'data/data.cpp',
|
108
|
+
'util/math.cpp',
|
109
|
+
'util/sl_list.cpp',
|
110
|
+
'util/io.cpp',
|
111
|
+
'storage/common.cpp',
|
112
|
+
'storage/storage.cpp',
|
113
|
+
'storage/dense.cpp',
|
114
|
+
'storage/yale.cpp',
|
115
|
+
'storage/list.cpp'
|
116
|
+
]
|
112
117
|
# add smmp in to get generic transp; remove smmp2 to eliminate funcptr transp
|
113
118
|
|
114
|
-
# The next line allows the user to supply --with-atlas-
|
115
|
-
# and tell the compiler where to look
|
116
|
-
|
119
|
+
# The next line allows the user to supply --with-atlas-dir=/usr/local/atlas,
|
120
|
+
# --with-atlas-lib or --with-atlas-include and tell the compiler where to look
|
121
|
+
# for ATLAS. The same for all the others
|
122
|
+
#
|
123
|
+
#dir_config("clapack", ["/usr/local/atlas/include"], [])
|
124
|
+
#
|
125
|
+
#
|
117
126
|
|
118
127
|
# Is g++ having trouble finding your header files?
|
119
128
|
# Try this:
|
@@ -121,15 +130,31 @@ dir_config("atlas")
|
|
121
130
|
# export CPLUS_INCLUDE_PATH=/usr/local/atlas/include
|
122
131
|
# (substituting in the path of your cblas.h and clapack.h for the path I used). -- JW 8/27/12
|
123
132
|
|
124
|
-
find_library("lapack", "clapack_dgetrf", "/usr/local/lib", "/usr/local/atlas/lib")
|
125
|
-
find_header("clapack.h", "/usr/local/atlas/include")
|
126
|
-
have_header("clapack.h")
|
127
133
|
|
128
|
-
|
129
|
-
|
130
|
-
|
134
|
+
unless have_library("lapack")
|
135
|
+
dir_config("lapack", ["/usr/include/atlas"], ["/usr/local/lib", "/usr/local/atlas/lib"])
|
136
|
+
end
|
137
|
+
|
138
|
+
unless have_library("cblas")
|
139
|
+
dir_config("cblas", ["/usr/local/atlas/include", "/usr/include/atlas"], ["/usr/local/lib", "/usr/local/atlas/lib"])
|
140
|
+
end
|
141
|
+
|
142
|
+
unless have_library("atlas")
|
143
|
+
dir_config("atlas", ["/usr/local/atlas/include", "/usr/include/atlas"], ["/usr/local/atlas/lib", "/usr/local/lib", "/usr/lib"])
|
144
|
+
end
|
145
|
+
|
146
|
+
#find_library("lapack", "clapack_dgetrf")
|
147
|
+
have_header("clapack.h")
|
131
148
|
have_header("cblas.h")
|
132
149
|
|
150
|
+
have_func("clapack_dgetrf", "clapack.h")
|
151
|
+
|
152
|
+
|
153
|
+
#find_library("cblas", "cblas_dgemm")
|
154
|
+
#find_library("atlas", "ATL_dgemmNN")
|
155
|
+
|
156
|
+
have_func("cblas_dgemm", "cblas.h")
|
157
|
+
|
133
158
|
# Order matters here: ATLAS has to go after LAPACK: http://mail.scipy.org/pipermail/scipy-user/2007-January/010717.html
|
134
159
|
$libs += " -llapack -lcblas -latlas "
|
135
160
|
|
@@ -138,8 +163,8 @@ $objs = %w{nmatrix ruby_constants data/data util/io util/math util/sl_list stora
|
|
138
163
|
#CONFIG['CXX'] = 'clang++'
|
139
164
|
CONFIG['CXX'] = 'g++'
|
140
165
|
|
141
|
-
def find_newer_gplusplus
|
142
|
-
[7,6,5,4,3].each do |minor|
|
166
|
+
def find_newer_gplusplus #:nodoc:
|
167
|
+
[8,7,6,5,4,3].each do |minor|
|
143
168
|
result = `which g++-4.#{minor}`
|
144
169
|
next if result.empty?
|
145
170
|
CONFIG['CXX'] = "g++-4.#{minor}"
|
@@ -148,16 +173,16 @@ def find_newer_gplusplus
|
|
148
173
|
false
|
149
174
|
end
|
150
175
|
|
151
|
-
def gplusplus_version
|
152
|
-
|
176
|
+
def gplusplus_version #:nodoc:
|
177
|
+
`LANG="en_US" #{CONFIG['CXX']} -v 2>&1`.lines.to_a.last.match(/gcc\sversion\s(\d\.\d.\d)/).captures.first
|
153
178
|
end
|
154
179
|
|
155
180
|
|
156
181
|
if CONFIG['CXX'] == 'clang++'
|
157
|
-
|
182
|
+
$CPP_STANDARD = 'c++11'
|
158
183
|
|
159
184
|
else
|
160
|
-
|
185
|
+
version = gplusplus_version
|
161
186
|
if version < '4.3.0' && CONFIG['CXX'] == 'g++' # see if we can find a newer G++, unless it's been overridden by user
|
162
187
|
if !find_newer_gplusplus
|
163
188
|
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++.")
|
@@ -165,16 +190,16 @@ else
|
|
165
190
|
version = gplusplus_version
|
166
191
|
end
|
167
192
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
193
|
+
if version < '4.7.0'
|
194
|
+
$CPP_STANDARD = 'c++0x'
|
195
|
+
else
|
196
|
+
$CPP_STANDARD = 'c++11'
|
197
|
+
end
|
173
198
|
end
|
174
199
|
|
175
200
|
# For release, these next two should both be changed to -O3.
|
176
|
-
$CFLAGS += " -O0 "
|
177
|
-
$CPPFLAGS += " -O0 -std=#{$CPP_STANDARD} " #-fmax-errors=10 -save-temps
|
201
|
+
$CFLAGS += " -O0 -g "
|
202
|
+
$CPPFLAGS += " -O0 -g -std=#{$CPP_STANDARD} " #-fmax-errors=10 -save-temps
|
178
203
|
|
179
204
|
CONFIG['warnflags'].gsub!('-Wshorten-64-to-32', '') # doesn't work except in Mac-patched gcc (4.2)
|
180
205
|
CONFIG['warnflags'].gsub!('-Wdeclaration-after-statement', '')
|
data/ext/nmatrix/new_extconf.rb
CHANGED
@@ -31,26 +31,25 @@ $CFLAGS = '-I. -fPIC -Wall -pipe -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fst
|
|
31
31
|
CONFIG['CXXFLAGS'] = '-std=c++11'
|
32
32
|
|
33
33
|
if clang_path = find_executable('clang') and clang_pp_path = find_executable('clang++')
|
34
|
-
|
35
|
-
|
34
|
+
CONFIG['CC'] = clang_path
|
35
|
+
CONFIG['CXX'] = clang_pp_path
|
36
36
|
end
|
37
37
|
|
38
38
|
# Necessary header files.
|
39
|
-
find_header('ruby/config.h')
|
39
|
+
find_header('ruby/config.h')
|
40
40
|
|
41
41
|
# List the source files that need to be compiled.
|
42
42
|
$srcs = [
|
43
|
-
# 'nmatrix.cpp',
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
]
|
43
|
+
# 'nmatrix.cpp',
|
44
|
+
'ruby_constants.cpp',
|
45
|
+
|
46
|
+
'data/data.cpp',
|
47
|
+
'math.cpp',
|
48
|
+
'storage/storage.cpp',
|
49
|
+
'storage/dense.cpp'
|
50
|
+
]
|
51
51
|
|
52
52
|
$objs = $srcs.map { |f| f.sub('.cpp', '.o') }
|
53
53
|
|
54
54
|
# Create the actual Makefile.
|
55
55
|
create_makefile('NMatrix')
|
56
|
-
|
data/ext/nmatrix/nmatrix.cpp
CHANGED
@@ -9,8 +9,8 @@
|
|
9
9
|
//
|
10
10
|
// == Copyright Information
|
11
11
|
//
|
12
|
-
// SciRuby is Copyright (c) 2010 -
|
13
|
-
// NMatrix is Copyright (c)
|
12
|
+
// SciRuby is Copyright (c) 2010 - 2013, Ruby Science Foundation
|
13
|
+
// NMatrix is Copyright (c) 2013, Ruby Science Foundation
|
14
14
|
//
|
15
15
|
// Please see LICENSE.txt for additional copyright notices.
|
16
16
|
//
|
@@ -23,9 +23,9 @@
|
|
23
23
|
//
|
24
24
|
// == nmatrix.cpp
|
25
25
|
//
|
26
|
-
// Main C++ source file for NMatrix. Contains Init_nmatrix and most Ruby
|
27
|
-
// class methods for NMatrix. Also responsible for calling Init
|
28
|
-
// modules.
|
26
|
+
// Main C++ source file for NMatrix. Contains Init_nmatrix and most Ruby
|
27
|
+
// instance and class methods for NMatrix. Also responsible for calling Init
|
28
|
+
// methods on related modules.
|
29
29
|
|
30
30
|
/*
|
31
31
|
* Standard Includes
|
@@ -44,6 +44,7 @@ extern "C" {
|
|
44
44
|
/*
|
45
45
|
* Project Includes
|
46
46
|
*/
|
47
|
+
|
47
48
|
#include "types.h"
|
48
49
|
#include "data/data.h"
|
49
50
|
#include "util/math.h"
|
@@ -58,26 +59,11 @@ extern "C" {
|
|
58
59
|
* Macros
|
59
60
|
*/
|
60
61
|
|
61
|
-
/*
|
62
|
-
* If no block is given, return an enumerator. This copied straight out of ruby's include/ruby/intern.h.
|
63
|
-
*
|
64
|
-
* rb_enumeratorize is located in enumerator.c.
|
65
|
-
*
|
66
|
-
* VALUE rb_enumeratorize(VALUE obj, VALUE meth, int argc, VALUE *argv) {
|
67
|
-
* return enumerator_init(enumerator_allocate(rb_cEnumerator), obj, meth, argc, argv);
|
68
|
-
* }
|
69
|
-
*/
|
70
|
-
#define RETURN_ENUMERATOR(obj, argc, argv) do { \
|
71
|
-
if (!rb_block_given_p()) \
|
72
|
-
return rb_enumeratorize((obj), ID2SYM(rb_frame_this_func()), \
|
73
|
-
(argc), (argv)); \
|
74
|
-
} while (0)
|
75
62
|
|
76
63
|
/*
|
77
64
|
* Global Variables
|
78
65
|
*/
|
79
66
|
|
80
|
-
|
81
67
|
namespace nm {
|
82
68
|
|
83
69
|
/*
|
@@ -144,7 +130,6 @@ namespace nm {
|
|
144
130
|
return bytes_written;
|
145
131
|
}
|
146
132
|
|
147
|
-
|
148
133
|
/*
|
149
134
|
* We need to specialize for Hermitian matrices. The next six functions accomplish that specialization, basically
|
150
135
|
* by ensuring that non-complex matrices cannot read or write hermitians (which would cause big problems).
|
@@ -187,7 +172,6 @@ namespace nm {
|
|
187
172
|
}
|
188
173
|
}
|
189
174
|
|
190
|
-
|
191
175
|
/*
|
192
176
|
* Read the elements of a dense storage matrix from a binary file, padded to 64-bits.
|
193
177
|
*
|
@@ -259,8 +243,6 @@ namespace nm {
|
|
259
243
|
if (bytes_read % 8) f.ignore(bytes_read % 8);
|
260
244
|
}
|
261
245
|
|
262
|
-
|
263
|
-
|
264
246
|
template <typename DType, typename IType>
|
265
247
|
void write_padded_yale_elements(std::ofstream& f, YALE_STORAGE* storage, size_t length, nm::symm_t symm) {
|
266
248
|
if (symm != nm::NONSYMM) rb_raise(rb_eNotImpError, "Yale matrices can only be read/written in full form");
|
@@ -299,8 +281,6 @@ namespace nm {
|
|
299
281
|
f.read(reinterpret_cast<char*>(&padding), bytes_read % 8);
|
300
282
|
}
|
301
283
|
|
302
|
-
|
303
|
-
|
304
284
|
/*
|
305
285
|
* Write the elements of a dense storage matrix to a binary file, padded to 64-bits.
|
306
286
|
*/
|
@@ -340,7 +320,6 @@ namespace nm {
|
|
340
320
|
|
341
321
|
} // end of namespace nm
|
342
322
|
|
343
|
-
|
344
323
|
extern "C" {
|
345
324
|
|
346
325
|
/*
|
@@ -365,6 +344,7 @@ static VALUE nm_dim(VALUE self);
|
|
365
344
|
static VALUE nm_shape(VALUE self);
|
366
345
|
static VALUE nm_capacity(VALUE self);
|
367
346
|
static VALUE nm_each(VALUE nmatrix);
|
347
|
+
static VALUE nm_each_stored_with_indices(VALUE nmatrix);
|
368
348
|
|
369
349
|
static SLICE* get_slice(size_t dim, VALUE* c, VALUE self);
|
370
350
|
static VALUE nm_xslice(int argc, VALUE* argv, void* (*slice_func)(STORAGE*, SLICE*), void (*delete_func)(NMATRIX*), VALUE self);
|
@@ -429,16 +409,11 @@ static VALUE nm_upcast(VALUE self, VALUE t1, VALUE t2);
|
|
429
409
|
static double get_time(void);
|
430
410
|
#endif
|
431
411
|
|
432
|
-
/*
|
433
|
-
* Functions
|
434
|
-
*/
|
435
|
-
|
436
412
|
///////////////////
|
437
413
|
// Ruby Bindings //
|
438
414
|
///////////////////
|
439
415
|
|
440
416
|
void Init_nmatrix() {
|
441
|
-
|
442
417
|
///////////////////////
|
443
418
|
// Class Definitions //
|
444
419
|
///////////////////////
|
@@ -447,8 +422,16 @@ void Init_nmatrix() {
|
|
447
422
|
cNVector = rb_define_class("NVector", cNMatrix);
|
448
423
|
|
449
424
|
// Special exceptions
|
450
|
-
|
451
|
-
|
425
|
+
|
426
|
+
/*
|
427
|
+
* Exception raised when there's a problem with data.
|
428
|
+
*/
|
429
|
+
nm_eDataTypeError = rb_define_class("DataTypeError", rb_eStandardError);
|
430
|
+
|
431
|
+
/*
|
432
|
+
* Exception raised when something goes wrong with the storage of a matrix.
|
433
|
+
*/
|
434
|
+
nm_eStorageTypeError = rb_define_class("StorageTypeError", rb_eStandardError);
|
452
435
|
|
453
436
|
///////////////////
|
454
437
|
// Class Methods //
|
@@ -487,8 +470,8 @@ void Init_nmatrix() {
|
|
487
470
|
rb_define_method(cNMatrix, "is_ref?", (METHOD)nm_is_ref, 0);
|
488
471
|
rb_define_method(cNMatrix, "dimensions", (METHOD)nm_dim, 0);
|
489
472
|
|
490
|
-
|
491
|
-
rb_define_alias(cNMatrix, "to_h", "to_hash");
|
473
|
+
rb_define_protected_method(cNMatrix, "to_hash_c", (METHOD)nm_to_hash, 0); // handles list and dense, which are n-dimensional
|
474
|
+
//rb_define_alias(cNMatrix, "to_h", "to_hash");
|
492
475
|
|
493
476
|
rb_define_method(cNMatrix, "shape", (METHOD)nm_shape, 0);
|
494
477
|
rb_define_method(cNMatrix, "det_exact", (METHOD)nm_det_exact, 0);
|
@@ -496,6 +479,7 @@ void Init_nmatrix() {
|
|
496
479
|
rb_define_method(cNMatrix, "complex_conjugate!", (METHOD)nm_complex_conjugate_bang, 0);
|
497
480
|
|
498
481
|
rb_define_method(cNMatrix, "each", (METHOD)nm_each, 0);
|
482
|
+
rb_define_method(cNMatrix, "each_stored_with_indices", (METHOD)nm_each_stored_with_indices, 0);
|
499
483
|
|
500
484
|
rb_define_method(cNMatrix, "==", (METHOD)nm_eqeq, 1);
|
501
485
|
|
@@ -574,8 +558,6 @@ static VALUE nm_alloc(VALUE klass) {
|
|
574
558
|
return Data_Wrap_Struct(klass, NULL, nm_delete, mat);
|
575
559
|
}
|
576
560
|
|
577
|
-
|
578
|
-
|
579
561
|
/*
|
580
562
|
* Find the capacity of an NMatrix. The capacity only differs from the size for
|
581
563
|
* Yale matrices, which occasionally allocate more space than they need. For
|
@@ -629,6 +611,9 @@ static void nm_delete_ref(NMATRIX* mat) {
|
|
629
611
|
}
|
630
612
|
|
631
613
|
/*
|
614
|
+
* call-seq:
|
615
|
+
* dtype -> Symbol
|
616
|
+
*
|
632
617
|
* Get the data type (dtype) of a matrix, e.g., :byte, :int8, :int16, :int32,
|
633
618
|
* :int64, :float32, :float64, :complex64, :complex128, :rational32,
|
634
619
|
* :rational64, :rational128, or :object (the last is a Ruby object).
|
@@ -638,8 +623,10 @@ static VALUE nm_dtype(VALUE self) {
|
|
638
623
|
return ID2SYM(dtype);
|
639
624
|
}
|
640
625
|
|
641
|
-
|
642
626
|
/*
|
627
|
+
* call-seq:
|
628
|
+
* itype -> Symbol or nil
|
629
|
+
*
|
643
630
|
* Get the index data type (dtype) of a matrix. Defined only for yale; others return nil.
|
644
631
|
*/
|
645
632
|
static VALUE nm_itype(VALUE self) {
|
@@ -650,7 +637,6 @@ static VALUE nm_itype(VALUE self) {
|
|
650
637
|
return Qnil;
|
651
638
|
}
|
652
639
|
|
653
|
-
|
654
640
|
/*
|
655
641
|
* Get the index data type (dtype) of a matrix. Defined only for yale; others return nil.
|
656
642
|
*/
|
@@ -665,8 +651,10 @@ static VALUE nm_itype_by_shape(VALUE self, VALUE shape_arg) {
|
|
665
651
|
return ID2SYM(itype_id);
|
666
652
|
}
|
667
653
|
|
668
|
-
|
669
654
|
/*
|
655
|
+
* call-seq:
|
656
|
+
* upcast(first_dtype, second_dtype) ->
|
657
|
+
*
|
670
658
|
* Given a binary operation between types t1 and t2, what type will be returned?
|
671
659
|
*
|
672
660
|
* This is a singleton method on NMatrix, e.g., NMatrix.upcast(:int32, :int64)
|
@@ -680,62 +668,11 @@ static VALUE nm_upcast(VALUE self, VALUE t1, VALUE t2) {
|
|
680
668
|
}
|
681
669
|
|
682
670
|
|
683
|
-
/*
|
684
|
-
* Each: Yield objects directly (suitable only for a dense matrix of Ruby objects).
|
685
|
-
*/
|
686
|
-
static VALUE nm_dense_each_direct(VALUE nm) {
|
687
|
-
DENSE_STORAGE* s = NM_STORAGE_DENSE(nm);
|
688
|
-
|
689
|
-
RETURN_ENUMERATOR(nm, 0, 0);
|
690
|
-
|
691
|
-
for (size_t i = 0; i < nm_storage_count_max_elements(s); ++i)
|
692
|
-
rb_yield( reinterpret_cast<VALUE*>(s->elements)[i] );
|
693
|
-
|
694
|
-
return nm;
|
695
|
-
}
|
696
|
-
|
697
|
-
/*
|
698
|
-
* Each: Copy matrix elements into Ruby VALUEs before operating on them (suitable for a dense matrix).
|
699
|
-
*/
|
700
|
-
static VALUE nm_dense_each_indirect(VALUE nm) {
|
701
|
-
DENSE_STORAGE* s = NM_STORAGE_DENSE(nm);
|
702
|
-
|
703
|
-
RETURN_ENUMERATOR(nm, 0, 0);
|
704
|
-
|
705
|
-
for (size_t i = 0; i < nm_storage_count_max_elements(s); ++i) {
|
706
|
-
VALUE v = rubyobj_from_cval((char*)(s->elements) + i*DTYPE_SIZES[NM_DTYPE(nm)], NM_DTYPE(nm)).rval;
|
707
|
-
rb_yield( v ); // yield to the copy we made
|
708
|
-
}
|
709
|
-
|
710
|
-
return nm;
|
711
|
-
}
|
712
|
-
|
713
671
|
|
714
672
|
/*
|
715
|
-
*
|
716
|
-
*
|
673
|
+
* call-seq:
|
674
|
+
* each ->
|
717
675
|
*
|
718
|
-
* Additionally, handles separately matrices containing VALUEs and matrices
|
719
|
-
* containing other types of data.
|
720
|
-
*/
|
721
|
-
static VALUE nm_dense_each(VALUE nmatrix) {
|
722
|
-
volatile VALUE nm = nmatrix; // Not sure this actually does anything.
|
723
|
-
|
724
|
-
if (NM_DTYPE(nm) == nm::RUBYOBJ) {
|
725
|
-
|
726
|
-
// matrix of Ruby objects -- yield those objects directly
|
727
|
-
return nm_dense_each_direct(nm);
|
728
|
-
|
729
|
-
} else {
|
730
|
-
|
731
|
-
// We're going to copy the matrix element into a Ruby VALUE and then operate on it. This way user can't accidentally
|
732
|
-
// modify it and cause a seg fault.
|
733
|
-
return nm_dense_each_indirect(nm);
|
734
|
-
}
|
735
|
-
}
|
736
|
-
|
737
|
-
|
738
|
-
/*
|
739
676
|
* Iterate over the matrix as you would an Enumerable (e.g., Array).
|
740
677
|
*
|
741
678
|
* Currently only works for dense.
|
@@ -751,6 +688,26 @@ static VALUE nm_each(VALUE nmatrix) {
|
|
751
688
|
}
|
752
689
|
}
|
753
690
|
|
691
|
+
/*
|
692
|
+
* Iterate over the sparse entries of any matrix. For dense and yale, this iterates over non-zero
|
693
|
+
* entries; for list, this iterates over non-default entries. Yields dim+1 values for each entry:
|
694
|
+
* i, j, ..., and the entry itself.
|
695
|
+
*/
|
696
|
+
static VALUE nm_each_stored_with_indices(VALUE nmatrix) {
|
697
|
+
volatile VALUE nm = nmatrix;
|
698
|
+
|
699
|
+
switch(NM_STYPE(nm)) {
|
700
|
+
case nm::YALE_STORE:
|
701
|
+
return nm_yale_each_stored_with_indices(nm);
|
702
|
+
case nm::DENSE_STORE:
|
703
|
+
return nm_dense_each_with_indices(nm);
|
704
|
+
case nm::LIST_STORE:
|
705
|
+
return nm_list_each_stored_with_indices(nm);
|
706
|
+
default:
|
707
|
+
rb_raise(nm_eDataTypeError, "Not a proper storage type");
|
708
|
+
}
|
709
|
+
}
|
710
|
+
|
754
711
|
|
755
712
|
|
756
713
|
/*
|
@@ -803,6 +760,9 @@ DEF_ELEMENTWISE_RUBY_ACCESSOR(LT, lt)
|
|
803
760
|
DEF_ELEMENTWISE_RUBY_ACCESSOR(GT, gt)
|
804
761
|
|
805
762
|
/*
|
763
|
+
* call-seq:
|
764
|
+
* hermitian? -> Boolean
|
765
|
+
*
|
806
766
|
* Is this matrix hermitian?
|
807
767
|
*
|
808
768
|
* Definition: http://en.wikipedia.org/wiki/Hermitian_matrix
|
@@ -814,6 +774,9 @@ static VALUE nm_hermitian(VALUE self) {
|
|
814
774
|
}
|
815
775
|
|
816
776
|
/*
|
777
|
+
* call-seq:
|
778
|
+
* complex_conjugate -> NMatrix
|
779
|
+
*
|
817
780
|
* Transform the matrix (in-place) to its complex conjugate. Only works on complex matrices.
|
818
781
|
*
|
819
782
|
* FIXME: For non-complex matrices, someone needs to implement a non-in-place complex conjugate (which doesn't use a bang).
|
@@ -860,7 +823,6 @@ static VALUE nm_complex_conjugate_bang(VALUE self) {
|
|
860
823
|
return self;
|
861
824
|
}
|
862
825
|
|
863
|
-
|
864
826
|
/*
|
865
827
|
* Helper function for creating a matrix. You have to create the storage and pass it in, but you don't
|
866
828
|
* need to worry about deleting it.
|
@@ -875,6 +837,9 @@ NMATRIX* nm_create(nm::stype_t stype, STORAGE* storage) {
|
|
875
837
|
}
|
876
838
|
|
877
839
|
/*
|
840
|
+
* call-seq:
|
841
|
+
* new -> NMatrix
|
842
|
+
*
|
878
843
|
* Create a new NMatrix.
|
879
844
|
*
|
880
845
|
* There are several ways to do this. At a minimum, dimensions and either a dtype or initial values are needed, e.g.,
|
@@ -999,7 +964,7 @@ static VALUE nm_init(int argc, VALUE* argv, VALUE nm) {
|
|
999
964
|
break;
|
1000
965
|
|
1001
966
|
case nm::YALE_STORE:
|
1002
|
-
nmatrix->storage = (STORAGE*)nm_yale_storage_create(dtype, shape, dim, init_cap);
|
967
|
+
nmatrix->storage = (STORAGE*)nm_yale_storage_create(dtype, shape, dim, init_cap, nm::UINT8);
|
1003
968
|
nm_yale_storage_init((YALE_STORAGE*)(nmatrix->storage));
|
1004
969
|
break;
|
1005
970
|
}
|
@@ -1007,11 +972,13 @@ static VALUE nm_init(int argc, VALUE* argv, VALUE nm) {
|
|
1007
972
|
return nm;
|
1008
973
|
}
|
1009
974
|
|
1010
|
-
|
1011
975
|
/*
|
976
|
+
* call-seq:
|
977
|
+
* to_hash -> Hash
|
978
|
+
*
|
1012
979
|
* Create a Ruby Hash from an NMatrix.
|
1013
980
|
*
|
1014
|
-
*
|
981
|
+
* This is an internal C function which handles list stype only.
|
1015
982
|
*/
|
1016
983
|
static VALUE nm_to_hash(VALUE self) {
|
1017
984
|
if (NM_STYPE(self) != nm::LIST_STORE) {
|
@@ -1021,7 +988,6 @@ static VALUE nm_to_hash(VALUE self) {
|
|
1021
988
|
return nm_list_storage_to_hash(NM_STORAGE_LIST(self), NM_DTYPE(self));
|
1022
989
|
}
|
1023
990
|
|
1024
|
-
|
1025
991
|
/*
|
1026
992
|
* Copy constructor for changing dtypes and stypes.
|
1027
993
|
*/
|
@@ -1046,7 +1012,6 @@ static VALUE nm_init_cast_copy(VALUE self, VALUE new_stype_symbol, VALUE new_dty
|
|
1046
1012
|
return Data_Wrap_Struct(CLASS_OF(self), mark[lhs->stype], nm_delete, lhs);
|
1047
1013
|
}
|
1048
1014
|
|
1049
|
-
|
1050
1015
|
/*
|
1051
1016
|
* Copy constructor for transposing.
|
1052
1017
|
*/
|
@@ -1066,7 +1031,6 @@ static VALUE nm_init_transposed(VALUE self) {
|
|
1066
1031
|
return Data_Wrap_Struct(CLASS_OF(self), mark[lhs->stype], nm_delete, lhs);
|
1067
1032
|
}
|
1068
1033
|
|
1069
|
-
|
1070
1034
|
/*
|
1071
1035
|
* Copy constructor for no change of dtype or stype (used for #initialize_copy hook).
|
1072
1036
|
*/
|
@@ -1089,7 +1053,6 @@ static VALUE nm_init_copy(VALUE copy, VALUE original) {
|
|
1089
1053
|
return copy;
|
1090
1054
|
}
|
1091
1055
|
|
1092
|
-
|
1093
1056
|
/*
|
1094
1057
|
* Get major, minor, and release components of NMatrix::VERSION. Store in function parameters.
|
1095
1058
|
*/
|
@@ -1339,7 +1302,7 @@ static VALUE nm_read(int argc, VALUE* argv, VALUE self) {
|
|
1339
1302
|
f.read(reinterpret_cast<char*>(&ndnz), sizeof(uint32_t));
|
1340
1303
|
f.read(reinterpret_cast<char*>(&length), sizeof(uint32_t));
|
1341
1304
|
|
1342
|
-
s = nm_yale_storage_create(dtype, shape, dim, length); // set length as init capacity
|
1305
|
+
s = nm_yale_storage_create(dtype, shape, dim, length, itype); // set length as init capacity
|
1343
1306
|
|
1344
1307
|
read_padded_yale_elements(f, reinterpret_cast<YALE_STORAGE*>(s), length, symm, dtype, itype);
|
1345
1308
|
} else {
|
@@ -1402,9 +1365,10 @@ static VALUE nm_is_ref(VALUE self) {
|
|
1402
1365
|
return Qfalse;
|
1403
1366
|
}
|
1404
1367
|
|
1405
|
-
|
1406
|
-
|
1407
1368
|
/*
|
1369
|
+
* call-seq:
|
1370
|
+
* slice -> ...
|
1371
|
+
*
|
1408
1372
|
* Access the contents of an NMatrix at given coordinates, using copying.
|
1409
1373
|
*
|
1410
1374
|
* n.slice(3,3) # => 5.0
|
@@ -1422,6 +1386,9 @@ static VALUE nm_mget(int argc, VALUE* argv, VALUE self) {
|
|
1422
1386
|
}
|
1423
1387
|
|
1424
1388
|
/*
|
1389
|
+
* call-seq:
|
1390
|
+
* matrix[indexes] -> ...
|
1391
|
+
*
|
1425
1392
|
* Access the contents of an NMatrix at given coordinates by reference.
|
1426
1393
|
*
|
1427
1394
|
* n[3,3] # => 5.0
|
@@ -1528,9 +1495,10 @@ static VALUE nm_multiply(VALUE left_v, VALUE right_v) {
|
|
1528
1495
|
return Qnil;
|
1529
1496
|
}
|
1530
1497
|
|
1531
|
-
|
1532
|
-
|
1533
1498
|
/*
|
1499
|
+
* call-seq:
|
1500
|
+
* matrix.factorize_lu -> ...
|
1501
|
+
*
|
1534
1502
|
* LU factorization of a matrix.
|
1535
1503
|
*
|
1536
1504
|
* FIXME: For some reason, getrf seems to require that the matrix be transposed first -- and then you have to transpose the
|
@@ -1573,6 +1541,9 @@ static VALUE nm_factorize_lu(VALUE self) {
|
|
1573
1541
|
}
|
1574
1542
|
|
1575
1543
|
/*
|
1544
|
+
* call-seq:
|
1545
|
+
* dim -> Integer
|
1546
|
+
*
|
1576
1547
|
* Get the number of dimensions of a matrix.
|
1577
1548
|
*
|
1578
1549
|
* In other words, if you set your matrix to be 3x4, the dim is 2. If the
|
@@ -1586,6 +1557,9 @@ static VALUE nm_dim(VALUE self) {
|
|
1586
1557
|
}
|
1587
1558
|
|
1588
1559
|
/*
|
1560
|
+
* call-seq:
|
1561
|
+
* shape -> Array
|
1562
|
+
*
|
1589
1563
|
* Get the shape (dimensions) of a matrix.
|
1590
1564
|
*/
|
1591
1565
|
static VALUE nm_shape(VALUE self) {
|
@@ -1601,6 +1575,9 @@ static VALUE nm_shape(VALUE self) {
|
|
1601
1575
|
}
|
1602
1576
|
|
1603
1577
|
/*
|
1578
|
+
* call-seq:
|
1579
|
+
* stype -> Symbol
|
1580
|
+
*
|
1604
1581
|
* Get the storage type (stype) of a matrix, e.g., :yale, :dense, or :list.
|
1605
1582
|
*/
|
1606
1583
|
static VALUE nm_stype(VALUE self) {
|
@@ -1609,6 +1586,9 @@ static VALUE nm_stype(VALUE self) {
|
|
1609
1586
|
}
|
1610
1587
|
|
1611
1588
|
/*
|
1589
|
+
* call-seq:
|
1590
|
+
* symmetric? -> Boolean
|
1591
|
+
*
|
1612
1592
|
* Is this matrix symmetric?
|
1613
1593
|
*/
|
1614
1594
|
static VALUE nm_symmetric(VALUE self) {
|
@@ -1665,7 +1645,6 @@ static VALUE elementwise_op(nm::ewop_t op, VALUE left_val, VALUE right_val) {
|
|
1665
1645
|
nm_dense_storage_ew_op,
|
1666
1646
|
nm_list_storage_ew_op,
|
1667
1647
|
nm_yale_storage_ew_op
|
1668
|
-
// NULL
|
1669
1648
|
};
|
1670
1649
|
|
1671
1650
|
NMATRIX *result = ALLOC(NMATRIX), *left;
|
@@ -1708,10 +1687,15 @@ static VALUE elementwise_op(nm::ewop_t op, VALUE left_val, VALUE right_val) {
|
|
1708
1687
|
}
|
1709
1688
|
}
|
1710
1689
|
|
1711
|
-
|
1712
|
-
}
|
1690
|
+
VALUE result_val = Data_Wrap_Struct(CLASS_OF(left_val), mark[result->stype], nm_delete, result);
|
1713
1691
|
|
1692
|
+
// If we're dealing with a vector, need to make sure the @orientation matches.
|
1693
|
+
// FIXME: Eventually we probably need to make this an internal property of NVector.
|
1694
|
+
if (CLASS_OF(left_val) == cNVector)
|
1695
|
+
rb_iv_set(result_val, "@orientation", rb_iv_get(left_val, "@orientation"));
|
1714
1696
|
|
1697
|
+
return result_val;
|
1698
|
+
}
|
1715
1699
|
|
1716
1700
|
/*
|
1717
1701
|
* Check to determine whether matrix is a reference to another matrix.
|
@@ -1751,7 +1735,6 @@ static VALUE is_symmetric(VALUE self, bool hermitian) {
|
|
1751
1735
|
return Qfalse;
|
1752
1736
|
}
|
1753
1737
|
|
1754
|
-
|
1755
1738
|
///////////////////////
|
1756
1739
|
// Utility Functions //
|
1757
1740
|
///////////////////////
|
@@ -1996,12 +1979,10 @@ static nm::stype_t interpret_stype(VALUE arg) {
|
|
1996
1979
|
}
|
1997
1980
|
}
|
1998
1981
|
|
1999
|
-
|
2000
1982
|
//////////////////
|
2001
1983
|
// Math Helpers //
|
2002
1984
|
//////////////////
|
2003
1985
|
|
2004
|
-
|
2005
1986
|
STORAGE* matrix_storage_cast_alloc(NMATRIX* matrix, nm::dtype_t new_dtype) {
|
2006
1987
|
if (matrix->storage->dtype == new_dtype && !is_ref(matrix))
|
2007
1988
|
return matrix->storage;
|
@@ -2010,7 +1991,6 @@ STORAGE* matrix_storage_cast_alloc(NMATRIX* matrix, nm::dtype_t new_dtype) {
|
|
2010
1991
|
return cast_copy_storage[matrix->stype][matrix->stype](matrix->storage, new_dtype);
|
2011
1992
|
}
|
2012
1993
|
|
2013
|
-
|
2014
1994
|
STORAGE_PAIR binary_storage_cast_alloc(NMATRIX* left_matrix, NMATRIX* right_matrix) {
|
2015
1995
|
STORAGE_PAIR casted;
|
2016
1996
|
nm::dtype_t new_dtype = Upcast[left_matrix->storage->dtype][right_matrix->storage->dtype];
|
@@ -2021,7 +2001,6 @@ STORAGE_PAIR binary_storage_cast_alloc(NMATRIX* left_matrix, NMATRIX* right_matr
|
|
2021
2001
|
return casted;
|
2022
2002
|
}
|
2023
2003
|
|
2024
|
-
|
2025
2004
|
static VALUE matrix_multiply_scalar(NMATRIX* left, VALUE scalar) {
|
2026
2005
|
rb_raise(rb_eNotImpError, "matrix-scalar multiplication not implemented yet");
|
2027
2006
|
return Qnil;
|
@@ -2070,10 +2049,6 @@ static VALUE matrix_multiply(NMATRIX* left, NMATRIX* right) {
|
|
2070
2049
|
return Qnil; // Only if we try to multiply list matrices should we return Qnil.
|
2071
2050
|
}
|
2072
2051
|
|
2073
|
-
|
2074
|
-
|
2075
|
-
|
2076
|
-
|
2077
2052
|
/*
|
2078
2053
|
* Calculate the exact determinant of a dense matrix.
|
2079
2054
|
*
|
@@ -2093,14 +2068,10 @@ static VALUE nm_det_exact(VALUE self) {
|
|
2093
2068
|
return rubyobj_from_cval(result, NM_DTYPE(self)).rval;
|
2094
2069
|
}
|
2095
2070
|
|
2096
|
-
|
2097
|
-
|
2098
|
-
|
2099
2071
|
/////////////////
|
2100
2072
|
// Exposed API //
|
2101
2073
|
/////////////////
|
2102
2074
|
|
2103
|
-
|
2104
2075
|
/*
|
2105
2076
|
* Create a dense matrix. Used by the NMatrix GSL fork. Unlike nm_create, this one copies all of the
|
2106
2077
|
* arrays and such passed in -- so you don't have to allocate and pass a new shape object for every
|
@@ -2142,7 +2113,6 @@ VALUE rb_nmatrix_dense_create(nm::dtype_t dtype, size_t* shape, size_t dim, void
|
|
2142
2113
|
return Data_Wrap_Struct(klass, nm_dense_storage_mark, nm_dense_storage_delete, nm);
|
2143
2114
|
}
|
2144
2115
|
|
2145
|
-
|
2146
2116
|
/*
|
2147
2117
|
* Create a dense vector. Used by the NMatrix GSL fork.
|
2148
2118
|
*
|
@@ -2158,4 +2128,3 @@ VALUE rb_nvector_dense_create(nm::dtype_t dtype, void* elements, size_t length)
|
|
2158
2128
|
}
|
2159
2129
|
|
2160
2130
|
} // end of extern "C"
|
2161
|
-
|