flex_array 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/lib/flex_array.rb +19 -13
- data/lib/flex_array/array.rb +19 -19
- data/lib/flex_array/flex_array_append.rb +11 -11
- data/lib/flex_array/flex_array_each.rb +390 -53
- data/lib/flex_array/flex_array_forever.rb +18 -0
- data/lib/flex_array/flex_array_index.rb +13 -11
- data/lib/flex_array/flex_array_new.rb +30 -34
- data/lib/flex_array/flex_array_process.rb +42 -37
- data/lib/flex_array/flex_array_reshape.rb +13 -21
- data/lib/flex_array/flex_array_transpose.rb +15 -2
- data/lib/flex_array/flex_array_validate.rb +11 -11
- data/lib/flex_array/integer.rb +2 -4
- data/lib/flex_array/object.rb +2 -4
- data/lib/flex_array/range.rb +10 -14
- data/lib/flex_array/spec_array.rb +47 -0
- data/lib/flex_array/spec_component.rb +11 -11
- data/rakefile.rb +22 -2
- data/reek.txt +2 -29
- data/tests/array_test.rb +19 -24
- data/tests/flex_array_append_test.rb +10 -10
- data/tests/flex_array_each_test.rb +466 -93
- data/tests/flex_array_index_test.rb +55 -57
- data/tests/flex_array_new_test.rb +21 -21
- data/tests/flex_array_reshape_test.rb +10 -17
- data/tests/flex_array_test.rb +20 -12
- data/tests/flex_array_transpose_test.rb +33 -6
- data/tests/integer_test.rb +1 -1
- data/tests/object_test.rb +7 -7
- data/tests/range_test.rb +9 -8
- data/tests/spec_array_test.rb +26 -0
- data/tests/spec_component_test.rb +19 -16
- metadata +6 -2
data/lib/flex_array/integer.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require_relative 'spec_component'
|
2
|
-
|
3
1
|
#Extensions to Integer needed to support flex array.
|
4
2
|
class Integer
|
5
3
|
#Convert this integer to a limits component.
|
@@ -14,7 +12,7 @@ class Integer
|
|
14
12
|
fail ArgumentError, "Invalid flex array dimension: #{self.inspect}"
|
15
13
|
end
|
16
14
|
end
|
17
|
-
|
15
|
+
|
18
16
|
#Convert this integer to an range index against the spec.
|
19
17
|
#<br>Parameters
|
20
18
|
#* spec - The spec component used to validate this index.
|
@@ -24,7 +22,7 @@ class Integer
|
|
24
22
|
#* IndexError if the range is not valid.
|
25
23
|
def to_index_range(spec)
|
26
24
|
alter_ego = (self >= 0) ? self : (spec.max + self + 1)
|
27
|
-
|
25
|
+
|
28
26
|
if spec === alter_ego
|
29
27
|
alter_ego..alter_ego
|
30
28
|
else
|
data/lib/flex_array/object.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require_relative 'spec_component'
|
2
|
-
|
3
1
|
#Extensions to Object needed to support flex array.
|
4
2
|
class Object
|
5
3
|
#Fail with message since the array dimension is invalid.
|
@@ -10,7 +8,7 @@ class Object
|
|
10
8
|
def to_spec_component(_stride)
|
11
9
|
fail ArgumentError, "Invalid flex array dimension: #{self.inspect}"
|
12
10
|
end
|
13
|
-
|
11
|
+
|
14
12
|
#Convert this object to an range index against the spec.
|
15
13
|
#<br>Parameters
|
16
14
|
#* spec - The spec component used to validate this index.
|
@@ -25,5 +23,5 @@ class Object
|
|
25
23
|
fail IndexError, "Invalid subscript: #{self.inspect}"
|
26
24
|
end
|
27
25
|
end
|
28
|
-
|
26
|
+
|
29
27
|
end
|
data/lib/flex_array/range.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
require_relative 'spec_component'
|
2
|
-
|
3
1
|
#Extensions to Range needed to support flex array.
|
4
2
|
class Range
|
5
3
|
#Convert this integer to a limits component.
|
@@ -9,7 +7,7 @@ class Range
|
|
9
7
|
#* A SpecComponent object with the same range as self.
|
10
8
|
def to_spec_component(stride)
|
11
9
|
min = self.min
|
12
|
-
|
10
|
+
|
13
11
|
if self == (0...0)
|
14
12
|
SpecComponent.new(0...0, stride)
|
15
13
|
elsif !self.none? && min.is_a?(Integer) && (min >= 0) && self.max.is_a?(Integer)
|
@@ -18,7 +16,7 @@ class Range
|
|
18
16
|
fail ArgumentError, "Invalid flex array dimension: #{self.inspect}"
|
19
17
|
end
|
20
18
|
end
|
21
|
-
|
19
|
+
|
22
20
|
#Convert this range to an range index against the spec.
|
23
21
|
#<br>Parameters
|
24
22
|
#* spec - The spec component used to validate this index.
|
@@ -27,16 +25,14 @@ class Range
|
|
27
25
|
#<br>Exceptions
|
28
26
|
#* IndexError if the range is not valid.
|
29
27
|
def to_index_range(spec)
|
30
|
-
self_min, self_max, spec_max = self.
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
if spec === alter_ego.min && spec === alter_ego.max
|
39
|
-
alter_ego
|
28
|
+
self_min, self_max, spec_max = self.begin, self.end, spec.max
|
29
|
+
self_max -= 1 if self_max > 0 && self.exclude_end?
|
30
|
+
|
31
|
+
self_min = spec_max + self_min + 1 if self_min < 0
|
32
|
+
self_max = spec_max + self_max + 1 if self_max < 0
|
33
|
+
|
34
|
+
if spec === self_min && spec === self_max && self_min < self_max
|
35
|
+
self_min..self_max
|
40
36
|
else
|
41
37
|
fail IndexError, "Subscript out of range: #{self.inspect}"
|
42
38
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
#This helper class encapsulates an array of flex array spec components.
|
2
|
+
class SpecArray < Array
|
3
|
+
#The number of elements defined by this array specification.
|
4
|
+
attr_reader :spec_count
|
5
|
+
|
6
|
+
#The number of dimensions specified by this specification
|
7
|
+
alias spec_dimensions length
|
8
|
+
|
9
|
+
#Create a flex array specification.
|
10
|
+
#<br>Parameters
|
11
|
+
#* array_specs - The specification of the flex array subscript limits.
|
12
|
+
# These can either be an array of containing integers, in which case
|
13
|
+
# the limits are 0...n or they can be ranges, in which case the
|
14
|
+
# limits are those of the range.
|
15
|
+
def initialize(array_specs)
|
16
|
+
super(0)
|
17
|
+
@spec_count = 1
|
18
|
+
|
19
|
+
#Parse the array limits.
|
20
|
+
array_specs.reverse_each do |spec|
|
21
|
+
self.insert(0, spec.to_spec_component(@spec_count))
|
22
|
+
@spec_count *= self[0].span
|
23
|
+
end
|
24
|
+
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
#Is this array specification transposed in any way?
|
29
|
+
def transposed?
|
30
|
+
check = 1
|
31
|
+
|
32
|
+
self.reverse_each do |component|
|
33
|
+
return true unless check == component.stride
|
34
|
+
check *= component.span
|
35
|
+
end
|
36
|
+
|
37
|
+
false
|
38
|
+
end
|
39
|
+
|
40
|
+
#Enlarge the flex array along its first dimension.
|
41
|
+
def enlarge(growth)
|
42
|
+
self[0].enlarge(growth)
|
43
|
+
|
44
|
+
#Compute the new size.
|
45
|
+
@spec_count = self.inject(1) {|product, element| product*element.span}
|
46
|
+
end
|
47
|
+
end
|
@@ -2,11 +2,11 @@
|
|
2
2
|
class SpecComponent
|
3
3
|
#The range of acceptable values for this limit.
|
4
4
|
attr_reader :range
|
5
|
-
|
5
|
+
|
6
6
|
#The stride of this array dimension. That is, for each step in this
|
7
7
|
#dimension, how many steps are required in the low level array?
|
8
8
|
attr_reader :stride
|
9
|
-
|
9
|
+
|
10
10
|
#Create a limits component from its constituent data.
|
11
11
|
#<br>Parameters
|
12
12
|
#* range - the range of values for this index limit.
|
@@ -14,34 +14,34 @@ class SpecComponent
|
|
14
14
|
def initialize(range, stride)
|
15
15
|
@range, @stride = range, stride
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
#Forward '=== value' to the range.
|
19
19
|
def ===(value)
|
20
20
|
@range === value
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
#Limits are equal if their ranges are equal.
|
24
24
|
#<br>Returns
|
25
25
|
#* true if the spec components have equal ranges.
|
26
26
|
def ==(other)
|
27
27
|
@range == other.range
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
#Forward 'min' to the range.
|
31
31
|
def min
|
32
32
|
@range.min
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
#Forward 'max' to the range.
|
36
|
-
def max
|
36
|
+
def max
|
37
37
|
@range.max
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
#Forward 'each' and the block to the range.
|
41
41
|
def each(&block)
|
42
42
|
@range.each(&block)
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
#Compute the span of indexes in this limit component.
|
46
46
|
#<br>Returns
|
47
47
|
#* The span of the range or zero if there is none.
|
@@ -52,7 +52,7 @@ class SpecComponent
|
|
52
52
|
@range.max - @range.min + 1
|
53
53
|
end
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
56
|
#Enlarge the range of this spec by the growth term.
|
57
57
|
def enlarge(growth)
|
58
58
|
if @range.none?
|
@@ -61,7 +61,7 @@ class SpecComponent
|
|
61
61
|
@range = (@range.min)..(@range.max + growth)
|
62
62
|
end
|
63
63
|
end
|
64
|
-
|
64
|
+
|
65
65
|
#Compute the step required for the index value.
|
66
66
|
#<br>Returns
|
67
67
|
#* The number of array cells to be skipped for this index.
|
data/rakefile.rb
CHANGED
@@ -4,7 +4,7 @@ require 'rdoc/task'
|
|
4
4
|
|
5
5
|
RDoc::Task.new do |rdoc|
|
6
6
|
rdoc.rdoc_dir = "rdoc"
|
7
|
-
rdoc.rdoc_files = ["lib/flex_array.rb",
|
7
|
+
rdoc.rdoc_files = ["lib/flex_array.rb",
|
8
8
|
"lib/flex_array/flex_array_new.rb",
|
9
9
|
"lib/flex_array/flex_array_index.rb",
|
10
10
|
"lib/flex_array/flex_array_each.rb",
|
@@ -13,10 +13,12 @@ RDoc::Task.new do |rdoc|
|
|
13
13
|
"lib/flex_array/flex_array_transpose.rb",
|
14
14
|
"lib/flex_array/flex_array_process.rb",
|
15
15
|
"lib/flex_array/flex_array_validate.rb",
|
16
|
+
"lib/flex_array/flex_array_forever.rb",
|
16
17
|
"lib/flex_array/object.rb",
|
17
18
|
"lib/flex_array/integer.rb",
|
18
19
|
"lib/flex_array/range.rb",
|
19
20
|
"lib/flex_array/array.rb",
|
21
|
+
"lib/flex_array/spec_array.rb",
|
20
22
|
"lib/flex_array/spec_component.rb",
|
21
23
|
"license.txt", "README.txt"]
|
22
24
|
rdoc.options << '--visibility' << 'private'
|
@@ -24,6 +26,7 @@ end
|
|
24
26
|
|
25
27
|
Rake::TestTask.new do |t|
|
26
28
|
t.test_files = ["tests/spec_component_test.rb",
|
29
|
+
"tests/spec_array_test.rb",
|
27
30
|
"tests/object_test.rb",
|
28
31
|
"tests/integer_test.rb",
|
29
32
|
"tests/range_test.rb",
|
@@ -40,5 +43,22 @@ Rake::TestTask.new do |t|
|
|
40
43
|
end
|
41
44
|
|
42
45
|
task :reek do |t|
|
43
|
-
`reek lib > reek.txt`
|
46
|
+
`reek --no-color lib > reek.txt`
|
47
|
+
end
|
48
|
+
|
49
|
+
def eval_puts(str)
|
50
|
+
puts str
|
51
|
+
eval str
|
52
|
+
end
|
53
|
+
|
54
|
+
task :console do
|
55
|
+
require 'irb'
|
56
|
+
require 'irb/completion'
|
57
|
+
require_relative 'lib/flex_array'
|
58
|
+
eval_puts "@a = FlexArray.new([2,3,4]) {|i| i.clone}"
|
59
|
+
eval_puts "@b = FlexArray.new([2,3,4]) {|i| (i[0]+i[2])*(i[1] + i[2])}"
|
60
|
+
eval_puts "@c = FlexArray.new([0,3])"
|
61
|
+
eval_puts "@d = FlexArray.new([3,3]) {|i| i[0]*3 + i[1]}"
|
62
|
+
ARGV.clear
|
63
|
+
IRB.start
|
44
64
|
end
|
data/reek.txt
CHANGED
@@ -1,29 +1,2 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
lib/flex_array/flex_array_append.rb -- 0 warnings
|
4
|
-
lib/flex_array/flex_array_each.rb -- 11 warnings:
|
5
|
-
[91, 94]:FlexArray#_each_raw calls process_indexes(indexes) twice (DuplicateMethodCall)
|
6
|
-
[94]:FlexArray#_each_raw contains iterators nested 2 deep (NestedIterators)
|
7
|
-
[41, 44]:FlexArray#cycle calls @array_data[posn] twice (DuplicateMethodCall)
|
8
|
-
[41, 44]:FlexArray#cycle calls process_indexes(indexes) twice (DuplicateMethodCall)
|
9
|
-
[44]:FlexArray#cycle contains iterators nested 3 deep (NestedIterators)
|
10
|
-
[18, 21]:FlexArray#each calls @array_data[posn] twice (DuplicateMethodCall)
|
11
|
-
[18, 21]:FlexArray#each calls process_indexes(indexes) twice (DuplicateMethodCall)
|
12
|
-
[21]:FlexArray#each contains iterators nested 2 deep (NestedIterators)
|
13
|
-
[65, 68]:FlexArray#each_with_index calls @array_data[posn] twice (DuplicateMethodCall)
|
14
|
-
[65, 68]:FlexArray#each_with_index calls process_indexes(indexes) twice (DuplicateMethodCall)
|
15
|
-
[68]:FlexArray#each_with_index contains iterators nested 2 deep (NestedIterators)
|
16
|
-
lib/flex_array/flex_array_index.rb -- 0 warnings
|
17
|
-
lib/flex_array/flex_array_new.rb -- 0 warnings
|
18
|
-
lib/flex_array/flex_array_process.rb -- 3 warnings:
|
19
|
-
[89]:FlexArray#process_all_worker has approx 7 statements (TooManyStatements)
|
20
|
-
[47]:FlexArray#process_indexes_worker has 4 parameters (LongParameterList)
|
21
|
-
[47]:FlexArray#process_indexes_worker has approx 9 statements (TooManyStatements)
|
22
|
-
lib/flex_array/flex_array_reshape.rb -- 0 warnings
|
23
|
-
lib/flex_array/flex_array_transpose.rb -- 0 warnings
|
24
|
-
lib/flex_array/flex_array_validate.rb -- 0 warnings
|
25
|
-
lib/flex_array/integer.rb -- 0 warnings
|
26
|
-
lib/flex_array/object.rb -- 0 warnings
|
27
|
-
lib/flex_array/range.rb -- 0 warnings
|
28
|
-
lib/flex_array/spec_component.rb -- 0 warnings
|
29
|
-
14 total warnings
|
1
|
+
|
2
|
+
0 total warnings
|
data/tests/array_test.rb
CHANGED
@@ -1,24 +1,24 @@
|
|
1
|
-
require_relative '../lib/flex_array
|
1
|
+
require_relative '../lib/flex_array'
|
2
2
|
require 'minitest/autorun'
|
3
3
|
|
4
4
|
class ArrayTester < MiniTest::Unit::TestCase
|
5
5
|
$do_this_only_one_time = "" unless defined? $do_this_only_one_time
|
6
|
-
|
6
|
+
|
7
7
|
def initialize(*all)
|
8
8
|
if $do_this_only_one_time != __FILE__
|
9
9
|
puts
|
10
|
-
puts "Running test file: #{File.split(__FILE__)[1]}"
|
10
|
+
puts "Running test file: #{File.split(__FILE__)[1]}"
|
11
11
|
$do_this_only_one_time = __FILE__
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
super(*all)
|
15
15
|
end
|
16
16
|
|
17
17
|
def test_the_limits_method
|
18
18
|
test = [1,2,3,4,5,6]
|
19
|
-
assert_equal([0...6], test.limits)
|
19
|
+
assert_equal([0...6], test.limits)
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
def test_the_array_specs_method
|
23
23
|
test = [1,2,3,4,5,6].array_specs
|
24
24
|
assert_equal(1, test.length)
|
@@ -26,37 +26,32 @@ class ArrayTester < MiniTest::Unit::TestCase
|
|
26
26
|
assert_equal(0...6, test[0].range)
|
27
27
|
assert_equal(1, test[0].stride)
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
def test_the_array_data_method
|
31
31
|
test = [1,2,3,4,5,6]
|
32
32
|
assert_equal(test, test.array_data)
|
33
33
|
assert_equal(test.object_id, test.array_data.object_id)
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
def test_the_count_method
|
37
37
|
test = [1,2,3,4,5,6]
|
38
38
|
assert_equal(test.count, 6)
|
39
39
|
assert_equal(test.count, test.length)
|
40
40
|
end
|
41
|
-
|
41
|
+
|
42
42
|
def test_the_to_index_range_method
|
43
43
|
spec = SpecComponent.new(0...10, 1)
|
44
|
-
|
45
|
-
assert_equal(0
|
46
|
-
assert_equal(9
|
47
|
-
assert_equal(0
|
48
|
-
|
49
|
-
assert_equal(0
|
50
|
-
assert_equal(1
|
51
|
-
assert_equal(8
|
52
|
-
|
53
|
-
assert_raises(IndexError) { [0,9,0].to_index_range(spec) }
|
54
|
-
assert_raises(IndexError) { [9,0].to_index_range(spec) }
|
55
|
-
assert_raises(IndexError) { [-1,-2].to_index_range(spec) }
|
44
|
+
|
45
|
+
assert_equal([0], [0].to_index_range(spec))
|
46
|
+
assert_equal([9,9], [9,9].to_index_range(spec))
|
47
|
+
assert_equal([0,9], [0,9].to_index_range(spec))
|
48
|
+
|
49
|
+
assert_equal([0, 9], [0,-1].to_index_range(spec))
|
50
|
+
assert_equal([1, 8], [1,-2].to_index_range(spec))
|
51
|
+
assert_equal([8, 9], [-2,-1].to_index_range(spec))
|
52
|
+
|
56
53
|
assert_raises(IndexError) { [0,10].to_index_range(spec) }
|
57
|
-
|
58
|
-
assert_raises(TypeError) { [].to_index_range(spec) }
|
59
|
-
assert_raises(TypeError) { [0].to_index_range(spec) }
|
54
|
+
|
60
55
|
assert_raises(TypeError) { [:one, :two].to_index_range(spec) }
|
61
56
|
end
|
62
57
|
end
|
@@ -3,14 +3,14 @@ require 'minitest/autorun'
|
|
3
3
|
|
4
4
|
class FlexArrayAppendTester < MiniTest::Unit::TestCase
|
5
5
|
$do_this_only_one_time = "" unless defined? $do_this_only_one_time
|
6
|
-
|
6
|
+
|
7
7
|
def initialize(*all)
|
8
8
|
if $do_this_only_one_time != __FILE__
|
9
9
|
puts
|
10
|
-
puts "Running test file: #{File.split(__FILE__)[1]}"
|
10
|
+
puts "Running test file: #{File.split(__FILE__)[1]}"
|
11
11
|
$do_this_only_one_time = __FILE__
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
super(*all)
|
15
15
|
end
|
16
16
|
|
@@ -18,13 +18,13 @@ class FlexArrayAppendTester < MiniTest::Unit::TestCase
|
|
18
18
|
f = FlexArray.new([1,3], "Title")
|
19
19
|
assert_equal(2, f.dimensions)
|
20
20
|
assert_equal([0...1, 0...3], f.limits)
|
21
|
-
|
21
|
+
|
22
22
|
f << [1,2,3]
|
23
23
|
assert_equal(2, f.dimensions)
|
24
24
|
assert_equal([0..1, 0...3], f.limits)
|
25
25
|
a = ["Title","Title","Title",1,2,3]
|
26
26
|
assert_equal(a, f.array_data)
|
27
|
-
|
27
|
+
|
28
28
|
g = FlexArray.new_from_array([4,5,6])
|
29
29
|
f << g
|
30
30
|
assert_equal(2, f.dimensions)
|
@@ -37,7 +37,7 @@ class FlexArrayAppendTester < MiniTest::Unit::TestCase
|
|
37
37
|
f = FlexArray.new([0,3])
|
38
38
|
assert_equal(2, f.dimensions)
|
39
39
|
assert_equal([0...0, 0...3], f.limits)
|
40
|
-
|
40
|
+
|
41
41
|
f << [1,2,3]
|
42
42
|
assert_equal(2, f.dimensions)
|
43
43
|
assert_equal([0...1, 0...3], f.limits)
|
@@ -55,11 +55,11 @@ class FlexArrayAppendTester < MiniTest::Unit::TestCase
|
|
55
55
|
f = FlexArray.new([1,3], "Title")
|
56
56
|
assert_raises(ArgumentError) { f << [3,4] }
|
57
57
|
assert_raises(ArgumentError) { f << [1,2,3,4] }
|
58
|
-
|
58
|
+
|
59
59
|
g = FlexArray.new([1,2], "Title")
|
60
60
|
assert_raises(ArgumentError) { f << g }
|
61
61
|
end
|
62
|
-
|
62
|
+
|
63
63
|
def test_the_copy_data_method
|
64
64
|
f = FlexArray.new([2,3], "Title")
|
65
65
|
g = FlexArray.new([2,3], "Fight")
|
@@ -67,12 +67,12 @@ class FlexArrayAppendTester < MiniTest::Unit::TestCase
|
|
67
67
|
assert_equal(f.array_data, g.array_data)
|
68
68
|
assert(f.array_data.object_id != g.array_data.object_id)
|
69
69
|
end
|
70
|
-
|
70
|
+
|
71
71
|
def test_copy_data_method_failures
|
72
72
|
f = FlexArray.new([2,3], "Title")
|
73
73
|
g = FlexArray.new([2,4], "Fight")
|
74
74
|
assert_raises(ArgumentError) { f.copy_data(g) }
|
75
|
-
|
75
|
+
|
76
76
|
g = FlexArray.new([1,3], "Fight")
|
77
77
|
assert_raises(ArgumentError) { f.copy_data(g) }
|
78
78
|
|