nmatrix 0.1.0.rc5 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +0 -1
  3. data/Gemfile +0 -2
  4. data/History.txt +39 -4
  5. data/LICENSE.txt +3 -1
  6. data/Manifest.txt +2 -0
  7. data/README.rdoc +6 -14
  8. data/Rakefile +4 -1
  9. data/ext/nmatrix/data/data.cpp +1 -1
  10. data/ext/nmatrix/data/data.h +2 -1
  11. data/ext/nmatrix/data/rational.h +230 -226
  12. data/ext/nmatrix/extconf.rb +7 -4
  13. data/ext/nmatrix/math.cpp +259 -172
  14. data/ext/nmatrix/math/getri.h +2 -2
  15. data/ext/nmatrix/math/math.h +1 -1
  16. data/ext/nmatrix/ruby_constants.cpp +0 -1
  17. data/ext/nmatrix/ruby_nmatrix.c +55 -32
  18. data/ext/nmatrix/storage/dense/dense.cpp +1 -0
  19. data/ext/nmatrix/storage/yale/yale.cpp +12 -14
  20. data/ext/nmatrix/ttable_helper.rb +0 -1
  21. data/lib/nmatrix.rb +5 -0
  22. data/lib/nmatrix/homogeneous.rb +98 -0
  23. data/lib/nmatrix/io/fortran_format.rb +135 -0
  24. data/lib/nmatrix/io/harwell_boeing.rb +220 -0
  25. data/lib/nmatrix/io/market.rb +18 -8
  26. data/lib/nmatrix/io/mat5_reader.rb +16 -111
  27. data/lib/nmatrix/io/mat_reader.rb +3 -5
  28. data/lib/nmatrix/io/point_cloud.rb +27 -28
  29. data/lib/nmatrix/lapack.rb +3 -1
  30. data/lib/nmatrix/math.rb +112 -43
  31. data/lib/nmatrix/monkeys.rb +67 -11
  32. data/lib/nmatrix/nmatrix.rb +56 -33
  33. data/lib/nmatrix/rspec.rb +2 -2
  34. data/lib/nmatrix/shortcuts.rb +42 -25
  35. data/lib/nmatrix/version.rb +4 -4
  36. data/nmatrix.gemspec +4 -3
  37. data/spec/03_nmatrix_monkeys_spec.rb +72 -0
  38. data/spec/blas_spec.rb +4 -0
  39. data/spec/homogeneous_spec.rb +12 -4
  40. data/spec/io/fortran_format_spec.rb +88 -0
  41. data/spec/io/harwell_boeing_spec.rb +98 -0
  42. data/spec/io/test.rua +9 -0
  43. data/spec/math_spec.rb +51 -9
  44. metadata +38 -9
@@ -30,31 +30,39 @@
30
30
 
31
31
  require_relative './lapack.rb'
32
32
  require_relative './yale_functions.rb'
33
+ require_relative './monkeys'
33
34
 
35
+ # NMatrix is a matrix class that supports both multidimensional arrays
36
+ # (`:dense` stype) and sparse storage (`:list` or `:yale` stypes) and 13 data
37
+ # types, including complex and rational numbers, various integer and
38
+ # floating-point sizes and ruby objects.
34
39
  class NMatrix
35
-
36
- # Read and write extensions for NMatrix. These are only loaded when needed.
37
- #
40
+ # Read and write extensions for NMatrix.
38
41
  module IO
42
+ extend AutoloadPatch
43
+
44
+ # Reader (and eventually writer) of Matlab .mat files.
45
+ #
46
+ # The .mat file format is documented in the following link:
47
+ # * http://www.mathworks.com/help/pdf_doc/matlab/matfile_format.pdf
39
48
  module Matlab
49
+ extend AutoloadPatch
50
+
40
51
  class << self
41
- def load_mat file_path
52
+ # call-seq:
53
+ # load(mat_file_path) -> NMatrix
54
+ # load_mat(mat_file_path) -> NMatrix
55
+ #
56
+ # Load a .mat file and return a NMatrix corresponding to it.
57
+ def load_mat(file_path)
42
58
  NMatrix::IO::Matlab::Mat5Reader.new(File.open(file_path, "rb+")).to_ruby
43
59
  end
44
60
  alias :load :load_mat
45
61
  end
46
-
47
- # FIXME: Remove autoloads
48
- autoload :MatReader, 'nmatrix/io/mat_reader'
49
- autoload :Mat5Reader, 'nmatrix/io/mat5_reader'
50
62
  end
51
-
52
- autoload :Market, 'nmatrix/io/market.rb'
53
- autoload :PointCloud, 'nmatrix/io/point_cloud.rb'
54
63
  end
55
64
 
56
65
  class << self
57
- #
58
66
  # call-seq:
59
67
  # load_matlab_file(path) -> Mat5Reader
60
68
  #
@@ -62,12 +70,10 @@ class NMatrix
62
70
  # - +file_path+ -> The path to a version 5 .mat file.
63
71
  # * *Returns* :
64
72
  # - A Mat5Reader object.
65
- #
66
73
  def load_matlab_file(file_path)
67
74
  NMatrix::IO::Mat5Reader.new(File.open(file_path, 'rb')).to_ruby
68
75
  end
69
76
 
70
- #
71
77
  # call-seq:
72
78
  # load_pcd_file(path) -> PointCloudReader::MetaReader
73
79
  #
@@ -75,12 +81,10 @@ class NMatrix
75
81
  # - +file_path+ -> The path to a PCL PCD file.
76
82
  # * *Returns* :
77
83
  # - A PointCloudReader::MetaReader object with the matrix stored in its +matrix+ property
78
- #
79
84
  def load_pcd_file(file_path)
80
85
  NMatrix::IO::PointCloudReader::MetaReader.new(file_path)
81
86
  end
82
87
 
83
- #
84
88
  # Calculate the size of an NMatrix of a given shape.
85
89
  def size(shape)
86
90
  shape = [shape,shape] unless shape.is_a?(Array)
@@ -128,8 +132,6 @@ class NMatrix
128
132
  end
129
133
  end
130
134
  end
131
- #alias :pp :pretty_print
132
-
133
135
 
134
136
  #
135
137
  # call-seq:
@@ -238,7 +240,6 @@ class NMatrix
238
240
  end
239
241
 
240
242
 
241
- ##
242
243
  # call-seq:
243
244
  # integer_dtype?() -> Boolean
244
245
  #
@@ -248,6 +249,26 @@ class NMatrix
248
249
  [:byte, :int8, :int16, :int32, :int64].include?(self.dtype)
249
250
  end
250
251
 
252
+ ##
253
+ # call-seq:
254
+ # complex_dtype?() -> Boolean
255
+ #
256
+ # Checks if dtype is a complex type
257
+ #
258
+ def complex_dtype?
259
+ [:complex64, :complex128].include?(self.dtype)
260
+ end
261
+
262
+ ##
263
+ # call-seq:
264
+ # complex_dtype?() -> Boolean
265
+ #
266
+ # Checks if dtype is a rational type
267
+ #
268
+ def rational_dtype?
269
+ [:rational32, :rational64, :rational128].include?(self.dtype)
270
+ end
271
+
251
272
 
252
273
  #
253
274
  # call-seq:
@@ -352,7 +373,7 @@ class NMatrix
352
373
  #
353
374
  # See @row (dimension = 0), @column (dimension = 1)
354
375
  def rank(shape_idx, rank_idx, meth = :copy)
355
-
376
+
356
377
  if shape_idx > (self.dim-1)
357
378
  raise(RangeError, "#rank call was out of bounds")
358
379
  end
@@ -428,7 +449,6 @@ class NMatrix
428
449
  end
429
450
  t = reshape_clone_structure(newer_shape)
430
451
  left_params = [:*]*newer_shape.size
431
- puts(left_params)
432
452
  right_params = [:*]*self.shape.size
433
453
  t[*left_params] = self[*right_params]
434
454
  t
@@ -512,7 +532,6 @@ class NMatrix
512
532
  end
513
533
 
514
534
 
515
- #
516
535
  # call-seq:
517
536
  # matrix1.concat(*m2) -> NMatrix
518
537
  # matrix1.concat(*m2, rank) -> NMatrix
@@ -520,20 +539,21 @@ class NMatrix
520
539
  # matrix1.vconcat(*m2) -> NMatrix
521
540
  # matrix1.dconcat(*m3) -> NMatrix
522
541
  #
523
- # Joins two matrices together into a new larger matrix. Attempts to determine which direction to concatenate
524
- # on by looking for the first common element of the matrix +shape+ in reverse. In other words, concatenating two
525
- # columns together without supplying +rank+ will glue them into an n x 2 matrix.
542
+ # Joins two matrices together into a new larger matrix. Attempts to determine
543
+ # which direction to concatenate on by looking for the first common element
544
+ # of the matrix +shape+ in reverse. In other words, concatenating two columns
545
+ # together without supplying +rank+ will glue them into an n x 2 matrix.
526
546
  #
527
- # You can also use hconcat, vconcat, and dconcat for the first three ranks. concat performs an hconcat when no
528
- # rank argument is provided.
547
+ # You can also use hconcat, vconcat, and dconcat for the first three ranks.
548
+ # concat performs an hconcat when no rank argument is provided.
529
549
  #
530
550
  # The two matrices must have the same +dim+.
531
551
  #
532
552
  # * *Arguments* :
533
553
  # - +matrices+ -> one or more matrices
534
- # - +rank+ -> Fixnum (for rank); alternatively, may use :row, :column, or :layer for 0, 1, 2, respectively
535
- #
536
- def concat *matrices
554
+ # - +rank+ -> Fixnum (for rank); alternatively, may use :row, :column, or
555
+ # :layer for 0, 1, 2, respectively
556
+ def concat(*matrices)
537
557
  rank = nil
538
558
  rank = matrices.pop unless matrices.last.is_a?(NMatrix)
539
559
 
@@ -587,15 +607,18 @@ class NMatrix
587
607
  n
588
608
  end
589
609
 
590
- def hconcat *matrices
610
+ # Horizontal concatenation with +matrices+.
611
+ def hconcat(*matrices)
591
612
  concat(*matrices, :column)
592
613
  end
593
614
 
594
- def vconcat *matrices
615
+ # Vertical concatenation with +matrices+.
616
+ def vconcat(*matrices)
595
617
  concat(*matrices, :row)
596
618
  end
597
619
 
598
- def dconcat *matrices
620
+ # Depth concatenation with +matrices+.
621
+ def dconcat(*matrices)
599
622
  concat(*matrices, :layer)
600
623
  end
601
624
 
@@ -29,7 +29,7 @@
29
29
  require 'rspec'
30
30
 
31
31
  # Amend RSpec to allow #be_within for matrices.
32
- module RSpec::Matchers::BuiltIn #:nodoc:
32
+ module RSpec::Matchers::BuiltIn
33
33
  class BeWithin
34
34
 
35
35
  def of(expected)
@@ -72,4 +72,4 @@ module RSpec::Matchers::BuiltIn #:nodoc:
72
72
  end
73
73
 
74
74
  end
75
- end
75
+ end
@@ -34,29 +34,40 @@
34
34
 
35
35
  class NMatrix
36
36
 
37
-
38
-
39
- #
40
37
  # call-seq:
41
- # dense? -> true or false
42
- # list? -> true or false
43
- # yale? -> true or false
44
- #
45
- # Shortcut functions for quickly determining a matrix's stype.
38
+ # m.dense? -> true or false
46
39
  #
40
+ # Determine if +m+ is a dense matrix.
47
41
  def dense?; return stype == :dense; end
48
- def yale?; return stype == :yale; end
49
- def list?; return stype == :list; end
50
42
 
43
+ # call-seq:
44
+ # m.yale? -> true or false
45
+ #
46
+ # Determine if +m+ is a Yale matrix.
47
+ def yale?; return stype == :yale; end
48
+
49
+ # call-seq:
50
+ # m.list? -> true or false
51
+ #
52
+ # Determine if +m+ is a list-of-lists matrix.
53
+ def list?; return stype == :list; end
51
54
 
52
55
  class << self
53
- #
54
56
  # call-seq:
55
- # NMatrix[array-of-arrays, dtype = nil]
57
+ # NMatrix[Numeric, ..., Numeric, dtype: Symbol] -> NMatrix
58
+ # NMatrix[Array, dtype: Symbol] -> NMatrix
59
+ #
60
+ # The default value for +dtype+ is guessed from the first parameter. For example:
61
+ # NMatrix[1.0, 2.0].dtype # => :float64
62
+ # NMatrix[1r, 2r].dtype # => :rational64
56
63
  #
57
- # You can use the old +N+ constant in this way:
64
+ # But this is just a *guess*. If the other values can't be converted to
65
+ # this dtype, a +TypeError+ will be raised.
66
+ #
67
+ # You can use the +N+ constant in this way:
58
68
  # N = NMatrix
59
69
  # N[1, 2, 3]
70
+ #
60
71
  # NMatrix needs to have a succinct way to create a matrix by specifying the
61
72
  # components directly. This is very useful for using it as an advanced
62
73
  # calculator, it is useful for learning how to use, for testing language
@@ -68,12 +79,16 @@ class NMatrix
68
79
  #
69
80
  # Examples:
70
81
  #
71
- # a = NMatrix[ 1,2,3,4 ] => 1.0 2.0 3.0 4.0
82
+ # a = N[ 1,2,3,4 ] => 1 2 3 4
72
83
  #
73
- # a = NMatrix[ 1,2,3,4, dtype: :int32 ] => 1 2 3 4
84
+ # a = N[ 1,2,3,4, :int32 ] => 1 2 3 4
74
85
  #
75
- # a = NMatrix[ [1,2,3], [3,4,5] ] => 1.0 2.0 3.0
76
- # 3.0 4.0 5.0
86
+ # a = N[ [1,2,3], [3,4,5] ] => 1.0 2.0 3.0
87
+ # 3.0 4.0 5.0
88
+ #
89
+ # a = N[ 3,6,9 ].transpose => 3
90
+ # 6
91
+ # 9
77
92
  #
78
93
  # SYNTAX COMPARISON:
79
94
  #
@@ -83,7 +98,6 @@ class NMatrix
83
98
  #
84
99
  # SciRuby: a = NMatrix[ [1,2,3], [4,5,6] ]
85
100
  # Ruby array: a = [ [1,2,3], [4,5,6] ]
86
- #
87
101
  def [](*params)
88
102
  options = params.last.is_a?(Hash) ? params.pop : {}
89
103
 
@@ -159,7 +173,6 @@ class NMatrix
159
173
  NMatrix.new(shape, 1, {:dtype => :float64, :default => 1}.merge(opts))
160
174
  end
161
175
 
162
- ##
163
176
  # call-seq:
164
177
  # ones_like(nm) -> NMatrix
165
178
  #
@@ -173,7 +186,6 @@ class NMatrix
173
186
  NMatrix.ones(nm.shape, dtype: nm.dtype, stype: nm.stype, capacity: nm.capacity, default: 1)
174
187
  end
175
188
 
176
- ##
177
189
  # call-seq:
178
190
  # zeros_like(nm) -> NMatrix
179
191
  #
@@ -355,7 +367,7 @@ class NMatrix
355
367
  end
356
368
  end
357
369
 
358
- module NVector
370
+ module NVector #:nodoc:
359
371
 
360
372
  class << self
361
373
  #
@@ -648,14 +660,19 @@ module NVector
648
660
  end
649
661
 
650
662
 
651
- # Use this constant as you would use NMatrix[].
663
+ # This constant is intended as a simple constructor for NMatrix meant for
664
+ # experimenting.
665
+ #
652
666
  # Examples:
653
667
  #
654
- # a = N[ 1,2,3,4 ] => 1.0 2.0 3.0 4.0
668
+ # a = N[ 1,2,3,4 ] => 1 2 3 4
655
669
  #
656
670
  # a = N[ 1,2,3,4, :int32 ] => 1 2 3 4
657
671
  #
658
- # a = N[ [1,2,3], [3,4,5] ] => 1.0 2.0 3.0
659
- # 3.0 4.0 5.0
672
+ # a = N[ [1,2,3], [3,4,5] ] => 1 2 3
673
+ # 3 4 5
660
674
  #
675
+ # a = N[ 3,6,9 ].transpose => 3
676
+ # 6
677
+ # 9
661
678
  N = NMatrix
@@ -26,14 +26,14 @@ class NMatrix
26
26
  # Note that the format of the VERSION string is needed for NMatrix
27
27
  # native IO. If you change the format, please make sure that native
28
28
  # IO can still understand NMatrix::VERSION.
29
- #VERSION = "0.1.0"
30
- module VERSION
29
+ module VERSION #:nodoc:
31
30
  MAJOR = 0
32
31
  MINOR = 1
33
32
  TINY = 0
34
- PRE = "rc5"
33
+ # PRE = "rc5"
35
34
 
36
- STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
35
+ STRING = [MAJOR, MINOR, TINY].compact.join(".")
36
+ #STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
37
37
  end
38
38
  end
39
39
 
@@ -6,12 +6,12 @@ require 'nmatrix/version'
6
6
  Gem::Specification.new do |gem|
7
7
  gem.name = "nmatrix"
8
8
  gem.version = NMatrix::VERSION::STRING
9
- gem.summary = "NMatrix is an experimental linear algebra library for Ruby, written mostly in C."
10
- gem.description = "NMatrix is an experimental linear algebra library for Ruby, written mostly in C."
9
+ gem.summary = "NMatrix is a linear algebra library for Ruby"
10
+ gem.description = "NMatrix is a linear algebra library for Ruby, written mostly in C and C++."
11
11
  gem.homepage = 'http://sciruby.com'
12
12
  gem.authors = ['John Woods', 'Chris Wailes', 'Aleksey Timin']
13
13
  gem.email = ['john.o.woods@gmail.com']
14
- gem.license = 'BSD 2-clause'
14
+ gem.license = 'BSD 3-clause'
15
15
  gem.post_install_message = <<-EOF
16
16
  ***********************************************************
17
17
  Welcome to SciRuby: Tools for Scientific Computing in Ruby!
@@ -44,6 +44,7 @@ EOF
44
44
  gem.required_ruby_version = '>= 1.9'
45
45
 
46
46
  gem.add_dependency 'rdoc', '~>4.0', '>=4.0.1'
47
+ gem.add_dependency 'packable', '~> 1.3', '>= 1.3.5'
47
48
  gem.add_development_dependency 'rake', '~>10.3'
48
49
  gem.add_development_dependency 'bundler', '~>1.6'
49
50
  gem.add_development_dependency 'rspec', '~>2.14'
@@ -0,0 +1,72 @@
1
+ require 'spec_helper'
2
+
3
+ describe NMatrix do
4
+ describe "#to_a" do
5
+ it "creates an Array with the same dimensions" do
6
+ n = NMatrix.seq([3,2])
7
+ expect(n.to_a).to eq([[0, 1], [2, 3], [4, 5]])
8
+ end
9
+
10
+ it "creates an Array with the proper element type" do
11
+ n = NMatrix.seq([3,2], dtype: :float64)
12
+ expect(n.to_a).to eq([[0.0, 1.0], [2.0, 3.0], [4.0, 5.0]])
13
+ end
14
+
15
+ it "properly interprets list matrices" do
16
+ n = NMatrix.seq([3,2], stype: :list)
17
+ expect(n.to_a).to eq([[0, 1], [2, 3], [4, 5]])
18
+ end
19
+
20
+ it "properly interprets yale matrices" do
21
+ n = NMatrix.seq([3,2], stype: :yale)
22
+ expect(n.to_a).to eq([[0, 1], [2, 3], [4, 5]])
23
+ end
24
+ end
25
+ end
26
+
27
+ describe Array do
28
+ describe "#to_nm" do
29
+ # [0, 1, 2, 3, 4, 5]
30
+ let(:a) {(0..5).to_a}
31
+
32
+ it "uses a given shape and type" do
33
+ expect(a.to_nm([3,2]).dtype).to eq :int64
34
+ expect(a.to_nm([3,2])).to eq(NMatrix.seq([3,2]))
35
+ end
36
+
37
+ it "guesses dtype based on first element" do
38
+ a[0] = 0.0
39
+ expect(a.to_nm([3,2]).dtype).to eq :float64
40
+ end
41
+
42
+ it "defaults to dtype :object if necessary" do
43
+ a = %w(this is an array of strings)
44
+ expect(a.to_nm([3,2]).dtype).to eq :object
45
+ expect(a.to_nm([3,2])).to eq(NMatrix.new([3,2], a, dtype: :object))
46
+ end
47
+
48
+ it "attempts to intuit the shape of the Array" do
49
+ a = [[0, 1], [2, 3], [4, 5]]
50
+ expect(a.to_nm).to eq(NMatrix.new([3,2], a.flatten))
51
+ expect(a.to_nm.dtype).to eq :int64
52
+ end
53
+
54
+ it "creates an object Array for inconsistent dimensions" do
55
+ a = [[0, 1, 2], [3], [4, 5]]
56
+ expect(a.to_nm).to eq(NMatrix.new([3], a, dtype: :object))
57
+ expect(a.to_nm.dtype).to eq :object
58
+ end
59
+
60
+ it "intuits shape of Array into multiple dimensions" do
61
+ a = [[[0], [1]], [[2], [3]], [[4], [5]]]
62
+ expect(a.to_nm).to eq(NMatrix.new([3,1,2], a.flatten))
63
+ expect(a).to eq(a.to_nm.to_a)
64
+ end
65
+
66
+ it "is reflective with NMatrix#to_a" do
67
+ a = [[0, 1, 2], [3], [4, 5]]
68
+ expect(a).to eq(a.to_nm.to_a)
69
+ end
70
+ end
71
+ end
72
+