flex_array 0.3.5 → 0.3.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -15
  3. data/.reek.yml +17 -0
  4. data/README.md +11 -0
  5. data/bench/benchmark.rb +243 -0
  6. data/bench/results.txt +97 -0
  7. data/flex_array.gemspec +5 -9
  8. data/lib/flex_array.rb +13 -30
  9. data/lib/flex_array/array.rb +9 -24
  10. data/lib/flex_array/flex_array_append.rb +4 -23
  11. data/lib/flex_array/flex_array_each.rb +33 -208
  12. data/lib/flex_array/flex_array_forever.rb +6 -4
  13. data/lib/flex_array/flex_array_index.rb +4 -29
  14. data/lib/flex_array/flex_array_new.rb +9 -56
  15. data/lib/flex_array/flex_array_process.rb +23 -63
  16. data/lib/flex_array/flex_array_reshape.rb +13 -23
  17. data/lib/flex_array/flex_array_transpose.rb +7 -16
  18. data/lib/flex_array/flex_array_validate.rb +5 -14
  19. data/lib/flex_array/integer.rb +4 -13
  20. data/lib/flex_array/object.rb +4 -13
  21. data/lib/flex_array/range.rb +4 -13
  22. data/lib/flex_array/spec_array.rb +5 -9
  23. data/lib/flex_array/spec_component.rb +14 -22
  24. data/lib/flex_array/version.rb +1 -2
  25. data/rakefile.rb +0 -10
  26. data/reek.txt +9 -2
  27. data/tests/array_test.rb +0 -4
  28. data/tests/flex_array_append_test.rb +0 -23
  29. data/tests/flex_array_each_test.rb +483 -487
  30. data/tests/flex_array_index_test.rb +0 -4
  31. data/tests/flex_array_new_test.rb +0 -4
  32. data/tests/flex_array_reshape_test.rb +4 -4
  33. data/tests/flex_array_test.rb +0 -4
  34. data/tests/flex_array_transpose_test.rb +0 -4
  35. data/tests/flex_array_validate_test.rb +0 -4
  36. data/tests/integer_test.rb +0 -4
  37. data/tests/object_test.rb +0 -4
  38. data/tests/range_test.rb +0 -4
  39. data/tests/spec_array_test.rb +0 -4
  40. data/tests/spec_component_test.rb +0 -4
  41. metadata +12 -43
  42. data/docs/Flex_Array_UG.odt +0 -0
  43. data/docs/Flex_Array_UG_Version_0_3_0.pdf +0 -0
  44. data/flex_array.reek +0 -109
  45. data/sire.rb +0 -82
@@ -1,13 +1,15 @@
1
- #* flex_array_forever.rb - Forever looping support for the flexible array class.
1
+ # Forever looping support for the flexible array class.
2
+
2
3
  class FlexArray
3
- #A helper class that encapsulates the idea of looping without end!
4
+ # A helper class that encapsulates the idea of looping without end!
5
+
4
6
  class ForEver
5
- #Do something until false == true ;-)
7
+ # Do something until false == true ;-)
6
8
  def times(&block)
7
9
  loop {block.call}
8
10
  end
9
11
 
10
- #Convert an eternity into an integer. ;-)
12
+ # Convert an eternity into an integer. ;-)
11
13
  def to_i
12
14
  nil
13
15
  end
@@ -1,19 +1,7 @@
1
- #* flex_array_index.rb - The flexible array indexing and related methods.
1
+ # The flexible array indexing and related methods.
2
+
2
3
  class FlexArray
3
- #Retrieve the selected data from the \FlexArray.
4
- #<br>Parameters
5
- #* indexes - An array with as many entries as the flexible array has
6
- # dimensions. These entries may be an integer that is in the bounds of
7
- # the range limit of that dimension, or it can be a range where the start
8
- # and end of the range are in the bounds of the range limit of that
9
- # dimension, or it can be the symbol :all for all of the possible values
10
- # of that dimension.
11
- #<br>Returns
12
- #* The data selected by the index or an array of data if the index selects
13
- # more than one cell.
14
- #<br>Note
15
- #* If the indexes parameter equals a single :all this maps to all
16
- # elements of the array, regardless of its dimensionality.
4
+ # Retrieve the selected data from the flex array.
17
5
  def [](*indexes)
18
6
  validate_index_count(indexes)
19
7
  result = []
@@ -21,20 +9,7 @@ class FlexArray
21
9
  result.length == 1 ? result[0] : result
22
10
  end
23
11
 
24
- #Store the value data into the \FlexArray.
25
- #<br>Parameters
26
- #* indexes - An array with as many entries as the flexible array has
27
- # dimensions. These entries may be an integer that is in the bounds of
28
- # the range limit of that dimension, or it can be a range where the start
29
- # and end of the range are in the bounds of the range limit of that
30
- # dimension, or it can be the symbol :all for all of the possible values
31
- # of that dimension.
32
- #* value - A value to be stored in the selected array entries.
33
- #<br>Returns
34
- #* The value stored in the array.
35
- #<br>Note
36
- #* If the indexes parameter equals a single :all this maps to all
37
- # elements of the array, regardless of its dimensionality.
12
+ # Store the value data into the flex array.
38
13
  def []=(*indexes, value)
39
14
  validate_index_count(indexes)
40
15
  source = value.in_array.cycle
@@ -1,28 +1,14 @@
1
- #* flex_array_new.rb - The flexible array class constructor and related methods.
1
+ # The flexible array class constructor and related methods.
2
2
  class FlexArray
3
- #Construct a flexible array object.
4
- #<br>Parameters
5
- #* array_specs - The specification of the flex array subscript limits.
6
- # These can either be integers, in which case the limits are 0...n or
7
- # they can be ranges of integers, in which case the limits are those
8
- # of the range, or they can be an array of integers and/or ranges of
9
- # integers to represent arrays of more than one dimension.
10
- #* default - The optional default value. Defaults to nil.
11
- #* init_block - An optional initialization block. The return values from this
12
- # block are used to initialize the array. This overrides the default value.
13
- #<br>Block Arguments
14
- #* index - An array with one element per dimension with the fully qualified
15
- # index of the element being accessed. Note that the same array is passed
16
- # in each time the block is called, so, if this parameter is to stored
17
- # anywhere, it's best that it be cloned or duplicated first.
3
+ # Construct a flexible array object.
18
4
  def initialize(array_specs, default=nil, &init_block)
19
5
  @array_specs = SpecArray.new(array_specs.in_array)
20
6
  @transposed = false
21
7
 
22
- #Allocate the data for the array.
8
+ # Allocate the data for the array.
23
9
  @array_data = Array.new(@array_specs.spec_count, default)
24
10
 
25
- #Set up the array with the optional init_block.
11
+ # Set up the array with the optional init_block.
26
12
  if init_block
27
13
  process_all {|index, posn| @array_data[posn] = init_block.call(index)}
28
14
  end
@@ -30,11 +16,7 @@ class FlexArray
30
16
 
31
17
  alias_method :shallow_dup, :dup
32
18
 
33
- #Create a duplicate of this array.
34
- #<br>Warning
35
- #* The rdoc tool messes this up. shallow_dup is NOT an alias for this
36
- # dup, but rather the original system implementation of dup. This dup,
37
- # overrides the default dup and calls shallow_dup as part of its processing.
19
+ # Create a duplicate of this array.
38
20
  def dup
39
21
  other = self.shallow_dup
40
22
  other.array_specs = @array_specs.dup
@@ -42,49 +24,20 @@ class FlexArray
42
24
  other
43
25
  end
44
26
 
45
- #Construct a \FlexArray using other as a template or data source.
46
- #<br>Parameters:
47
- #* array_specs - The specification of the flex array subscript limits.
48
- # These can either be integers, in which case the limits are 0...n or
49
- # they can be ranges of integers, in which case the limits are those
50
- # of the range, or they can be an array of integers and/or ranges of
51
- # integers to represent arrays of more than one dimension.
52
- #* other - The array or flex array that is the source of the data.
53
- #<br>Note:
54
- #* To make a copy of a flex array, use dup instead.
27
+ # Construct a flex array using other as a template or data source.
55
28
  def self.new_from(array_specs, other)
56
29
  iterator = other.array_data.cycle
57
30
  FlexArray.new(array_specs) {iterator.next}
58
31
  end
59
32
 
60
- #Construct a \FlexArray using a all or a portion of portion of another
61
- #\FlexArray as a data source.
62
- #<br>Parameters
63
- #* array_specs - The specification of the flex array subscript limits.
64
- # These can either be integers, in which case the limits are 0...n or
65
- # they can be ranges of integers, in which case the limits are those
66
- # of the range, or they can be an array of integers and/or ranges of
67
- # integers to represent arrays of more than one dimension.
68
- #* other - The flex array source of the data used to build this flex
69
- # array. If no limits or other_indexes are specified, the limits of the
70
- # other array are used instead.
71
- #* selection - The indexes of the required sub-set of data to use
72
- # in setting up the new array.
73
- #<br>Notes:
74
- #* If the entire source array is to be used, use new_from instead.
75
- #* To make a copy of a flex array, use dup instead.
33
+ # Construct a flex array using a all or a portion of portion of another flex
34
+ # array as a data source.
76
35
  def self.new_from_selection(array_specs, other, selection)
77
36
  iterator = other.select_cycle(selection)
78
37
  FlexArray.new(array_specs) {iterator.next}
79
38
  end
80
39
 
81
- #Construct a \FlexArray as a duplicate of a source array or flex array.
82
- #<br>Parameters
83
- #* other - the array or flex array that is the source.
84
- #<br>Returns
85
- #* A flex array.
86
- #<br>Note
87
- #* The data array of the new flex array is a reference to the source array.
40
+ # Construct a flex array as a duplicate of a source array or flex array.
88
41
  def self.new_from_array(other)
89
42
  result = FlexArray.new(0)
90
43
  result.array_specs = other.array_specs.dup
@@ -1,18 +1,9 @@
1
- #* flex_array_process.rb - The flexible array class index processing routines.
1
+ # The flexible array class index processing routines.
2
2
  class FlexArray
3
3
  private
4
- #Process a \FlexArray index array. This is the heart of the \FlexArray
5
- #indexing process.
6
- #<br>Parameters
7
- #* indexes - An array with as many entries as the flexible array has
8
- # dimensions. See [] for more details. Note that since indexes is NOT
9
- # a splat parameter, it must be passed as an array explicitly. If passed
10
- # in as [:all] all elements of the array are processed.
11
- #* block - a block to be called for each value selected by this process.
12
- #<br>Block Arguments
13
- #* current - An array with one element per dimension with the fully qualified
14
- # index of the element being accessed.
15
- #* posn - The position of the element being accessed in the data array.
4
+
5
+ # Process a flex array index array. This is the heart of the flex array
6
+ # indexing process.
16
7
  def process_indexes(indexes, &block)
17
8
  current = Array.new(dimensions, 0)
18
9
 
@@ -29,33 +20,19 @@ class FlexArray
29
20
  end
30
21
  end
31
22
 
32
- #The worker bee for process_indexes.
33
- #<br>Parameters
34
- #* depth - The index of the dimension being processed.
35
- #* posn - The partially computed position of the element being accessed
36
- # in the data array.
37
- #* indexes - An array of array indexes. See the method [] for details on
38
- # what sorts of things these can be.
39
- #* current - The partial fully qualified index of the element being accessed.
40
- #* block - A block to be called for each value selected by this process.
41
- #<br>Block Arguments
42
- #* current - An array with one element per dimension with the fully qualified
43
- # index of the element being accessed.
44
- #* posn - The position of the element being accessed in the data array.
45
- #<br>Note
46
- #This is a recursive function. The recursion runs for index in 0..#dimensions
47
- #<br>Endemic Code Smells
23
+ # The worker bee for process_indexes.
48
24
  # :reek:LongParameterList
49
25
  def process_indexes_worker(depth, posn, indexes, current, &block)
50
- if depth == dimensions #Is there more work to do?
51
- block.call(current, posn) #Index ready, call the block.
26
+ if depth == dimensions # Is there more work to do?
27
+ block.call(current, posn) # Index ready, call the block.
52
28
  else
53
- spec = @array_specs[depth] #Get the current specification.
54
- min, stride = spec.min, spec.stride #Extract the relevant info.
29
+ spec = @array_specs[depth] # Get the current specification.
30
+ min, stride = spec.min, spec.stride # Extract the relevant info.
31
+
32
+ indexes[depth].each do |index| # Iterate over the range.
33
+ current[depth] = index # Update the current index.
55
34
 
56
- indexes[depth].each do |index| #Iterate over the range.
57
- current[depth] = index #Update the current index.
58
- #Process the next component in the array index.
35
+ # Process the next component in the array index.
59
36
  process_indexes_worker(depth+1,
60
37
  posn + (index-min) * stride,
61
38
  indexes,
@@ -65,43 +42,26 @@ class FlexArray
65
42
  end
66
43
  end
67
44
 
68
- #Special case where all of the array is being processed.
69
- #<br>Parameters
70
- #* block - A block to be called for each value selected by this process.
71
- #<br>Block Arguments
72
- #* current - An array with one element per dimension with the fully qualified
73
- # index of the element being accessed.
74
- #* posn - The position of the element being accessed in the data array.
45
+ # Special case where all of the array is being processed.
75
46
  def process_all(&block)
76
47
  current = Array.new(dimensions, 0)
77
48
  process_all_worker(0, 0, current, &block)
78
49
  end
79
50
 
80
- #The worker bee for process_all.
81
- #<br>Parameters
82
- #* depth - The index of the dimension being processed.
83
- #* posn - The partially computed position of the element being accessed
84
- # in the data array.
85
- #* current - The partial fully qualified index of the element being accessed.
86
- #* block - A block to be called for each value selected by this process.
87
- #<br>Block Arguments
88
- #* current - An array with one element per dimension with the fully qualified
89
- # index of the element being accessed.
90
- #* posn - The position of the element being accessed in the data array.
91
- #<br>Note
92
- #This is a recursive function. The recursion runs for index in 0..#dimensions
51
+ # The worker bee for process_all.
93
52
  def process_all_worker(depth, posn, current, &block)
94
- if depth == dimensions #Is there more work to do?
95
- block.call(current, posn) #Index ready, call the block.
53
+ if depth == dimensions # Is there more work to do?
54
+ block.call(current, posn) # Index ready, call the block.
96
55
  else
97
- spec = @array_specs[depth] #Get the current specification.
56
+ spec = @array_specs[depth] # Get the current specification.
98
57
  stride = spec.stride
99
58
 
100
- spec.each do |index| #Iterate over the range.
101
- current[depth] = index #Update the current index.
102
- #Process the next component in the array specification.
59
+ spec.each do |index| # Iterate over the range.
60
+ current[depth] = index # Update the current index.
61
+
62
+ # Process the next component in the array specification.
103
63
  process_all_worker(depth+1, posn, current, &block)
104
- posn += stride #Step to the next position.
64
+ posn += stride # Step to the next position.
105
65
  end
106
66
  end
107
67
  end
@@ -1,38 +1,28 @@
1
- #* flex_array_reshape.rb - The flexible array class reshape and related methods.
1
+ # The flexible array class reshape and related methods.
2
+
2
3
  class FlexArray
3
- #Return a copy of this \FlexArray, recast in a new shape, dropping or
4
- #repeating data elements as required.
5
- #<br>Parameters
6
- #* array_specs - The specification of the flex array subscript limits.
7
- # These can either be integers, in which case the limits are 0...n or
8
- # they can be ranges of integers, in which case the limits are those
9
- # of the range, or they can be an array of integers and/or ranges of
10
- # integers to represent arrays of more than one dimension.
11
- #<br>Returns
12
- #* The reshaped flexible array.
4
+ # Return a copy of this flex array, recast in a new shape, dropping or
5
+ # repeating data elements as required.
13
6
  def reshape(array_specs)
14
7
  iterator = @array_data.cycle
15
8
  FlexArray.new(array_specs) {iterator.next}
16
9
  end
17
10
 
18
- #Recast this \FlexArray in a new shape, dropping or
19
- #repeating data elements as required.
20
- #<br>Parameters
21
- #* array_specs - The specification of the flex array subscript limits.
22
- # These can either be integers, in which case the limits are 0...n or
23
- # they can be ranges of integers, in which case the limits are those
24
- # of the range, or they can be an array of integers and/or ranges of
25
- # integers to represent arrays of more than one dimension.
26
- #<br>Returns
27
- #* The reshaped, flexible array.
11
+ # Recast this flex array in a new shape, dropping or repeating data elements
12
+ # as required.
28
13
  def reshape!(array_specs)
29
14
  temp = self.reshape(array_specs)
30
15
  @array_specs, @array_data = temp.array_specs, temp.array_data
31
16
  self
32
17
  end
33
18
 
34
- #Convert the flex array to a simple array. Contained arrays are not affected.
19
+ # Convert the flex array to a simple array. Contained arrays are not affected.
35
20
  def to_a
36
- @array_data.dup
21
+ if @transposed
22
+ fetch = self.cycle
23
+ Array.new(@array_data.length) { fetch.next }
24
+ else
25
+ @array_data.dup
26
+ end
37
27
  end
38
28
  end
@@ -1,12 +1,8 @@
1
- #* flex_array_transpose.rb - The flexible array class transpose and related methods.
1
+ # The flexible array class transpose and related methods.
2
+
2
3
  class FlexArray
3
- #Transpose the specified dimensions. This may change the "shape" of the array
4
- #if the transposed dimensions were of different limits.
5
- #<br>Returns
6
- #* The flex array transposed.
7
- #<br>Note
8
- #* Transposing an array disables the speed-up for processing the array with
9
- # an index of [:all].
4
+ # Transpose the specified dimensions. This may change the "shape" of the array
5
+ # if the transposed dimensions were of different limits.
10
6
  def transpose!(dim_a, dim_b)
11
7
  validate_dimension(dim_a)
12
8
  validate_dimension(dim_b)
@@ -15,14 +11,9 @@ class FlexArray
15
11
  self
16
12
  end
17
13
 
18
- #Return a reference to this array's data with the specified dimensions
19
- #transposed. This may change the "shape" of the array if the transposed
20
- #dimensions were of different limits.
21
- #<br>Returns
22
- #* The flex array transposed.
23
- #<br>Note
24
- #* Transposing an array disables the speed-up for processing the array with
25
- # an index of [:all].
14
+ # Return a reference to this array's data with the specified dimensions
15
+ # transposed. This may change the "shape" of the array if the transposed
16
+ # dimensions were of different limits.
26
17
  def transpose(dim_a, dim_b)
27
18
  FlexArray.new_from_array(self).transpose!(dim_a, dim_b)
28
19
  end
@@ -1,10 +1,7 @@
1
- #* flex_array_validate.rb - The flexible array class index validation routines.
1
+ # Some flexible array class index validation routines.
2
+
2
3
  class FlexArray
3
- #Is this array compatible with other?
4
- #<br>Parameters
5
- #* other - The object being tested for compatibility.
6
- #<br>Returns
7
- #* true if the arrays are compatible.
4
+ # Is this array compatible with other?
8
5
  def compatible?(other)
9
6
  @array_specs == other.array_specs
10
7
  rescue
@@ -13,11 +10,7 @@ class FlexArray
13
10
 
14
11
  private
15
12
 
16
- #Validate the dimensionality of the indexes passed in.
17
- #<br>Parameters
18
- #* indexes - An array of indexes to be validated.
19
- #<br>Exceptions
20
- #* ArgumentError - raised on invalid dimensionality.
13
+ # Validate the dimensionality of the indexes passed in.
21
14
  def validate_index_count(indexes)
22
15
  unless indexes == [:all]
23
16
  if dimensions != indexes.length
@@ -26,9 +19,7 @@ class FlexArray
26
19
  end
27
20
  end
28
21
 
29
- #Is this a valid dimension selector?
30
- #<br>Exceptions
31
- #* ArgumentError - raised on invalid dimension.
22
+ # Is this a valid dimension selector?
32
23
  def validate_dimension(dim)
33
24
  unless (0...dimensions) === dim
34
25
  fail ArgumentError, "Invalid dimension selector: #{dim}"
@@ -1,10 +1,7 @@
1
- #Extensions to Integer needed to support flex array.
1
+ # Extensions to Integer needed to support flex array.
2
+
2
3
  class Integer
3
- #Convert this integer to a limits component.
4
- #<br>Parameters
5
- #* stride - the number of cells separating data with adjacent indexes.
6
- #<br>Returns
7
- #* A SpecComponent object of 0...self
4
+ # Convert this integer to a limits component.
8
5
  def to_spec_component(stride)
9
6
  if self >= 0
10
7
  SpecComponent.new(0...self, stride)
@@ -13,13 +10,7 @@ class Integer
13
10
  end
14
11
  end
15
12
 
16
- #Convert this integer to an range index against the spec.
17
- #<br>Parameters
18
- #* spec - The spec component used to validate this index.
19
- #<br>Returns
20
- #* A range.
21
- #<br>Exceptions
22
- #* IndexError if the range is not valid.
13
+ # Convert this integer to a range index against the spec.
23
14
  def to_index_range(spec)
24
15
  alter_ego = (self >= 0) ? self : (spec.max + self + 1)
25
16
 
@@ -1,21 +1,12 @@
1
- #Extensions to Object needed to support flex array.
1
+ # Extensions to Object needed to support flex array.
2
+
2
3
  class Object
3
- #Fail with message since the array dimension is invalid.
4
- #<br>Parameters
5
- #* _stride - unused, required to maintain signature.
6
- #<br>Returns
7
- #* Nothing, always fails.
4
+ # Fail with message since the array dimension is invalid.
8
5
  def to_spec_component(_stride)
9
6
  fail ArgumentError, "Invalid flex array dimension: #{self.inspect}"
10
7
  end
11
8
 
12
- #Convert this object to an range index against the spec.
13
- #<br>Parameters
14
- #* spec - The spec component used to validate this index.
15
- #<br>Returns
16
- #* A range.
17
- #<br>Exceptions
18
- #* IndexError if the range is not valid.
9
+ # Convert this object to an range index against the spec.
19
10
  def to_index_range(spec)
20
11
  if self == :all
21
12
  spec.range