nmatrix 0.1.0.rc2 → 0.1.0.rc3
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 +4 -4
- data/.travis.yml +1 -0
- data/History.txt +16 -0
- data/README.rdoc +1 -1
- data/ext/nmatrix/ruby_nmatrix.c +16 -6
- data/ext/nmatrix/storage/dense/dense.cpp +2 -7
- data/lib/nmatrix/lapack.rb +65 -4
- data/lib/nmatrix/version.rb +1 -1
- data/spec/00_nmatrix_spec.rb +42 -6
- data/spec/02_slice_spec.rb +6 -0
- data/spec/shortcuts_spec.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9bccc178bd2c4a0ee318f3a0808e7f3c52cfbc3f
|
4
|
+
data.tar.gz: eec9ec0890b8ab958c123452f98064883de0ea33
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ab789cf265f5461e75e0425ce126c45e52ff627b69bfa0a5a94018260254708ec11c9e0e67a9f94e7dab0696fe1171c56d8043304b59848bfede52761e33924f
|
7
|
+
data.tar.gz: b8f8cfe0c81c7ce46306afcd9b5e469e84856aae990b6e42e52ca299234fe03801bd7f0c4ba585f14786909f1dbe88b10e5b12b3ef16c37935b8efa06e58b7ed
|
data/.travis.yml
CHANGED
data/History.txt
CHANGED
@@ -583,3 +583,19 @@
|
|
583
583
|
* NMatrix::random now raises an exception when rational matrices
|
584
584
|
are requested
|
585
585
|
|
586
|
+
=== 0.1.0.rc3 / 2014-03-27
|
587
|
+
|
588
|
+
* No major enhancements.
|
589
|
+
|
590
|
+
* 2 minor enhancements:
|
591
|
+
|
592
|
+
* Exposed NMatrix::LAPACK::geev for LAPACK's xGEEV
|
593
|
+
|
594
|
+
* Added out-of-place complex conjugate for dense and yale storage
|
595
|
+
(by @rve)
|
596
|
+
|
597
|
+
* 1 bug fixes:
|
598
|
+
|
599
|
+
* Fixed critical bug with transposing a matrix reference slice (by
|
600
|
+
@rajatkapoor)
|
601
|
+
|
data/README.rdoc
CHANGED
@@ -38,7 +38,7 @@ If you want to obtain the latest (development) code, you should generally do:
|
|
38
38
|
bundle install
|
39
39
|
bundle exec rake compile
|
40
40
|
bundle exec rake repackage
|
41
|
-
gem install pkg/nmatrix-0.1.0.
|
41
|
+
gem install pkg/nmatrix-0.1.0.rc3.gem
|
42
42
|
|
43
43
|
Detailed instructions are available for {Mac}[https://github.com/SciRuby/nmatrix/wiki/Installation#mac-os-x] and {Linux}[https://github.com/SciRuby/nmatrix/wiki/Installation#linux].
|
44
44
|
We are currently working on Mavericks (Mac OS X) installation instructions, but in general, you'll need Homebrew and should
|
data/ext/nmatrix/ruby_nmatrix.c
CHANGED
@@ -154,6 +154,7 @@ static VALUE nm_multiply(VALUE left_v, VALUE right_v);
|
|
154
154
|
static VALUE nm_det_exact(VALUE self);
|
155
155
|
static VALUE nm_inverse_exact(VALUE self, VALUE inverse);
|
156
156
|
static VALUE nm_complex_conjugate_bang(VALUE self);
|
157
|
+
static VALUE nm_complex_conjugate(VALUE self);
|
157
158
|
static VALUE nm_reshape_bang(VALUE self, VALUE arg);
|
158
159
|
|
159
160
|
static nm::dtype_t interpret_dtype(int argc, VALUE* argv, nm::stype_t stype);
|
@@ -260,6 +261,7 @@ void Init_nmatrix() {
|
|
260
261
|
rb_define_method(cNMatrix, "det_exact", (METHOD)nm_det_exact, 0);
|
261
262
|
rb_define_protected_method(cNMatrix, "__inverse_exact__", (METHOD)nm_inverse_exact, 1);
|
262
263
|
rb_define_method(cNMatrix, "complex_conjugate!", (METHOD)nm_complex_conjugate_bang, 0);
|
264
|
+
rb_define_method(cNMatrix, "complex_conjugate", (METHOD)nm_complex_conjugate, 0);
|
263
265
|
rb_define_protected_method(cNMatrix, "reshape_bang", (METHOD)nm_reshape_bang, 1);
|
264
266
|
|
265
267
|
rb_define_protected_method(cNMatrix, "__dense_each__", (METHOD)nm_dense_each, 0);
|
@@ -975,11 +977,10 @@ static VALUE nm_hermitian(VALUE self) {
|
|
975
977
|
|
976
978
|
/*
|
977
979
|
* call-seq:
|
978
|
-
*
|
980
|
+
* complex_conjugate_bang -> NMatrix
|
979
981
|
*
|
980
982
|
* Transform the matrix (in-place) to its complex conjugate. Only works on complex matrices.
|
981
983
|
*
|
982
|
-
* FIXME: For non-complex matrices, someone needs to implement a non-in-place complex conjugate (which doesn't use a bang).
|
983
984
|
* Bang should imply that no copy is being made, even temporarily.
|
984
985
|
*/
|
985
986
|
static VALUE nm_complex_conjugate_bang(VALUE self) {
|
@@ -1017,13 +1018,22 @@ static VALUE nm_complex_conjugate_bang(VALUE self) {
|
|
1017
1018
|
reinterpret_cast<nm::Complex128*>(elem)[p].i = -reinterpret_cast<nm::Complex128*>(elem)[p].i;
|
1018
1019
|
}
|
1019
1020
|
|
1020
|
-
}
|
1021
|
-
rb_raise(nm_eDataTypeError, "can only calculate in-place complex conjugate on matrices of type :complex64 or :complex128");
|
1022
|
-
}
|
1023
|
-
|
1021
|
+
}
|
1024
1022
|
return self;
|
1025
1023
|
}
|
1026
1024
|
|
1025
|
+
/*
|
1026
|
+
* call-seq:
|
1027
|
+
* complex_conjugate -> NMatrix
|
1028
|
+
*
|
1029
|
+
* Transform the matrix (non-in-place) to its complex conjugate. Only works on complex matrices.
|
1030
|
+
*
|
1031
|
+
*/
|
1032
|
+
static VALUE nm_complex_conjugate(VALUE self) {
|
1033
|
+
VALUE copy;
|
1034
|
+
return nm_complex_conjugate_bang(nm_init_copy(copy,self));
|
1035
|
+
}
|
1036
|
+
|
1027
1037
|
|
1028
1038
|
/*
|
1029
1039
|
* call-seq:
|
@@ -742,7 +742,6 @@ void nm_dense_storage_coords(const DENSE_STORAGE* s, const size_t slice_pos, siz
|
|
742
742
|
coords_out[i] = (temp_pos - temp_pos % s->stride[i])/s->stride[i] - s->offset[i];
|
743
743
|
temp_pos = temp_pos % s->stride[i];
|
744
744
|
}
|
745
|
-
|
746
745
|
}
|
747
746
|
|
748
747
|
/*
|
@@ -834,16 +833,13 @@ STORAGE* nm_dense_storage_copy_transposed(const STORAGE* rhs_base) {
|
|
834
833
|
DENSE_STORAGE* rhs = (DENSE_STORAGE*)rhs_base;
|
835
834
|
|
836
835
|
nm_dense_storage_register(rhs);
|
837
|
-
|
838
836
|
size_t *shape = NM_ALLOC_N(size_t, rhs->dim);
|
839
837
|
|
840
|
-
// swap shape
|
838
|
+
// swap shape
|
841
839
|
shape[0] = rhs->shape[1];
|
842
840
|
shape[1] = rhs->shape[0];
|
843
841
|
|
844
842
|
DENSE_STORAGE *lhs = nm_dense_storage_create(rhs->dtype, shape, rhs->dim, NULL, 0);
|
845
|
-
lhs->offset[0] = rhs->offset[1];
|
846
|
-
lhs->offset[1] = rhs->offset[0];
|
847
843
|
|
848
844
|
nm_dense_storage_register(lhs);
|
849
845
|
|
@@ -916,8 +912,7 @@ void ref_slice_copy_transposed(const DENSE_STORAGE* rhs, DENSE_STORAGE* lhs) {
|
|
916
912
|
|
917
913
|
LDType* lhs_els = reinterpret_cast<LDType*>(lhs->elements);
|
918
914
|
RDType* rhs_els = reinterpret_cast<RDType*>(rhs->elements);
|
919
|
-
|
920
|
-
size_t count = nm_storage_count_max_elements(lhs);
|
915
|
+
size_t count = nm_storage_count_max_elements(lhs);;
|
921
916
|
size_t* temp_coords = NM_ALLOCA_N(size_t, lhs->dim);
|
922
917
|
size_t coord_swap_temp;
|
923
918
|
|
data/lib/nmatrix/lapack.rb
CHANGED
@@ -140,10 +140,11 @@ class NMatrix
|
|
140
140
|
]
|
141
141
|
end
|
142
142
|
|
143
|
+
|
143
144
|
#
|
144
145
|
# call-seq:
|
145
|
-
# gesvd -> [u, sigma, v_transpose]
|
146
|
-
# gesvd -> [u, sigma, v_conjugate_transpose] # complex
|
146
|
+
# gesvd(matrix) -> [u, sigma, v_transpose]
|
147
|
+
# gesvd(matrix) -> [u, sigma, v_conjugate_transpose] # complex
|
147
148
|
#
|
148
149
|
# Compute the singular value decomposition of a matrix using LAPACK's GESVD function.
|
149
150
|
#
|
@@ -158,8 +159,8 @@ class NMatrix
|
|
158
159
|
|
159
160
|
#
|
160
161
|
# call-seq:
|
161
|
-
# gesdd -> [u, sigma, v_transpose]
|
162
|
-
# gesdd -> [u, sigma, v_conjugate_transpose] # complex
|
162
|
+
# gesdd(matrix) -> [u, sigma, v_transpose]
|
163
|
+
# gesdd(matrix) -> [u, sigma, v_conjugate_transpose] # complex
|
163
164
|
#
|
164
165
|
# Compute the singular value decomposition of a matrix using LAPACK's GESDD function. This uses a divide-and-conquer
|
165
166
|
# strategy. See also #gesvd.
|
@@ -173,6 +174,66 @@ class NMatrix
|
|
173
174
|
result
|
174
175
|
end
|
175
176
|
|
177
|
+
def alloc_evd_result(matrix)
|
178
|
+
[
|
179
|
+
NMatrix.new(matrix.shape[0], dtype: matrix.dtype),
|
180
|
+
NMatrix.new(matrix.shape[0], dtype: matrix.dtype),
|
181
|
+
NMatrix.new([matrix.shape[0],1], dtype: matrix.dtype),
|
182
|
+
NMatrix.new([matrix.shape[0],1], dtype: matrix.dtype),
|
183
|
+
]
|
184
|
+
end
|
185
|
+
|
186
|
+
|
187
|
+
#
|
188
|
+
# call-seq:
|
189
|
+
# geev(matrix) -> [eigenvalues, left_eigenvectors, right_eigenvectors]
|
190
|
+
# geev(matrix, :left) -> [eigenvalues, left_eigenvectors]
|
191
|
+
# geev(matrix, :right) -> [eigenvalues, right_eigenvectors]
|
192
|
+
#
|
193
|
+
# Perform eigenvalue decomposition on a matrix using LAPACK's xGEEV function.
|
194
|
+
#
|
195
|
+
def geev(matrix, which=:both)
|
196
|
+
result = alloc_evd_result(matrix)
|
197
|
+
jobvl = (which == :both || which == :left) ? :left : false
|
198
|
+
jobvr = (which == :both || which == :right) ? :right : false
|
199
|
+
|
200
|
+
# Copy the matrix so it doesn't get overwritten.
|
201
|
+
temporary_matrix = matrix.clone
|
202
|
+
|
203
|
+
# Outputs
|
204
|
+
real_eigenvalues = NMatrix.new([matrix.shape[0], 1], dtype: matrix.dtype)
|
205
|
+
imag_eigenvalues = NMatrix.new([matrix.shape[0], 1], dtype: matrix.dtype)
|
206
|
+
|
207
|
+
left_output = jobvl == :left ? matrix.clone_structure : NMatrix.new(1, dtype: matrix.dtype)
|
208
|
+
right_output = jobvr == :right ? matrix.clone_structure : NMatrix.new(1, dtype: matrix.dtype)
|
209
|
+
|
210
|
+
NMatrix::LAPACK::lapack_geev(jobvl, # compute left eigenvectors of A?
|
211
|
+
jobvr, # compute right eigenvectors of A? (left eigenvectors of A**T)
|
212
|
+
matrix.shape[0], # order of the matrix
|
213
|
+
temporary_matrix,# input matrix (used as work)
|
214
|
+
matrix.shape[0], # leading dimension of matrix
|
215
|
+
real_eigenvalues,# real part of computed eigenvalues
|
216
|
+
imag_eigenvalues,# imag part of computed eigenvalues
|
217
|
+
left_output, # left eigenvectors, if applicable
|
218
|
+
left_output.shape[0], # leading dimension of left_output
|
219
|
+
right_output, # right eigenvectors, if applicable
|
220
|
+
right_output.shape[0], # leading dimension of right_output
|
221
|
+
2*matrix.shape[0])
|
222
|
+
|
223
|
+
# Put the real and imaginary parts together
|
224
|
+
eigenvalues = real_eigenvalues.to_a.flatten.map.with_index do |real,i|
|
225
|
+
imag_eigenvalues[i] != 0 ? Complex(real, imag_eigenvalues[i]) : real
|
226
|
+
end
|
227
|
+
|
228
|
+
if which == :both
|
229
|
+
return [eigenvalues, left_output.transpose, right_output.transpose]
|
230
|
+
elsif which == :left
|
231
|
+
return [eigenvalues, left_output.transpose]
|
232
|
+
else
|
233
|
+
return [eigenvalues, right_output]
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
176
237
|
end
|
177
238
|
end
|
178
239
|
end
|
data/lib/nmatrix/version.rb
CHANGED
data/spec/00_nmatrix_spec.rb
CHANGED
@@ -291,12 +291,6 @@ describe NMatrix do
|
|
291
291
|
expect(lambda { NMatrix.new(3,dtype: :int8)[1,1] }).to_not raise_error
|
292
292
|
end
|
293
293
|
|
294
|
-
it "calculates the complex conjugate in-place" do
|
295
|
-
n = NMatrix.new(:dense, 3, [1,2,3,4,5,6,7,8,9], :complex128)
|
296
|
-
n.complex_conjugate!
|
297
|
-
# FIXME: Actually test that values are correct.
|
298
|
-
end
|
299
|
-
|
300
294
|
it "converts from list to yale properly" do
|
301
295
|
m = NMatrix.new(3, 0, stype: :list)
|
302
296
|
m[0,2] = 333
|
@@ -519,4 +513,46 @@ describe 'NMatrix' do
|
|
519
513
|
expect(n[0,0..-2]).to eq(NMatrix.new([1,4],[1,2,3,4]))
|
520
514
|
end
|
521
515
|
end
|
516
|
+
|
517
|
+
context "#complex_conjugate!" do
|
518
|
+
[:dense, :yale, :list].each do |stype|
|
519
|
+
context(stype) do
|
520
|
+
it "should work in-place for complex dtypes" do
|
521
|
+
pending("not yet implemented for list stype") if stype == :list
|
522
|
+
n = NMatrix.new([2,3], [Complex(2,3)], stype: stype, dtype: :complex128)
|
523
|
+
n.complex_conjugate!
|
524
|
+
expect(n).to eq(NMatrix.new([2,3], [Complex(2,-3)], stype: stype, dtype: :complex128))
|
525
|
+
end
|
526
|
+
|
527
|
+
[:object, :int64].each do |dtype|
|
528
|
+
it "should work in-place for non-complex dtypes" do
|
529
|
+
pending("not yet implemented for list stype") if stype == :list
|
530
|
+
n = NMatrix.new([2,3], 1, stype: stype, dtype: dtype)
|
531
|
+
n.complex_conjugate!
|
532
|
+
expect(n).to eq(NMatrix.new([2,3], [1], stype: stype, dtype: dtype))
|
533
|
+
end
|
534
|
+
end
|
535
|
+
end
|
536
|
+
end
|
537
|
+
end
|
538
|
+
|
539
|
+
context "#complex_conjugate" do
|
540
|
+
[:dense, :yale, :list].each do |stype|
|
541
|
+
context(stype) do
|
542
|
+
it "should work out-of-place for complex dtypes" do
|
543
|
+
pending("not yet implemented for list stype") if stype == :list
|
544
|
+
n = NMatrix.new([2,3], [Complex(2,3)], stype: stype, dtype: :complex128)
|
545
|
+
expect(n.complex_conjugate).to eq(NMatrix.new([2,3], [Complex(2,-3)], stype: stype, dtype: :complex128))
|
546
|
+
end
|
547
|
+
|
548
|
+
[:object, :int64].each do |dtype|
|
549
|
+
it "should work out-of-place for non-complex dtypes" do
|
550
|
+
pending("not yet implemented for list stype") if stype == :list
|
551
|
+
n = NMatrix.new([2,3], 1, stype: stype, dtype: dtype)
|
552
|
+
expect(n.complex_conjugate).to eq(NMatrix.new([2,3], [1], stype: stype, dtype: dtype))
|
553
|
+
end
|
554
|
+
end
|
555
|
+
end
|
556
|
+
end
|
557
|
+
end
|
522
558
|
end
|
data/spec/02_slice_spec.rb
CHANGED
@@ -314,6 +314,12 @@ describe "Slice operation" do
|
|
314
314
|
|
315
315
|
it "correctly transposes slices" do
|
316
316
|
expect(@m[0...3,0].transpose).to eq NMatrix[[0, 3, 6]]
|
317
|
+
expect(@m[0...3,1].transpose).to eq NMatrix[[1, 4, 7]]
|
318
|
+
expect(@m[0...3,2].transpose).to eq NMatrix[[2, 5, 8]]
|
319
|
+
expect(@m[0,0...3].transpose).to eq NMatrix[[0], [1], [2]]
|
320
|
+
expect(@m[1,0...3].transpose).to eq NMatrix[[3], [4], [5]]
|
321
|
+
expect(@m[2,0...3].transpose).to eq NMatrix[[6], [7], [8]]
|
322
|
+
expect(@m[1..2,1..2].transpose).to eq NMatrix[[4, 7], [5, 8]]
|
317
323
|
end
|
318
324
|
|
319
325
|
it "adds slices" do
|
data/spec/shortcuts_spec.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nmatrix
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.0.
|
4
|
+
version: 0.1.0.rc3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Woods
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2014-03-
|
13
|
+
date: 2014-03-27 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rdoc
|