stair_car 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +21 -0
- data/Gemfile +14 -0
- data/Guardfile +18 -0
- data/LICENSE.txt +22 -0
- data/README.md +223 -0
- data/Rakefile +1 -0
- data/lib/matlab/matlabcontrol-4.0.0.jar +0 -0
- data/lib/pcolt/lib/arpack-combo.jar +0 -0
- data/lib/pcolt/lib/csparsej.jar +0 -0
- data/lib/pcolt/lib/jplasma.jar +0 -0
- data/lib/pcolt/lib/jtransforms.jar +0 -0
- data/lib/pcolt/lib/junit.jar +0 -0
- data/lib/pcolt/lib/netlib-java.jar +0 -0
- data/lib/pcolt/lib/optimization.jar +0 -0
- data/lib/pcolt/parallelcolt-0.9.4.jar +0 -0
- data/lib/stair_car/mmatrix/matlab_interface.rb +9 -0
- data/lib/stair_car/mmatrix/mmatrix.rb +26 -0
- data/lib/stair_car/pmatrix/compare.rb +34 -0
- data/lib/stair_car/pmatrix/matrix_math.rb +169 -0
- data/lib/stair_car/pmatrix/pmatrix.rb +151 -0
- data/lib/stair_car/pmatrix/transforms.rb +74 -0
- data/lib/stair_car/pmatrix/types.rb +106 -0
- data/lib/stair_car/shared/errors.rb +7 -0
- data/lib/stair_car/shared/indicies.rb +33 -0
- data/lib/stair_car/shared/init_methods.rb +56 -0
- data/lib/stair_car/shared/inspect.rb +113 -0
- data/lib/stair_car/shared/iteration.rb +32 -0
- data/lib/stair_car/umatrix/compare.rb +34 -0
- data/lib/stair_car/umatrix/matrix_math.rb +190 -0
- data/lib/stair_car/umatrix/transforms.rb +49 -0
- data/lib/stair_car/umatrix/types.rb +42 -0
- data/lib/stair_car/umatrix/umatrix.rb +166 -0
- data/lib/stair_car.rb +35 -0
- data/lib/ujmp/ujmp-complete-0.2.5.jar +0 -0
- data/spec/pmatrix/matrix_math_spec.rb +65 -0
- data/spec/pmatrix/pmatrix_spec.rb +103 -0
- data/spec/pmatrix/transforms_spec.rb +44 -0
- data/spec/shared/indicies_spec.rb +52 -0
- data/spec/shared/inspect_spec.rb +23 -0
- data/spec/shared/iteration_spec.rb +17 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/umatrix/matrix_math_spec.rb +68 -0
- data/spec/umatrix/transform_spec.rb +32 -0
- data/spec/umatrix/umatrix_spec.rb +104 -0
- data/stair_car.gemspec +19 -0
- metadata +120 -0
@@ -0,0 +1,151 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../pcolt/parallelcolt-0.9.4'
|
2
|
+
require 'stair_car/pmatrix/types'
|
3
|
+
require 'stair_car/pmatrix/matrix_math'
|
4
|
+
require 'stair_car/pmatrix/transforms'
|
5
|
+
require 'stair_car/pmatrix/compare'
|
6
|
+
require 'stair_car/shared/iteration'
|
7
|
+
require 'stair_car/shared/inspect'
|
8
|
+
require 'stair_car/shared/indicies'
|
9
|
+
require 'stair_car/shared/init_methods'
|
10
|
+
require 'stair_car/shared/errors'
|
11
|
+
|
12
|
+
|
13
|
+
module StairCar
|
14
|
+
class PMatrix
|
15
|
+
include PMatrixTypes
|
16
|
+
include PMatrixMatrixMath
|
17
|
+
include PMatrixTransforms
|
18
|
+
include PMatrixCompare
|
19
|
+
include Iteration
|
20
|
+
include Inspect
|
21
|
+
include Indicies
|
22
|
+
include InitMethods
|
23
|
+
|
24
|
+
attr_accessor :data
|
25
|
+
|
26
|
+
# Proxy methods
|
27
|
+
[:size, :rows].each do |method_name|
|
28
|
+
define_method(method_name) do |*args|
|
29
|
+
@data.send(method_name, *args)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def cols
|
34
|
+
@data.columns
|
35
|
+
end
|
36
|
+
|
37
|
+
def shape
|
38
|
+
[rows, cols]
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
def initialize(rows_or_data=nil, cols=nil, type=:double, sparse=false, initialize_values=:zeros)
|
43
|
+
if rows_or_data.is_a?(Array)
|
44
|
+
klass = type_class(type, sparse, initialize_values)
|
45
|
+
|
46
|
+
# Create the matrix from an array
|
47
|
+
from_array(rows_or_data, klass)
|
48
|
+
elsif rows_or_data.is_a?(Fixnum)
|
49
|
+
raise MatrixDimensionsError, "Must specify columns and rows" unless rows_or_data && cols
|
50
|
+
klass = type_class(type, sparse, initialize_values)
|
51
|
+
if klass.is_a?(Method) || klass.is_a?(Proc)
|
52
|
+
# A factory method was returned, call to build
|
53
|
+
@data = klass.call(rows_or_data, cols)
|
54
|
+
else
|
55
|
+
# A class was returned, create new
|
56
|
+
@data = klass.new(rows_or_data, cols)
|
57
|
+
|
58
|
+
setup_default_values(initialize_values)
|
59
|
+
end
|
60
|
+
else
|
61
|
+
# Passing in data directly
|
62
|
+
@data = rows_or_data
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def setup_default_values(initialize_values)
|
67
|
+
if initialize_values == :ones
|
68
|
+
@data.assign(1.0)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def [](rows, cols)
|
73
|
+
rows = convert_indicies(rows, self.rows)
|
74
|
+
cols = convert_indicies(cols, self.cols)
|
75
|
+
|
76
|
+
# Returns either the value in a cell or a subview
|
77
|
+
if rows && cols && rows.size == 1 && cols.size == 1 && rows.first.is_a?(Fixnum) && cols.first.is_a?(Fixnum)
|
78
|
+
@data.get(rows.first, cols.first)
|
79
|
+
else
|
80
|
+
# Get subview, also convert rows/cols to java arrays
|
81
|
+
self.class.new(@data.view_selection(rows && rows.to_java(:int), cols && cols.to_java(:int)))
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def []=(rows, cols, value)
|
86
|
+
rows = convert_indicies(rows, self.rows)
|
87
|
+
cols = convert_indicies(cols, self.cols)
|
88
|
+
|
89
|
+
# Set either the value in a cell or a subview with a matrix
|
90
|
+
if rows && cols && rows.size == 1 && cols.size == 1 && rows.first.is_a?(Fixnum) && cols.first.is_a?(Fixnum)
|
91
|
+
@data.set(rows.first, cols.first, value)
|
92
|
+
else
|
93
|
+
subview = @data.view_selection(rows && rows.to_java(:int), cols && cols.to_java(:int))
|
94
|
+
|
95
|
+
# Assign a single array or a nested array
|
96
|
+
if value.is_a?(Array)
|
97
|
+
value_rows, value_cols = array_dimensions(value)
|
98
|
+
|
99
|
+
# If one dimentional, and they want to set cols
|
100
|
+
if value_rows == 1 && subview.columns == 1
|
101
|
+
# Transpose so we can place an array vertically
|
102
|
+
subview = subview.view_dice
|
103
|
+
end
|
104
|
+
|
105
|
+
# Check to make sure the sizes match
|
106
|
+
if value_rows != subview.rows || value_cols != subview.columns
|
107
|
+
raise MatrixDimensionsError, "the array you are trying to assign is not the correct size"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
if value.is_a?(PMatrix)
|
112
|
+
value = value.data
|
113
|
+
end
|
114
|
+
|
115
|
+
if value.is_a?(Array)
|
116
|
+
assign_values(subview, value)
|
117
|
+
else
|
118
|
+
subview.assign(value)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
# Loop through each non-zero value, pass in the value, row, column
|
125
|
+
def each_non_zero(&block)
|
126
|
+
@data.for_each_non_zero do |row, col, value|
|
127
|
+
yield(value, row, col)
|
128
|
+
|
129
|
+
value
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
|
134
|
+
# Takes an array and assigns it to the right cells in the subview
|
135
|
+
def assign_values(subview, value)
|
136
|
+
unless value.first.is_a?(Array)
|
137
|
+
value = [value]
|
138
|
+
end
|
139
|
+
|
140
|
+
value.each_with_index do |row,row_index|
|
141
|
+
row.each_with_index do |val,col_index|
|
142
|
+
subview.set(row_index, col_index, val.to_java(:double))
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def dup
|
148
|
+
PMatrix.new(@data.copy)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module StairCar
|
2
|
+
module PMatrixTransforms
|
3
|
+
def transpose
|
4
|
+
return PMatrix.new(@data.view_dice.copy)
|
5
|
+
end
|
6
|
+
|
7
|
+
def ~
|
8
|
+
return transpose
|
9
|
+
end
|
10
|
+
|
11
|
+
def inv
|
12
|
+
algebra = Java::cern.colt.matrix.tdouble.algo.DenseDoubleAlgebra.new
|
13
|
+
begin
|
14
|
+
return PMatrix.new(algebra.inverse(@data))
|
15
|
+
rescue Java::JavaLang::IllegalArgumentException => e
|
16
|
+
if e.message == 'Matrix is singular.' || e.message == 'A is singular.'
|
17
|
+
raise InverseMatrixIsSignular, e.message
|
18
|
+
else
|
19
|
+
raise
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def map(&block)
|
25
|
+
dup.map!(&block)
|
26
|
+
end
|
27
|
+
|
28
|
+
def map!
|
29
|
+
result = self.each_with_index do |val,row,col|
|
30
|
+
self[row,col] = yield(val, row, col)
|
31
|
+
end
|
32
|
+
|
33
|
+
return self
|
34
|
+
end
|
35
|
+
|
36
|
+
def map_non_zero(&block)
|
37
|
+
dup.map_non_zero!(&block)
|
38
|
+
end
|
39
|
+
|
40
|
+
def map_non_zero!
|
41
|
+
result = @data.for_each_non_zero do |row,col,val|
|
42
|
+
yield(val, row, col)
|
43
|
+
end
|
44
|
+
|
45
|
+
PMatrix.new(result)
|
46
|
+
end
|
47
|
+
|
48
|
+
def count
|
49
|
+
count = 0
|
50
|
+
|
51
|
+
each do |val,row,col|
|
52
|
+
if yield(val,row,col)
|
53
|
+
count += 1
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
return count
|
58
|
+
end
|
59
|
+
|
60
|
+
# Converts the matrix into an array
|
61
|
+
def to_a
|
62
|
+
array = []
|
63
|
+
rows.times do |row|
|
64
|
+
col_array = []
|
65
|
+
cols.times do |col|
|
66
|
+
col_array << self[row,col]
|
67
|
+
end
|
68
|
+
array << col_array
|
69
|
+
end
|
70
|
+
|
71
|
+
return array
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# Lookup the type for the underlying matrix implementation
|
2
|
+
module StairCar
|
3
|
+
module PMatrixTypes
|
4
|
+
|
5
|
+
def type
|
6
|
+
klass = @data.class
|
7
|
+
if klass == Java::CernColtMatrixTdoubleImpl::DenseDoubleMatrix2D
|
8
|
+
return :double
|
9
|
+
elsif klass == Java::CernColtMatrixTdoubleImpl::SparseDoubleMatrix2D
|
10
|
+
return :double
|
11
|
+
elsif klass == Java::CernColtMatrixTfloatImpl::DenseFloatMatrix2D
|
12
|
+
return :float
|
13
|
+
elsif klass == Java::CernColtMatrixTfloatImpl::SparseFloatMatrix2D
|
14
|
+
return :float
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def sparse?
|
19
|
+
klass = @data.class
|
20
|
+
if klass == Java::CernColtMatrixTdoubleImpl::DenseDoubleMatrix2D
|
21
|
+
return false
|
22
|
+
elsif klass == Java::CernColtMatrixTdoubleImpl::SparseDoubleMatrix2D
|
23
|
+
return true
|
24
|
+
elsif klass == Java::CernColtMatrixTfloatImpl::DenseFloatMatrix2D
|
25
|
+
return false
|
26
|
+
elsif klass == Java::CernColtMatrixTfloatImpl::SparseFloatMatrix2D
|
27
|
+
return true
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
def type_class(type, sparse, initialize_values)
|
33
|
+
types = {
|
34
|
+
:zeros => {
|
35
|
+
false => {
|
36
|
+
# dense
|
37
|
+
:double => Java::cern.colt.matrix.tdouble.impl.DenseDoubleMatrix2D,
|
38
|
+
:float => Java::cern.colt.matrix.tfloat.impl.DenseFloatMatrix2D
|
39
|
+
},
|
40
|
+
true => {
|
41
|
+
# sparse
|
42
|
+
:double => Java::cern.colt.matrix.tdouble.impl.SparseDoubleMatrix2D,
|
43
|
+
# :double => Proc.new {|rows,cols| Java::cern.colt.matrix.tdouble.impl.SparseDoubleMatrix2D.new(rows,cols,10000.to_java(:int),0.0.to_java(:double),0.999999999.to_java(:double)) },
|
44
|
+
:float => Java::cern.colt.matrix.tfloat.impl.SparseFloatMatrix2D
|
45
|
+
}
|
46
|
+
},
|
47
|
+
:ones => {
|
48
|
+
false => {
|
49
|
+
# dense
|
50
|
+
:double => Java::cern.colt.matrix.tdouble.impl.DenseDoubleMatrix2D,
|
51
|
+
:float => Java::cern.colt.matrix.tfloat.impl.DenseFloatMatrix2D
|
52
|
+
},
|
53
|
+
true => {
|
54
|
+
# sparse
|
55
|
+
:double => Java::cern.colt.matrix.tdouble.impl.SparseDoubleMatrix2D,
|
56
|
+
:float => Java::cern.colt.matrix.tfloat.impl.SparseFloatMatrix2D
|
57
|
+
}
|
58
|
+
},
|
59
|
+
:rand => {
|
60
|
+
false => {
|
61
|
+
# dense
|
62
|
+
:double => Java::cern.colt.matrix.tdouble.DoubleFactory2D.dense.method(:random),
|
63
|
+
:float => Java::cern.colt.matrix.tfloat.FloatFactory2D.dense.method(:random)
|
64
|
+
},
|
65
|
+
true => {
|
66
|
+
# sparse
|
67
|
+
:double => Java::cern.colt.matrix.tdouble.DoubleFactory2D.sparse.method(:random),
|
68
|
+
:float => Java::cern.colt.matrix.tfloat.FloatFactory2D.sparse.method(:random)
|
69
|
+
}
|
70
|
+
},
|
71
|
+
:desc => {
|
72
|
+
false => {
|
73
|
+
# dense
|
74
|
+
:double => Java::cern.colt.matrix.tdouble.DoubleFactory2D.dense.method(:descending),
|
75
|
+
:float => Java::cern.colt.matrix.tfloat.FloatFactory2D.dense.method(:descending)
|
76
|
+
},
|
77
|
+
true => {
|
78
|
+
# sparse
|
79
|
+
:double => Java::cern.colt.matrix.tdouble.DoubleFactory2D.sparse.method(:descending),
|
80
|
+
:float => Java::cern.colt.matrix.tfloat.FloatFactory2D.sparse.method(:descending)
|
81
|
+
}
|
82
|
+
},
|
83
|
+
:asc => {
|
84
|
+
false => {
|
85
|
+
# dense
|
86
|
+
:double => Java::cern.colt.matrix.tdouble.DoubleFactory2D.dense.method(:ascending),
|
87
|
+
:float => Java::cern.colt.matrix.tfloat.FloatFactory2D.dense.method(:ascending)
|
88
|
+
},
|
89
|
+
true => {
|
90
|
+
# sparse
|
91
|
+
:double => Java::cern.colt.matrix.tdouble.DoubleFactory2D.sparse.method(:ascending),
|
92
|
+
:float => Java::cern.colt.matrix.tfloat.FloatFactory2D.sparse.method(:ascending)
|
93
|
+
}
|
94
|
+
}
|
95
|
+
}
|
96
|
+
|
97
|
+
klass = types[initialize_values][sparse][type]
|
98
|
+
|
99
|
+
unless klass
|
100
|
+
raise "Could not make a #{sparse ? 'sparse' : 'dense'} #{type} matrix"
|
101
|
+
end
|
102
|
+
|
103
|
+
return klass
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# Handles converting indicies into arrays of row or column offsets
|
2
|
+
module StairCar
|
3
|
+
module Indicies
|
4
|
+
def convert_indicies(index, max_index)
|
5
|
+
if index.is_a?(Fixnum)
|
6
|
+
if index < 0
|
7
|
+
return [max_index + index]
|
8
|
+
else
|
9
|
+
return [index]
|
10
|
+
end
|
11
|
+
elsif index.is_a?(Array)
|
12
|
+
# Map to indicies and convert into one array
|
13
|
+
return index.map {|i| convert_indicies(i, max_index) }.flatten
|
14
|
+
elsif index.is_a?(Range)
|
15
|
+
if index.end < 0
|
16
|
+
start = index.begin
|
17
|
+
new_end = max_index + index.end
|
18
|
+
|
19
|
+
# Recreate with the end value
|
20
|
+
if index.exclude_end?
|
21
|
+
index = (start...new_end)
|
22
|
+
else
|
23
|
+
index = (start..new_end)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
return index.to_a
|
28
|
+
elsif index.is_a?(NilClass)
|
29
|
+
return nil.to_java#convert_indicies(0...max_index, max_index)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module StairCar
|
2
|
+
module InitMethods
|
3
|
+
def from_array(array, klass)
|
4
|
+
rows, cols = array_dimensions(array)
|
5
|
+
|
6
|
+
if klass.is_a?(Method) || klass.is_a?(Proc)
|
7
|
+
@data = klass.call(rows, cols)
|
8
|
+
else
|
9
|
+
@data = klass.new(rows, cols)
|
10
|
+
end
|
11
|
+
self[nil,nil] = array
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
def array_dimensions(array)
|
16
|
+
if array.first.is_a?(Array)
|
17
|
+
# Nested array
|
18
|
+
rows = array.size
|
19
|
+
cols = array.first.size
|
20
|
+
else
|
21
|
+
# 1 dimensional array
|
22
|
+
cols = array.size
|
23
|
+
rows = 1
|
24
|
+
end
|
25
|
+
|
26
|
+
return rows, cols
|
27
|
+
end
|
28
|
+
|
29
|
+
module ClassMethods
|
30
|
+
def init_method_names
|
31
|
+
[true, false].each do |sparse|
|
32
|
+
[:double, :float].each do |type|
|
33
|
+
[:zeros, :ones, :rand, :desc, :asc].each do |initialize_values|
|
34
|
+
method_name = :"#{sparse ? 'sp' : ''}#{initialize_values}#{type == :float ? 'f' : ''}"
|
35
|
+
|
36
|
+
yield(method_name, sparse, type, initialize_values)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Also add float and double shortcuts
|
42
|
+
yield(:float, false, :float, :zeros)
|
43
|
+
yield(:double, false, :float, :zeros)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.included(klass)
|
48
|
+
klass.extend(ClassMethods)
|
49
|
+
klass.init_method_names do |method_name, sparse, type, initialize_values|
|
50
|
+
klass.define_singleton_method(method_name) do |cols, rows|
|
51
|
+
klass.new(cols, rows, type, sparse, initialize_values)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module StairCar
|
2
|
+
module Inspect
|
3
|
+
def inspect(screen_width = 80, rows_to_show=12)
|
4
|
+
lines = []
|
5
|
+
lines << "<#PMatrix(#{type}) #{rows}x#{cols} #{sparse? ? 'sparse' : 'dense'}>"
|
6
|
+
|
7
|
+
# To print cleanly, we should make the rows as big as the max width
|
8
|
+
# cell. We greedly loop through the columns and keep track of where
|
9
|
+
# we are.
|
10
|
+
formatter = Proc.new { |number| sprintf('%.3f', number).gsub(/[.]?0+$/, '') }
|
11
|
+
|
12
|
+
# Sometimes we only have a 1x1 matrix, and lookups will return a float
|
13
|
+
if rows == 1 && cols == 1
|
14
|
+
lines << formatter.call(self[0,0])
|
15
|
+
return lines.join("\n")
|
16
|
+
end
|
17
|
+
|
18
|
+
# Max rows, minus the last row
|
19
|
+
max_rows = [rows_to_show-1, rows].min
|
20
|
+
|
21
|
+
# We need to find the biggest cell we're going to need to display. So
|
22
|
+
# we grab the last row, then all of the other rows, by the last column,
|
23
|
+
# followed by all of the other columns. We go down columns until we go
|
24
|
+
# past the screen width.
|
25
|
+
cell_width = self[[-1,0...(max_rows-1)],[-1,0...(cols-1)]].max_char_width(formatter, max_rows, screen_width)
|
26
|
+
|
27
|
+
# Compute how many columns we can show in the screen area, min with cols
|
28
|
+
# incase we could fit more than we have
|
29
|
+
max_columns = (screen_width / cell_width).floor
|
30
|
+
if max_columns >= self.cols
|
31
|
+
# We can display all of the cells, set the screen width to the new width
|
32
|
+
hidden_columns = false
|
33
|
+
screen_width = (cell_width * self.cols) - 1
|
34
|
+
else
|
35
|
+
# We can't fit all cells, hide the columns
|
36
|
+
hidden_columns = true
|
37
|
+
max_columns = ((screen_width - 3 - cell_width) / cell_width).floor
|
38
|
+
end
|
39
|
+
|
40
|
+
# See if we need to hide rows
|
41
|
+
hidden_rows = (self.rows > max_rows)
|
42
|
+
|
43
|
+
# Add all rows, except the last
|
44
|
+
[max_rows, self.rows-1].min.times do |row|
|
45
|
+
lines << row_line_text(row, formatter, max_columns, screen_width, cell_width, hidden_columns)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Put a line in saying how rows we've hidden
|
49
|
+
if hidden_rows
|
50
|
+
lines << "#{self.rows - max_rows} rows".center(screen_width, '.')
|
51
|
+
end
|
52
|
+
|
53
|
+
# Say how many rows we're leaving out
|
54
|
+
if hidden_columns
|
55
|
+
# Go in and replace the .'s with text
|
56
|
+
message = "#{self.cols - max_columns} cols".center(max_rows, '.')
|
57
|
+
|
58
|
+
# convert message to an array
|
59
|
+
message = message.split(//)
|
60
|
+
(max_rows-1).times do |row|
|
61
|
+
next_char = message.slice!(0)
|
62
|
+
break unless next_char
|
63
|
+
lines[row+1][(cell_width + 2) * -1] = next_char
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Add last row
|
68
|
+
lines << row_line_text(-1, formatter, max_columns, screen_width, cell_width, hidden_columns)
|
69
|
+
|
70
|
+
return lines.join("\n")
|
71
|
+
end
|
72
|
+
|
73
|
+
# Figure out how big the cells should be, stop early when we reach the
|
74
|
+
# end of the screen
|
75
|
+
def max_char_width(formatter, max_rows, max_char_width)
|
76
|
+
max_cell_width = 0
|
77
|
+
rows.times do |row|
|
78
|
+
cols.times do |column|
|
79
|
+
cell_value = self[row, column]
|
80
|
+
width = formatter.call(cell_value).size + 1
|
81
|
+
|
82
|
+
# Track the biggest cell width we've seen so far
|
83
|
+
max_cell_width = width if width > max_cell_width
|
84
|
+
|
85
|
+
if max_cell_width * column > max_char_width
|
86
|
+
# We have now passed the width of the screen or section, break
|
87
|
+
# to next row
|
88
|
+
break
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
return max_cell_width
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
def row_line_text(row_number, formatter, max_columns, screen_width, cell_width, hidden_columns)
|
98
|
+
line = ''
|
99
|
+
[self.cols-1, max_columns].min.times do |column|
|
100
|
+
cell_value = self[row_number, column]
|
101
|
+
line << formatter.call(cell_value).ljust(cell_width)
|
102
|
+
end
|
103
|
+
|
104
|
+
last_cell = formatter.call(self[row_number, -1]).ljust(cell_width-1)
|
105
|
+
padding_size = screen_width - line.size - last_cell.size - 1
|
106
|
+
line << ('.' * padding_size) + ' ' if hidden_columns
|
107
|
+
|
108
|
+
line << last_cell
|
109
|
+
|
110
|
+
return line
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module StairCar
|
2
|
+
module Iteration
|
3
|
+
def each(&block)
|
4
|
+
rows.times do |row|
|
5
|
+
cols.times do |col|
|
6
|
+
yield(self[row,col])
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def each_with_index(&block)
|
12
|
+
rows.times do |row|
|
13
|
+
cols.times do |col|
|
14
|
+
yield(self[row,col], row, col)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def each_column
|
20
|
+
cols.times do |col_number|
|
21
|
+
yield(self[nil,col_number],col_number)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def each_row
|
26
|
+
rows.times do |row_number|
|
27
|
+
yield(self[row_number,nil],row_number)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module StairCar
|
2
|
+
module UMatrixCompare
|
3
|
+
# def >(val)
|
4
|
+
# map {|v| (v > val) ? 1 : 0 }
|
5
|
+
# end
|
6
|
+
#
|
7
|
+
# def >=(val)
|
8
|
+
# map {|v| (v >= val) ? 1 : 0 }
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# def <(val)
|
12
|
+
# map {|v| (v < val) ? 1 : 0 }
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# def <=(val)
|
16
|
+
# map {|v| (v <= val) ? 1 : 0 }
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# def find(matrix)
|
20
|
+
#
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# def any?
|
24
|
+
# @data.cardinality > 0
|
25
|
+
# end
|
26
|
+
|
27
|
+
|
28
|
+
# Compares this matrix to another to see if they are the same (in values)
|
29
|
+
def ==(matrix2)
|
30
|
+
self.data.equalsContent(matrix2.data)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|