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 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