flex_array 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,71 @@
1
+ #This helper class encapsulates a single component of the flex array spec.
2
+ class SpecComponent
3
+ #The range of acceptable values for this limit.
4
+ attr_reader :range
5
+
6
+ #The stride of this array dimension. That is, for each step in this
7
+ #dimension, how many steps are required in the low level array?
8
+ attr_reader :stride
9
+
10
+ #Create a limits component from its constituent data.
11
+ #<br>Parameters
12
+ #* range - the range of values for this index limit.
13
+ #* stride - the number of cells separating data with adjacent indexes.
14
+ def initialize(range, stride)
15
+ @range, @stride = range, stride
16
+ end
17
+
18
+ #Forward '=== value' to the range.
19
+ def ===(value)
20
+ @range === value
21
+ end
22
+
23
+ #Limits are equal if their ranges are equal.
24
+ #<br>Returns
25
+ #* true if the spec components have equal ranges.
26
+ def ==(other)
27
+ @range == other.range
28
+ end
29
+
30
+ #Forward 'min' to the range.
31
+ def min
32
+ @range.min
33
+ end
34
+
35
+ #Forward 'max' to the range.
36
+ def max
37
+ @range.max
38
+ end
39
+
40
+ #Forward 'each' and the block to the range.
41
+ def each(&block)
42
+ @range.each(&block)
43
+ end
44
+
45
+ #Compute the span of indexes in this limit component.
46
+ #<br>Returns
47
+ #* The span of the range or zero if there is none.
48
+ def span
49
+ if @range.none?
50
+ 0
51
+ else
52
+ @range.max - @range.min + 1
53
+ end
54
+ end
55
+
56
+ #Enlarge the range of this spec by the growth term.
57
+ def enlarge(growth)
58
+ if @range.none?
59
+ @range = 0...growth
60
+ else
61
+ @range = (@range.min)..(@range.max + growth)
62
+ end
63
+ end
64
+
65
+ #Compute the step required for the index value.
66
+ #<br>Returns
67
+ #* The number of array cells to be skipped for this index.
68
+ def index_step(index)
69
+ (index - @range.min) * @stride
70
+ end
71
+ end
data/lib/flex_array.rb ADDED
@@ -0,0 +1,89 @@
1
+ require 'in_array'
2
+ require_relative 'flex_array/spec_component'
3
+ require_relative 'flex_array/object'
4
+ require_relative 'flex_array/integer'
5
+ require_relative 'flex_array/range'
6
+ require_relative 'flex_array/array'
7
+
8
+ require_relative 'flex_array/flex_array_new'
9
+ require_relative 'flex_array/flex_array_index'
10
+ require_relative 'flex_array/flex_array_append'
11
+ require_relative 'flex_array/flex_array_reshape'
12
+ require_relative 'flex_array/flex_array_transpose'
13
+ require_relative 'flex_array/flex_array_each'
14
+ require_relative 'flex_array/flex_array_validate'
15
+ require_relative 'flex_array/flex_array_process'
16
+
17
+ #\FlexArray - A flexible array class.
18
+ #* flex_array.rb - The root file that gathers up all the flex array parts.
19
+ class FlexArray
20
+ include Enumerable
21
+ include InArrayAlready
22
+
23
+ #The version of this class.
24
+ #<br>Returns
25
+ #* A version string; <major>.<minor>.<step>
26
+ def self.version
27
+ '0.2.0'
28
+ end
29
+
30
+ #The version of the class of this instance.
31
+ #<br>Returns
32
+ #* A version string; <major>.<minor>.<step>
33
+ def version
34
+ self.class.version
35
+ end
36
+
37
+ #The array specifications. An array of spec components.
38
+ attr_accessor :array_specs
39
+
40
+ #The underlying array data used by the flex array.
41
+ attr_accessor :array_data
42
+
43
+ #The total number of elements in this array.
44
+ attr_reader :count
45
+
46
+ #The number of dimensions in this array.
47
+ attr_reader :dimensions
48
+
49
+ #Get the limits of the subscripts of the flex array.
50
+ #<br>Returns
51
+ #* An array of dimension limits ranges.
52
+ def limits
53
+ Array.new(@dimensions) {|dimension| @array_specs[dimension].range}
54
+ end
55
+
56
+ #Return this flex array as a flex array!
57
+ #<br>Returns
58
+ #* A flex array -- self
59
+ def to_flex_array
60
+ self
61
+ end
62
+
63
+ #Are these FlexArrays equal?
64
+ #<br>Parameters
65
+ #* other - The object being tested for equality.
66
+ #<br>Returns
67
+ #* true if the flex arrays are equal shape and data.
68
+ def ==(other)
69
+ self.compatible?(other) && @array_data == other.array_data
70
+ end
71
+
72
+ #Make FlexArrays comparable.
73
+ #<br>Parameters
74
+ #* other - The object being tested for compariositality.
75
+ #<br>Returns
76
+ #* 1 if self > other
77
+ #* 0 if self = other
78
+ #* -1 if self < other
79
+ def <=>(other)
80
+ @array_data <=> other.array_data
81
+ end
82
+
83
+ #Update the count and dimensions variables
84
+ def update_count_and_dimensions
85
+ @dimensions = @array_specs.length
86
+ @count = @array_data.length
87
+ self
88
+ end
89
+ end
data/license.txt ADDED
@@ -0,0 +1,21 @@
1
+ === The MIT License (MIT).
2
+
3
+ Copyright (c) 2014 Peter Camilleri
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/rakefile.rb ADDED
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env rake
2
+ require 'rake/testtask'
3
+ require 'rdoc/task'
4
+
5
+ RDoc::Task.new do |rdoc|
6
+ rdoc.rdoc_dir = "rdoc"
7
+ rdoc.rdoc_files = ["lib/flex_array.rb",
8
+ "lib/flex_array/flex_array_new.rb",
9
+ "lib/flex_array/flex_array_index.rb",
10
+ "lib/flex_array/flex_array_each.rb",
11
+ "lib/flex_array/flex_array_reshape.rb",
12
+ "lib/flex_array/flex_array_append.rb",
13
+ "lib/flex_array/flex_array_transpose.rb",
14
+ "lib/flex_array/flex_array_process.rb",
15
+ "lib/flex_array/flex_array_validate.rb",
16
+ "lib/flex_array/object.rb",
17
+ "lib/flex_array/integer.rb",
18
+ "lib/flex_array/range.rb",
19
+ "lib/flex_array/array.rb",
20
+ "lib/flex_array/spec_component.rb",
21
+ "license.txt", "README.txt"]
22
+ rdoc.options << '--visibility' << 'private'
23
+ end
24
+
25
+ Rake::TestTask.new do |t|
26
+ t.test_files = ["tests/spec_component_test.rb",
27
+ "tests/object_test.rb",
28
+ "tests/integer_test.rb",
29
+ "tests/range_test.rb",
30
+ "tests/array_test.rb",
31
+ "tests/flex_array_new_test.rb",
32
+ "tests/flex_array_index_test.rb",
33
+ "tests/flex_array_each_test.rb",
34
+ "tests/flex_array_reshape_test.rb",
35
+ "tests/flex_array_append_test.rb",
36
+ "tests/flex_array_transpose_test.rb",
37
+ "tests/flex_array_validate_test.rb",
38
+ "tests/flex_array_test.rb"]
39
+ t.verbose = false
40
+ end
41
+
42
+ task :reek do |t|
43
+ `reek lib > reek.txt`
44
+ end
data/readme.txt ADDED
@@ -0,0 +1,2 @@
1
+ This project contains the Ruby FlexArray gem. A gem used to facilitate the
2
+ creation and processing of multi-dimensional arrays in a flexible manner.
data/reek.txt ADDED
@@ -0,0 +1,29 @@
1
+ lib/flex_array.rb -- 0 warnings
2
+ lib/flex_array/array.rb -- 0 warnings
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
@@ -0,0 +1,62 @@
1
+ require_relative '../lib/flex_array/array'
2
+ require 'minitest/autorun'
3
+
4
+ class ArrayTester < MiniTest::Unit::TestCase
5
+ $do_this_only_one_time = "" unless defined? $do_this_only_one_time
6
+
7
+ def initialize(*all)
8
+ if $do_this_only_one_time != __FILE__
9
+ puts
10
+ puts "Running test file: #{File.split(__FILE__)[1]}"
11
+ $do_this_only_one_time = __FILE__
12
+ end
13
+
14
+ super(*all)
15
+ end
16
+
17
+ def test_the_limits_method
18
+ test = [1,2,3,4,5,6]
19
+ assert_equal([0...6], test.limits)
20
+ end
21
+
22
+ def test_the_array_specs_method
23
+ test = [1,2,3,4,5,6].array_specs
24
+ assert_equal(1, test.length)
25
+ assert_equal(SpecComponent, test[0].class)
26
+ assert_equal(0...6, test[0].range)
27
+ assert_equal(1, test[0].stride)
28
+ end
29
+
30
+ def test_the_array_data_method
31
+ test = [1,2,3,4,5,6]
32
+ assert_equal(test, test.array_data)
33
+ assert_equal(test.object_id, test.array_data.object_id)
34
+ end
35
+
36
+ def test_the_count_method
37
+ test = [1,2,3,4,5,6]
38
+ assert_equal(test.count, 6)
39
+ assert_equal(test.count, test.length)
40
+ end
41
+
42
+ def test_the_to_index_range_method
43
+ spec = SpecComponent.new(0...10, 1)
44
+
45
+ assert_equal(0..0, [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
+
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) }
56
+ 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) }
60
+ assert_raises(TypeError) { [:one, :two].to_index_range(spec) }
61
+ end
62
+ end
@@ -0,0 +1,82 @@
1
+ require_relative '../lib/flex_array'
2
+ require 'minitest/autorun'
3
+
4
+ class FlexArrayAppendTester < MiniTest::Unit::TestCase
5
+ $do_this_only_one_time = "" unless defined? $do_this_only_one_time
6
+
7
+ def initialize(*all)
8
+ if $do_this_only_one_time != __FILE__
9
+ puts
10
+ puts "Running test file: #{File.split(__FILE__)[1]}"
11
+ $do_this_only_one_time = __FILE__
12
+ end
13
+
14
+ super(*all)
15
+ end
16
+
17
+ def test_append_onto_an_existing_array
18
+ f = FlexArray.new([1,3], "Title")
19
+ assert_equal(2, f.dimensions)
20
+ assert_equal([0...1, 0...3], f.limits)
21
+
22
+ f << [1,2,3]
23
+ assert_equal(2, f.dimensions)
24
+ assert_equal([0..1, 0...3], f.limits)
25
+ a = ["Title","Title","Title",1,2,3]
26
+ assert_equal(a, f.array_data)
27
+
28
+ g = FlexArray.new_from_array([4,5,6])
29
+ f << g
30
+ assert_equal(2, f.dimensions)
31
+ assert_equal([0..2, 0...3], f.limits)
32
+ a << 4 << 5 << 6
33
+ assert_equal(a, f.array_data)
34
+ end
35
+
36
+ def test_append_onto_an_empty_array
37
+ f = FlexArray.new([0,3])
38
+ assert_equal(2, f.dimensions)
39
+ assert_equal([0...0, 0...3], f.limits)
40
+
41
+ f << [1,2,3]
42
+ assert_equal(2, f.dimensions)
43
+ assert_equal([0...1, 0...3], f.limits)
44
+ a = [1,2,3]
45
+ assert_equal(a, f.array_data)
46
+
47
+ f << [4,5,6]
48
+ assert_equal(2, f.dimensions)
49
+ assert_equal([0..1, 0...3], f.limits)
50
+ a = [1,2,3,4,5,6]
51
+ assert_equal(a, f.array_data)
52
+ end
53
+
54
+ def test_append_failures
55
+ f = FlexArray.new([1,3], "Title")
56
+ assert_raises(ArgumentError) { f << [3,4] }
57
+ assert_raises(ArgumentError) { f << [1,2,3,4] }
58
+
59
+ g = FlexArray.new([1,2], "Title")
60
+ assert_raises(ArgumentError) { f << g }
61
+ end
62
+
63
+ def test_the_copy_data_method
64
+ f = FlexArray.new([2,3], "Title")
65
+ g = FlexArray.new([2,3], "Fight")
66
+ f.copy_data(g)
67
+ assert_equal(f.array_data, g.array_data)
68
+ assert(f.array_data.object_id != g.array_data.object_id)
69
+ end
70
+
71
+ def test_copy_data_method_failures
72
+ f = FlexArray.new([2,3], "Title")
73
+ g = FlexArray.new([2,4], "Fight")
74
+ assert_raises(ArgumentError) { f.copy_data(g) }
75
+
76
+ g = FlexArray.new([1,3], "Fight")
77
+ assert_raises(ArgumentError) { f.copy_data(g) }
78
+
79
+ g = FlexArray.new([2,2], "Fight")
80
+ assert_raises(ArgumentError) { f.copy_data(g) }
81
+ end
82
+ end
@@ -0,0 +1,120 @@
1
+ require_relative '../lib/flex_array'
2
+ require 'minitest/autorun'
3
+
4
+ class FlexArrayEachTester < MiniTest::Unit::TestCase
5
+ $do_this_only_one_time = "" unless defined? $do_this_only_one_time
6
+
7
+ def initialize(*all)
8
+ if $do_this_only_one_time != __FILE__
9
+ puts
10
+ puts "Running test file: #{File.split(__FILE__)[1]}"
11
+ $do_this_only_one_time = __FILE__
12
+ end
13
+
14
+ super(*all)
15
+ end
16
+
17
+ def test_that_the_each_verbs_work
18
+ idx = []
19
+ q = FlexArray.new([3, 3]) {|i| idx << i.clone; i[0]*i[1]}
20
+ it = q.array_data.each
21
+
22
+ q.each do |v|
23
+ assert_equal(it.next, v)
24
+ end
25
+
26
+ it = q.each
27
+ q.array_data.each do |v|
28
+ assert_equal(it.next, v)
29
+ end
30
+
31
+ it = q.array_data.each
32
+ it2 = idx.each
33
+ q.each_with_index do |v, i|
34
+ assert_equal(it.next, v)
35
+ assert_equal(it2.next, i)
36
+ end
37
+
38
+ it = q.each_with_index
39
+ it2 = idx.each
40
+ q.array_data.each do |v|
41
+ value, index = it.next
42
+ assert_equal(value, v)
43
+ assert_equal(it2.next, index)
44
+ end
45
+
46
+ it = (0...9).each
47
+ it2 = idx.each
48
+ q._each_raw do |d, index, p|
49
+ assert_equal(d.object_id, q.array_data.object_id)
50
+ assert_equal(it2.next, index)
51
+ assert_equal(it.next, p)
52
+ end
53
+
54
+ it = q._each_raw
55
+ it2 = idx.each
56
+ (0...9).each do |i|
57
+ d, index, p = it.next
58
+ assert_equal(d.object_id, q.array_data.object_id)
59
+ assert_equal(it2.next, index)
60
+ assert_equal(i, p)
61
+ end
62
+ end
63
+
64
+ def test_that_the_indexed_each_verbs_work
65
+ q = FlexArray.new([3, 3]) {|i| i[0]*i[1]}
66
+ a = [0, 1, 2]
67
+ b = [[1,0], [1,1], [1,2]]
68
+ it = a.each
69
+
70
+ q.each([1, :all]) do |v|
71
+ assert_equal(it.next, v)
72
+ end
73
+
74
+ it = q.each([1, :all])
75
+ a.each do |v|
76
+ assert_equal(it.next, v)
77
+ end
78
+
79
+ it = a.each
80
+ it2 = b.each
81
+ q.each_with_index([1, :all]) do |v, i|
82
+ assert_equal(it.next, v)
83
+ assert_equal(it2.next, i)
84
+ end
85
+
86
+ it = q.each_with_index([1, :all])
87
+ it2 = b.each
88
+ a.each do |v|
89
+ value, index = it.next
90
+ assert_equal(value, v)
91
+ assert_equal(it2.next, index)
92
+ end
93
+
94
+ c = [3, 4, 5]
95
+ it = c.each
96
+ it2 = b.each
97
+ q._each_raw([1, :all]) do |d, index, p|
98
+ assert_equal(d.object_id, q.array_data.object_id)
99
+ assert_equal(it2.next, index)
100
+ assert_equal(it.next, p)
101
+ end
102
+
103
+ it = q._each_raw([1, :all])
104
+ it2 = b.each
105
+ c.each do |i|
106
+ d, index, p = it.next
107
+ assert_equal(d.object_id, q.array_data.object_id)
108
+ assert_equal(it2.next, index)
109
+ assert_equal(i, p)
110
+ end
111
+ end
112
+
113
+ def test_that_flex_array_cycle_works
114
+ a = FlexArray.new_from(3, [1,2,3])
115
+ r = []
116
+ it = a.cycle
117
+ 10.times {r << it.next}
118
+ assert_equal([1,2,3,1,2,3,1,2,3,1], r)
119
+ end
120
+ end