nmatrix 0.0.3 → 0.0.4
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.
- 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
|
-
|