stair_car 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/.gitignore +21 -0
  2. data/Gemfile +14 -0
  3. data/Guardfile +18 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +223 -0
  6. data/Rakefile +1 -0
  7. data/lib/matlab/matlabcontrol-4.0.0.jar +0 -0
  8. data/lib/pcolt/lib/arpack-combo.jar +0 -0
  9. data/lib/pcolt/lib/csparsej.jar +0 -0
  10. data/lib/pcolt/lib/jplasma.jar +0 -0
  11. data/lib/pcolt/lib/jtransforms.jar +0 -0
  12. data/lib/pcolt/lib/junit.jar +0 -0
  13. data/lib/pcolt/lib/netlib-java.jar +0 -0
  14. data/lib/pcolt/lib/optimization.jar +0 -0
  15. data/lib/pcolt/parallelcolt-0.9.4.jar +0 -0
  16. data/lib/stair_car/mmatrix/matlab_interface.rb +9 -0
  17. data/lib/stair_car/mmatrix/mmatrix.rb +26 -0
  18. data/lib/stair_car/pmatrix/compare.rb +34 -0
  19. data/lib/stair_car/pmatrix/matrix_math.rb +169 -0
  20. data/lib/stair_car/pmatrix/pmatrix.rb +151 -0
  21. data/lib/stair_car/pmatrix/transforms.rb +74 -0
  22. data/lib/stair_car/pmatrix/types.rb +106 -0
  23. data/lib/stair_car/shared/errors.rb +7 -0
  24. data/lib/stair_car/shared/indicies.rb +33 -0
  25. data/lib/stair_car/shared/init_methods.rb +56 -0
  26. data/lib/stair_car/shared/inspect.rb +113 -0
  27. data/lib/stair_car/shared/iteration.rb +32 -0
  28. data/lib/stair_car/umatrix/compare.rb +34 -0
  29. data/lib/stair_car/umatrix/matrix_math.rb +190 -0
  30. data/lib/stair_car/umatrix/transforms.rb +49 -0
  31. data/lib/stair_car/umatrix/types.rb +42 -0
  32. data/lib/stair_car/umatrix/umatrix.rb +166 -0
  33. data/lib/stair_car.rb +35 -0
  34. data/lib/ujmp/ujmp-complete-0.2.5.jar +0 -0
  35. data/spec/pmatrix/matrix_math_spec.rb +65 -0
  36. data/spec/pmatrix/pmatrix_spec.rb +103 -0
  37. data/spec/pmatrix/transforms_spec.rb +44 -0
  38. data/spec/shared/indicies_spec.rb +52 -0
  39. data/spec/shared/inspect_spec.rb +23 -0
  40. data/spec/shared/iteration_spec.rb +17 -0
  41. data/spec/spec_helper.rb +5 -0
  42. data/spec/umatrix/matrix_math_spec.rb +68 -0
  43. data/spec/umatrix/transform_spec.rb +32 -0
  44. data/spec/umatrix/umatrix_spec.rb +104 -0
  45. data/stair_car.gemspec +19 -0
  46. metadata +120 -0
@@ -0,0 +1,190 @@
1
+ module StairCar
2
+ module UMatrixMatrixMath
3
+ class MatrixMathError < RuntimeError
4
+ end
5
+
6
+ # In jruby, we need to pass the params to java_methods to distinguish them
7
+ # when multiple java methods (with different params) have the same name.
8
+ def find_params(object, method_name, &search)
9
+ while object
10
+ object.declared_instance_methods.each do |method|
11
+ if method.name == method_name
12
+ if yield(method.parameter_types)
13
+ # Method checks to see if the parameter types are correct, if they
14
+ # are then we return them.
15
+ return method.parameter_types
16
+ end
17
+ end
18
+ end
19
+
20
+ # If we didn't find it here, move up the chain
21
+ object = object.superclass
22
+ end
23
+
24
+ return nil
25
+ end
26
+
27
+ def perform(method, val)
28
+ method = method.to_s
29
+ result = @data.clone
30
+ if val.is_a?(UMatrix)
31
+ @param_types ||= {}
32
+ @param_types[method] ||= find_params(result.java_class, method) do |params|
33
+ # params.first.name == 'org.ujmp.core.Matrix'
34
+ params.size == 3 &&
35
+ params[0].name == 'org.ujmp.core.calculation.Calculation$Ret' &&
36
+ params[1].name == 'boolean' &&
37
+ params[2].name == 'org.ujmp.core.Matrix'
38
+ end
39
+ if rows == val.rows && cols == val.cols
40
+ # Another matrix of the same size
41
+ # result = result.java_send(method, @param_types[method], val.data)
42
+ result.java_send(method, @param_types[method], Java::OrgUjmpCoreCalculation::Calculation.ORIG, false.to_java, val.data)
43
+ elsif rows == val.rows && val.cols == 1
44
+ # Vector on column (vertical)
45
+ UMatrix.new(result).each_column do |row|
46
+ # row.data.send(method, Java::OrgUjmpCoreCalculation::Calculation.ORIG, false.to_java, val.data)
47
+ # row.data.java_send(method, @param_types[method], val.data)
48
+ row.data.java_send(method, @param_types[method], Java::OrgUjmpCoreCalculation::Calculation.ORIG, false.to_java, val.data)
49
+ end
50
+ elsif cols == val.cols && val.rows == 1
51
+ # Vector on rows (horizontal)
52
+ UMatrix.new(result).each_row do |col|
53
+ col.data.java_send(method, @param_types[method], Java::OrgUjmpCoreCalculation::Calculation.ORIG, false.to_java, val.data)
54
+ # col.data.send(method, Java::OrgUjmpCoreCalculation::Calculation.ORIG, false.to_java, val.data)
55
+ end
56
+ else
57
+ # Incorrect size
58
+ raise MatrixMathError, "matrix dimensions incorrect"
59
+ end
60
+ else
61
+ # Passed in a number
62
+ result = result.send(method, Java::OrgUjmpCoreCalculation::Calculation.ORIG, false.to_java, val.to_java(:double))
63
+ end
64
+
65
+ return UMatrix.new(result)
66
+ end
67
+
68
+ def +(val)
69
+ perform(:plus, val)
70
+ end
71
+
72
+ def -(val)
73
+ perform(:minus, val)
74
+ end
75
+
76
+ def **(val)
77
+ end
78
+
79
+ def /(val)
80
+ end
81
+
82
+ def *(val)
83
+ n = self.rows
84
+ m = self.cols
85
+
86
+ p = val.rows
87
+ q = val.cols
88
+
89
+ if m != p
90
+ raise MatrixMathError, "matricies can not be multiplied"
91
+ end
92
+
93
+ # Build a like matrix to receive
94
+ c = @data.like(n, q)
95
+
96
+ @data.z_mult(val.data, c)
97
+
98
+ return UMatrix.new(c)
99
+ end
100
+
101
+ # ujmp requires you pass in a special code for all dimensions
102
+ def dim_convert(dimension)
103
+ if dimension == nil
104
+ dimension = Java::org.ujmp.core.Matrix::ALL
105
+ end
106
+
107
+ return dimension
108
+ end
109
+
110
+ # Calls aggraration method on the data
111
+ def call_data_method(method, dimension, *args)
112
+ result = UMatrix.new(@data.send(method, Java::OrgUjmpCoreCalculation::Calculation.NEW, dim_convert(dimension), *args))
113
+ if dimension
114
+ return result
115
+ else
116
+ # Just return the first element
117
+ return result[0,0]
118
+ end
119
+ end
120
+
121
+ def sum(dimension=nil)
122
+ return call_data_method(:sum, dimension, false)
123
+ end
124
+
125
+ def max(dimension=nil)
126
+ return call_data_method(:max, dimension)
127
+ end
128
+
129
+ def min(dimension=nil)
130
+ return call_data_method(:min, dimension)
131
+ end
132
+
133
+ def mean(dimension=nil)
134
+ return call_data_method(:mean, dimension, false)
135
+ end
136
+
137
+ def variance(dimension=nil, sample=false)
138
+ if dimension
139
+ value = aggrate_on_dimension(:variance, dimension, sample)
140
+ else
141
+ mean = self.mean
142
+ total = 0
143
+ self.each_non_zero do |v|
144
+ total += (mean - v) ** 2
145
+ end
146
+
147
+ if sample
148
+ value = total / (self.size - 1)
149
+ else
150
+ value = total / self.size
151
+ end
152
+ end
153
+
154
+ return value
155
+ end
156
+
157
+ def std(dimension=nil, sample=false)
158
+ if dimension
159
+ value = aggrate_on_dimension(:variance, dimension, sample)
160
+ else
161
+ value = Math.sqrt(self.variance(dimension, sample))
162
+ end
163
+
164
+ return value
165
+ end
166
+
167
+ private
168
+ def aggrate_on_dimension(method_name, dimension, *args)
169
+ if dimension == 0
170
+ # Get the per row
171
+ vals = UMatrix.new(@data.like(rows, 1))
172
+
173
+ self.each_row do |row, row_number|
174
+ vals[row_number,0] = row.send(method_name, nil, *args).to_f
175
+ end
176
+
177
+ return vals
178
+ elsif dimension == 1
179
+ # Get the per row
180
+ vals = UMatrix.new(@data.like(1, cols))
181
+
182
+ self.each_column do |col, col_number|
183
+ vals[0,col_number] = col.send(method_name, nil, *args).to_f
184
+ end
185
+
186
+ return vals
187
+ end
188
+ end
189
+ end
190
+ end
@@ -0,0 +1,49 @@
1
+ module StairCar
2
+ module UMatrixTransforms
3
+ def transpose
4
+ return UMatrix.new(@data.transpose)
5
+ end
6
+
7
+ def ~
8
+ return transpose
9
+ end
10
+
11
+ def map(&block)
12
+ dup.map!(&block)
13
+ end
14
+
15
+ def map!
16
+ result = self.each_with_index do |val,row,col|
17
+ self[row,col] = yield(val, row, col)
18
+ end
19
+
20
+ return self
21
+ end
22
+
23
+ def map_non_zero(&block)
24
+ dup.map_non_zero!(&block)
25
+ end
26
+
27
+ def map_non_zero!
28
+ each_non_zero do |val,row,col|
29
+ self[row,col] = yield(val, row, col)
30
+ end
31
+
32
+ return self
33
+ end
34
+
35
+ # Converts the matrix into an array
36
+ def to_a
37
+ array = []
38
+ rows.times do |row|
39
+ col_array = []
40
+ cols.times do |col|
41
+ col_array << self[row,col]
42
+ end
43
+ array << col_array
44
+ end
45
+
46
+ return array
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,42 @@
1
+ # Lookup the type for the underlying matrix implementation
2
+ module StairCar
3
+ module UMatrixTypes
4
+
5
+ def type
6
+ return :double
7
+ end
8
+
9
+ def sparse?
10
+ @data.sparse?
11
+ end
12
+
13
+
14
+ def type_class(type, sparse, initialize_values)
15
+ if sparse
16
+ base = Java::org.ujmp.parallelcolt::ParallelColtSparseDoubleMatrix2D
17
+ else
18
+ base = Java::org.ujmp.core.Matrix.factory
19
+ end
20
+
21
+ # if sparse
22
+ # base = Java::org.ujmp.core.matrix.SparseMatrix.factory
23
+ # else
24
+ # base = Java::org.ujmp.core.Matrix.factory
25
+ # end
26
+
27
+ if [:zeros, :ones, :rand, :desc, :asc].include?(initialize_values)
28
+ if [:asc, :desc].include?(initialize_values)
29
+ initialize_values = :zeros
30
+ end
31
+
32
+ if sparse && initialize_values == :zeros
33
+ initialize_values = :new
34
+ end
35
+
36
+ return Proc.new { |rows, cols| base.send(initialize_values, rows, cols) }
37
+ else
38
+ raise "Type is not valid"
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,166 @@
1
+ require File.dirname(__FILE__) + '/../../pcolt/parallelcolt-0.9.4'
2
+ require File.dirname(__FILE__) + '/../../ujmp/ujmp-complete-0.2.5'
3
+
4
+ require 'stair_car/umatrix/types'
5
+ require 'stair_car/umatrix/matrix_math'
6
+ require 'stair_car/umatrix/transforms'
7
+ require 'stair_car/umatrix/compare'
8
+ require 'stair_car/shared/iteration'
9
+ require 'stair_car/shared/inspect'
10
+ require 'stair_car/shared/indicies'
11
+ require 'stair_car/shared/init_methods'
12
+ require 'stair_car/shared/errors'
13
+
14
+ module StairCar
15
+ class UMatrix
16
+ include UMatrixTypes
17
+ # include Indicies
18
+ include UMatrixMatrixMath
19
+ include UMatrixTransforms
20
+ include UMatrixCompare
21
+ include Iteration
22
+ include Inspect
23
+ include Indicies
24
+ include InitMethods
25
+
26
+ attr_accessor :data
27
+
28
+ def initialize(rows_or_data=nil, cols=nil, type=:double, sparse=false, initialize_values=:zeros)
29
+ if rows_or_data.is_a?(Array)
30
+ klass = type_class(type, sparse, initialize_values)
31
+
32
+ # Create the matrix from an array
33
+ from_array(rows_or_data, klass)
34
+ elsif rows_or_data.is_a?(Fixnum)
35
+ raise MatrixDimensionsError, "Must specify columns and rows" unless rows_or_data && cols
36
+ klass = type_class(type, sparse, initialize_values)
37
+ if klass.is_a?(Method) || klass.is_a?(Proc)
38
+ # A factory method was returned, call to build
39
+ @data = klass.call(rows_or_data, cols)
40
+ else
41
+ # A class was returned, create new
42
+ @data = klass.new(rows_or_data, cols)
43
+ end
44
+
45
+ setup_default_values(initialize_values)
46
+ else
47
+ # Passing in data directly
48
+ @data = rows_or_data
49
+ end
50
+ end
51
+
52
+ def setup_default_values(initialize_values)
53
+ if initialize_values == :asc
54
+ i = 0
55
+ self.map! do |val,row,col|
56
+ self[row,col] = i
57
+ i += 1
58
+ end
59
+ elsif initialize_values == :desc
60
+ i = size
61
+ self.map! do |val,row,col|
62
+ self[row,col] = i
63
+ i -= 1
64
+ end
65
+ end
66
+ end
67
+
68
+
69
+ def shape
70
+ rows, cols = data.size
71
+
72
+ return [rows, cols]
73
+ end
74
+
75
+ def size
76
+ rows, cols = shape
77
+ return rows * cols
78
+ end
79
+
80
+ def rows
81
+ return shape[0]
82
+ end
83
+
84
+ def cols
85
+ return shape[1]
86
+ end
87
+
88
+ def [](rows, cols)
89
+ rows = convert_indicies(rows, self.rows)
90
+ cols = convert_indicies(cols, self.cols)
91
+
92
+ # Returns either the value in a cell or a subview
93
+ if rows && cols && rows.size == 1 && cols.size == 1 && rows.first.is_a?(Fixnum) && cols.first.is_a?(Fixnum)
94
+ if @data.is_a?(Java::org.ujmp.core.objectmatrix.impl.ObjectCalculationMatrix)
95
+ @data.getObject(rows.first.to_java(:int), cols.first.to_java(:int)) || 0.0
96
+ else
97
+ # From jruby we have to call this way for doubles
98
+ @data.java_send(:getObject, [Java::long, Java::long], rows.first, cols.first) || 0.0
99
+ end
100
+ else
101
+ # Get subview, also convert rows/cols to java arrays
102
+ if !rows && !cols
103
+ return self.class.new(@data)
104
+ else
105
+ if rows
106
+ return self.class.new(@data.select(Java::OrgUjmpCoreCalculation::Calculation.LINK, rows, cols))
107
+ else
108
+ # If row is nil, we need to lookup by columns directly
109
+ return self.class.new(@data.select_columns(Java::OrgUjmpCoreCalculation::Calculation.LINK, cols))
110
+ end
111
+ end
112
+ end
113
+ end
114
+
115
+ def []=(rows, cols, value)
116
+ rows = convert_indicies(rows, self.rows)
117
+ cols = convert_indicies(cols, self.cols)
118
+
119
+ # Set either the value in a cell or a subview with a matrix
120
+ if rows && cols && rows.size == 1 && cols.size == 1 && rows.first.is_a?(Fixnum) && cols.first.is_a?(Fixnum)
121
+ @data.setObject(value.to_java(:double), rows.first, cols.first)
122
+ else
123
+ subview = self[rows, cols]
124
+
125
+ # Assign a single array or a nested array
126
+ if value.is_a?(Array)
127
+ value_rows, value_cols = array_dimensions(value)
128
+
129
+ # If one dimentional, and they want to set cols
130
+ if value_rows == 1 && subview.cols == 1
131
+ # Transpose so we can place an array vertically
132
+ subview = subview.transpose
133
+ end
134
+
135
+ # Check to make sure the sizes match
136
+ if value_rows != subview.rows || value_cols != subview.cols
137
+ raise MatrixDimensionsError, "the array you are trying to assign is not the correct size"
138
+ end
139
+ end
140
+
141
+ # value = convert_value(value)
142
+ unless value[0].is_a?(Array)
143
+ value = [value]
144
+ end
145
+
146
+ value.each_with_index do |row,row_index|
147
+ row.each_with_index do |cell,col_index|
148
+ subview[row_index, col_index] = cell
149
+ end
150
+ end
151
+ end
152
+ end
153
+
154
+ # Loop through each non-zero value, pass in the value, row, column
155
+ def each_non_zero(&block)
156
+ @data.available_coordinates.each do |row, col|
157
+ val = self[row,col]
158
+ yield(val, row, col)
159
+ end
160
+ end
161
+
162
+ def dup
163
+ UMatrix.new(@data.clone)
164
+ end
165
+ end
166
+ end
data/lib/stair_car.rb ADDED
@@ -0,0 +1,35 @@
1
+ require 'java'
2
+ require 'stair_car/pmatrix/pmatrix'
3
+ require 'stair_car/umatrix/umatrix'
4
+
5
+ module StairCar
6
+ def self.included(klass)
7
+ # Add easy access methods
8
+ PMatrix.init_method_names do |method_name, sparse, type, initialize_values|
9
+ klass.send(:define_method, method_name) do |cols, rows|
10
+ PMatrix.new(cols, rows, type, sparse, initialize_values)
11
+ end
12
+ end
13
+ end
14
+
15
+ def to_java_nested_array(array, type=:double)
16
+ if type == :double
17
+ type = java.lang.Double::TYPE
18
+ else
19
+ type = java.lang.Float::TYPE
20
+ end
21
+
22
+ rows = array.size
23
+ cols = array[0].size
24
+
25
+ java_array = java.lang.reflect.Array.newInstance(type, [rows,cols].to_java(:int))
26
+
27
+ rows.times do |row|
28
+ cols.times do |col|
29
+ java_array[row][col] = array[row][col]
30
+ end
31
+ end
32
+
33
+ return java_array
34
+ end
35
+ end
Binary file
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+ require 'stair_car'
3
+
4
+ describe StairCar::PMatrixMatrixMath do
5
+ before(:all) do
6
+ @a = StairCar::PMatrix.asc(5,5)
7
+ @b = StairCar::PMatrix.asc(5,5)
8
+ end
9
+
10
+ it 'should add matricies' do
11
+ c = @a + @b
12
+ c[0,0].should == 2
13
+ end
14
+
15
+ it 'should add scalars' do
16
+ c = @a + 5
17
+ # Should copy
18
+ @a[0,0].should == 1
19
+
20
+ c[0,0].should == 6
21
+ end
22
+
23
+ it 'should add vectors' do
24
+ c = StairCar::PMatrix.new([[1,2,3,4,5]])
25
+ # (@a + c).should == StairCar::PMatrix.new([[2,4,6,8,10]])
26
+ end
27
+
28
+
29
+ it 'should sum all' do
30
+ matrix = StairCar::PMatrix.asc(3,3)
31
+ matrix.sum.should == 45
32
+ end
33
+
34
+ it 'should sum columns' do
35
+ matrix = StairCar::PMatrix.asc(3,5)
36
+ matrix.sum(0).should == StairCar::PMatrix.new([[18, 21, 24, 27, 30]])
37
+ end
38
+
39
+ it 'should get the max on columns or rows' do
40
+ matrix = StairCar::PMatrix.asc(3,5)
41
+ matrix.max(1).should == StairCar::PMatrix.new([[5],[10],[15]])
42
+ matrix.max(0).should == StairCar::PMatrix.new([[11, 12, 13, 14, 15]])
43
+ end
44
+
45
+ it 'should get the mins on columns or rows' do
46
+ matrix = StairCar::PMatrix.asc(3,5)
47
+ matrix.min(1).should == StairCar::PMatrix.new([[1],[6],[11]])
48
+ matrix.min(0).should == StairCar::PMatrix.new([[1, 2, 3, 4, 5]])
49
+ end
50
+
51
+ it "should return the mean on each dimension" do
52
+ matrix = StairCar::PMatrix.asc(3,5)
53
+ matrix.mean.should == 8.0
54
+ matrix.mean(1).should == StairCar::PMatrix.new([[3],[8],[13]])
55
+ matrix.mean(0).should == StairCar::PMatrix.new([[6, 7, 8, 9, 10]])
56
+ end
57
+
58
+ it "should return the variance" do
59
+
60
+ end
61
+
62
+ it "should return the standard deviation" do
63
+
64
+ end
65
+ end
@@ -0,0 +1,103 @@
1
+ require 'spec_helper'
2
+ require 'stair_car'
3
+
4
+ describe StairCar::PMatrix do
5
+ it "should initialize" do
6
+ matrix = StairCar::PMatrix.zeros(5,4)
7
+ matrix.cols.should == 4
8
+ matrix.rows.should == 5
9
+ matrix.size.should == 20
10
+
11
+ matrix = StairCar::PMatrix.spzeros(5,4)
12
+ matrix.size.should == 20
13
+ end
14
+
15
+ it "should initialize with values" do
16
+ matrix1 = StairCar::PMatrix.new([[3,8,13]])
17
+ matrix1[0,0].should == 3
18
+ matrix1[0,2].should == 13
19
+
20
+ matrix2 = StairCar::PMatrix.new([[3],[8],[13]])
21
+ matrix2[0,0].should == 3
22
+ matrix2[2,0].should == 13
23
+ end
24
+
25
+ it "should set and get" do
26
+ matrix = StairCar::PMatrix.zeros(3,4)
27
+ matrix[0,0] = 5
28
+ matrix[0,0].should == 5
29
+ end
30
+
31
+ it 'should assign a matrix to a subview' do
32
+ matrix = StairCar::PMatrix.asc(3,3)
33
+ s = matrix[0,nil]
34
+ matrix[1,nil] = s
35
+ end
36
+
37
+ it "should set via arrays" do
38
+ matrix = StairCar::PMatrix.zeros(3,4)
39
+ matrix[0,nil] = [1,2,3,4]
40
+ matrix[0,nil].should == StairCar::PMatrix.new([1,2,3,4])
41
+ matrix[nil,0] = [1,2,3]
42
+ matrix[nil,nil] = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
43
+ end
44
+
45
+ it "should raise an error when trying to assign an array with invalid dimensions" do
46
+ matrix = StairCar::PMatrix.zeros(3,4)
47
+
48
+ lambda {
49
+ matrix[0,nil] = [1,2,3,4,5,6]
50
+ }.should raise_error(StairCar::MatrixDimensionsError)
51
+ end
52
+
53
+ it "should get and set with negative values" do
54
+ matrix = StairCar::PMatrix.zeros(5,4)
55
+ matrix[4,3] = 5
56
+ matrix[-1,-1].should == 5
57
+ end
58
+
59
+ it "should allow you to setup ones" do
60
+ matrix = StairCar::PMatrix.ones(5,5)
61
+ matrix[2,2].should == 1
62
+ end
63
+
64
+
65
+ it 'should compare matrix values' do
66
+ matrix1 = StairCar::PMatrix.asc(3,3)
67
+ matrix2 = StairCar::PMatrix.asc(3,3)
68
+ matrix3 = StairCar::PMatrix.zeros(3,3)
69
+
70
+ matrix1.should == matrix2
71
+ matrix1.should_not == matrix3
72
+ end
73
+
74
+ it "should allow you to set with an array" do
75
+ matrix = StairCar::PMatrix.zeros(2,2)
76
+ matrix[nil,nil] = [[1,2],[3,4]]
77
+ matrix[0,0].should == 1.0
78
+ matrix[1,1].should == 4.0
79
+ end
80
+
81
+ it "should allow you to initialize by an array" do
82
+ matrix = StairCar::PMatrix.new([[1,2],[3,4]])
83
+ matrix[0,0].should == 1.0
84
+ matrix[1,1].should == 4.0
85
+ end
86
+
87
+ describe "dimensions" do
88
+ before(:all) do
89
+ @matrix = StairCar::PMatrix.zeros(3,2)
90
+ end
91
+ it "should return its shape" do
92
+ @matrix.shape.should == [3,2]
93
+ end
94
+
95
+ it "should return the rows" do
96
+ @matrix.rows.should == 3
97
+ end
98
+
99
+ it "should return the cols" do
100
+ @matrix.cols.should == 2
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+ require 'stair_car'
3
+
4
+ describe StairCar::PMatrixTransforms do
5
+ it "should transpose" do
6
+ matrix = StairCar::PMatrix.asc(3,4)
7
+ (~matrix).should_not == matrix
8
+ (~~matrix).should == matrix
9
+ end
10
+
11
+ it 'should invert' do
12
+ matrix = StairCar::PMatrix.new([[4,3],[3,2]])
13
+ matrix.inv.should == StairCar::PMatrix.new([[-2, 3], [3, -4]])
14
+ end
15
+
16
+ it 'should raise an error when it fails to invert' do
17
+ matrix = StairCar::PMatrix.asc(3,3)
18
+ lambda {
19
+ matrix.inv
20
+ }.should raise_error(StairCar::InverseMatrixIsSignular)
21
+ end
22
+
23
+ it "should map and map_non_zero" do
24
+ matrix = StairCar::PMatrix.zeros(2,3)
25
+ matrix[0,0] = 5
26
+ matrix[1,2] = 10
27
+ mapped_matrix = matrix.map {|v| v * 2 }
28
+ mapped_matrix[0,0].should == 10
29
+ mapped_matrix[1,2].should == 20
30
+ mapped_matrix[0,1].should == 0
31
+
32
+ calls = 0
33
+ matrix.map_non_zero! {|v,row,col| calls += 1; v + 2 }
34
+ calls.should == 2
35
+ matrix[0,0].should == 7
36
+ matrix[1,2].should == 12
37
+ end
38
+
39
+ it "should convert back to a ruby array" do
40
+ matrix = StairCar::PMatrix.asc(3,3)
41
+ matrix.to_a.should == [[1,2,3],[4,5,6],[7,8,9]]
42
+ end
43
+
44
+ end