nmatrix 0.1.0.rc2 → 0.1.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4052431a5f81ea9304f96fe293f6f22a47dacf3d
4
- data.tar.gz: 777b0fd050d7f0726ea97f337d5f4ce3cf850f8b
3
+ metadata.gz: 9bccc178bd2c4a0ee318f3a0808e7f3c52cfbc3f
4
+ data.tar.gz: eec9ec0890b8ab958c123452f98064883de0ea33
5
5
  SHA512:
6
- metadata.gz: daabd9cebbe93674079728f254cf5429bb1d0cadfb2ddbb56061da9181508852bd919844baf7e63615237fe6f2fc864dd27515b97153ea7704185001417a2f27
7
- data.tar.gz: b36dcd576afedd2ddc1fa57af569823fb72f98d0e11cd0e1d7ea751553e1b2de39fe32a197d0a731a308ec28a6e96aedcc0687b73853f88ab0002c6145e53e7b
6
+ metadata.gz: ab789cf265f5461e75e0425ce126c45e52ff627b69bfa0a5a94018260254708ec11c9e0e67a9f94e7dab0696fe1171c56d8043304b59848bfede52761e33924f
7
+ data.tar.gz: b8f8cfe0c81c7ce46306afcd9b5e469e84856aae990b6e42e52ca299234fe03801bd7f0c4ba585f14786909f1dbe88b10e5b12b3ef16c37935b8efa06e58b7ed
@@ -7,6 +7,7 @@ rvm:
7
7
  - "1.9.3"
8
8
  - "2.0.0"
9
9
  - "2.1.0"
10
+ - "2.1.1"
10
11
  before_install:
11
12
  - sudo apt-get update -qq
12
13
  - sudo apt-get install -qq libatlas-base-dev
@@ -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
+
@@ -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.rc2.gem
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
@@ -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
- * complex_conjugate -> NMatrix
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
- } else {
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 and offset
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
 
@@ -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
@@ -31,7 +31,7 @@ class NMatrix
31
31
  MAJOR = 0
32
32
  MINOR = 1
33
33
  TINY = 0
34
- PRE = "rc2"
34
+ PRE = "rc3"
35
35
 
36
36
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
37
37
  end
@@ -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
@@ -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
@@ -89,7 +89,7 @@ describe NMatrix do
89
89
  it "correctly accepts :scale parameter" do
90
90
  m = NMatrix.random([2,2], dtype: :byte, scale: 255)
91
91
  m.each do |v|
92
- expect(v).to be > 0
92
+ expect(v).to be >= 0
93
93
  expect(v).to be < 255
94
94
  end
95
95
  end
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.rc2
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-12 00:00:00.000000000 Z
13
+ date: 2014-03-27 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rdoc