stair_car 0.0.1
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.
- 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
|