multiarray 0.16.0 → 0.17.0
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/Rakefile +1 -1
- data/lib/multiarray.rb +57 -0
- data/lib/multiarray/gccvalue.rb +38 -0
- data/lib/multiarray/mask.rb +147 -0
- data/lib/multiarray/multiarray.rb +5 -3
- data/lib/multiarray/operations.rb +54 -1
- data/lib/multiarray/sequence.rb +10 -3
- data/lib/multiarray/unmask.rb +154 -0
- data/test/tc_multiarray.rb +27 -0
- data/test/tc_sequence.rb +23 -0
- metadata +5 -3
    
        data/Rakefile
    CHANGED
    
    
    
        data/lib/multiarray.rb
    CHANGED
    
    | @@ -176,6 +176,25 @@ class Object | |
| 176 176 | 
             
                a.is_a?( Proc ) ? a.call : a
         | 
| 177 177 | 
             
              end
         | 
| 178 178 |  | 
| 179 | 
            +
              # Conditional operation
         | 
| 180 | 
            +
              #
         | 
| 181 | 
            +
              # @param [Proc] action Action to perform if condition is +true+.
         | 
| 182 | 
            +
              #
         | 
| 183 | 
            +
              # @return [Object] The return value should be ignored.
         | 
| 184 | 
            +
              def if( &action )
         | 
| 185 | 
            +
                action.call
         | 
| 186 | 
            +
              end
         | 
| 187 | 
            +
             | 
| 188 | 
            +
              # Conditional operation
         | 
| 189 | 
            +
              #
         | 
| 190 | 
            +
              # @param [Proc] action1 Action to perform if condition is +true+.
         | 
| 191 | 
            +
              # @param [Proc] action2 Action to perform if condition is +false+.
         | 
| 192 | 
            +
              #
         | 
| 193 | 
            +
              # @return [Object] The return value should be ignored.
         | 
| 194 | 
            +
              def if_else( action1, action2 )
         | 
| 195 | 
            +
                action1.call
         | 
| 196 | 
            +
              end
         | 
| 197 | 
            +
             | 
| 179 198 | 
             
            end
         | 
| 180 199 |  | 
| 181 200 | 
             
            # +NilClass+ is extended with a few methods
         | 
| @@ -235,6 +254,24 @@ class NilClass | |
| 235 254 | 
             
                b.is_a?( Proc ) ? b.call : b
         | 
| 236 255 | 
             
              end
         | 
| 237 256 |  | 
| 257 | 
            +
              # Conditional operation
         | 
| 258 | 
            +
              #
         | 
| 259 | 
            +
              # @param [Proc] action Action to perform if condition is +true+.
         | 
| 260 | 
            +
              #
         | 
| 261 | 
            +
              # @return [Object] The return value should be ignored.
         | 
| 262 | 
            +
              def if( &action )
         | 
| 263 | 
            +
              end
         | 
| 264 | 
            +
             | 
| 265 | 
            +
              # Conditional operation
         | 
| 266 | 
            +
              #
         | 
| 267 | 
            +
              # @param [Proc] action1 Action to perform if condition is +true+.
         | 
| 268 | 
            +
              # @param [Proc] action2 Action to perform if condition is +false+.
         | 
| 269 | 
            +
              #
         | 
| 270 | 
            +
              # @return [Object] The return value should be ignored.
         | 
| 271 | 
            +
              def if_else( action1, action2 )
         | 
| 272 | 
            +
                action2.call
         | 
| 273 | 
            +
              end
         | 
| 274 | 
            +
             | 
| 238 275 | 
             
              # Check whether this term is compilable
         | 
| 239 276 | 
             
              #
         | 
| 240 277 | 
             
              # @return [FalseClass,TrueClass] Returns +false+
         | 
| @@ -305,6 +342,24 @@ class FalseClass | |
| 305 342 | 
             
                b.is_a?( Proc ) ? b.call : b
         | 
| 306 343 | 
             
              end
         | 
| 307 344 |  | 
| 345 | 
            +
              # Conditional operation
         | 
| 346 | 
            +
              #
         | 
| 347 | 
            +
              # @param [Proc] action Action to perform if condition is +true+.
         | 
| 348 | 
            +
              #
         | 
| 349 | 
            +
              # @return [Object] The return value should be ignored.
         | 
| 350 | 
            +
              def if( &action )
         | 
| 351 | 
            +
              end
         | 
| 352 | 
            +
             | 
| 353 | 
            +
              # Conditional operation
         | 
| 354 | 
            +
              #
         | 
| 355 | 
            +
              # @param [Proc] action1 Action to perform if condition is +true+.
         | 
| 356 | 
            +
              # @param [Proc] action2 Action to perform if condition is +false+.
         | 
| 357 | 
            +
              #
         | 
| 358 | 
            +
              # @return [Object] The return value should be ignored.
         | 
| 359 | 
            +
              def if_else( action1, action2 )
         | 
| 360 | 
            +
                action2.call
         | 
| 361 | 
            +
              end
         | 
| 362 | 
            +
             | 
| 308 363 | 
             
            end
         | 
| 309 364 |  | 
| 310 365 | 
             
            # Some methods of +Fixnum+ are modified
         | 
| @@ -603,6 +658,8 @@ require 'multiarray/diagonal' | |
| 603 658 | 
             
            require 'multiarray/histogram'
         | 
| 604 659 | 
             
            require 'multiarray/lut'
         | 
| 605 660 | 
             
            require 'multiarray/integral'
         | 
| 661 | 
            +
            require 'multiarray/mask'
         | 
| 662 | 
            +
            require 'multiarray/unmask'
         | 
| 606 663 | 
             
            require 'multiarray/operations'
         | 
| 607 664 | 
             
            require 'multiarray/methods'
         | 
| 608 665 | 
             
            require 'multiarray/rgb'
         | 
    
        data/lib/multiarray/gccvalue.rb
    CHANGED
    
    | @@ -333,6 +333,44 @@ module Hornetseye | |
| 333 333 |  | 
| 334 334 | 
             
                alias_method_chain :conditional, :complex
         | 
| 335 335 |  | 
| 336 | 
            +
                # Generate code for conditional statement
         | 
| 337 | 
            +
                #
         | 
| 338 | 
            +
                # @param [Proc] action Block of conditional.
         | 
| 339 | 
            +
                #
         | 
| 340 | 
            +
                # @return [Object] Returns +self+.
         | 
| 341 | 
            +
                #
         | 
| 342 | 
            +
                # @private
         | 
| 343 | 
            +
                def if( &action )
         | 
| 344 | 
            +
                  @function << "#{@function.indent}if ( #{self} ) {\n"
         | 
| 345 | 
            +
                  @function.indent_offset +1
         | 
| 346 | 
            +
                  action.call
         | 
| 347 | 
            +
                  @function.indent_offset -1
         | 
| 348 | 
            +
                  @function << "#{@function.indent}};\n"
         | 
| 349 | 
            +
                  self
         | 
| 350 | 
            +
                end
         | 
| 351 | 
            +
             | 
| 352 | 
            +
                # Generate code for conditional statement
         | 
| 353 | 
            +
                #
         | 
| 354 | 
            +
                # @param [Proc] action1 Block to run when condition is fullfilled.
         | 
| 355 | 
            +
                # @param [Proc] action2 Block to run otherwise.
         | 
| 356 | 
            +
                #
         | 
| 357 | 
            +
                # @return [Object] Returns +self+.
         | 
| 358 | 
            +
                #
         | 
| 359 | 
            +
                # @private
         | 
| 360 | 
            +
                def if_else( action1, action2 )
         | 
| 361 | 
            +
                  @function << "#{@function.indent}if ( #{self} ) {\n"
         | 
| 362 | 
            +
                  @function.indent_offset +1
         | 
| 363 | 
            +
                  action1.call
         | 
| 364 | 
            +
                  @function.indent_offset -1
         | 
| 365 | 
            +
                  @function << "#{@function.indent}} else {\n"
         | 
| 366 | 
            +
                  @function.indent_offset +1
         | 
| 367 | 
            +
                  action2.call
         | 
| 368 | 
            +
                  @function.indent_offset -1
         | 
| 369 | 
            +
                  @function << "#{@function.indent}};\n"
         | 
| 370 | 
            +
                  self
         | 
| 371 | 
            +
                end
         | 
| 372 | 
            +
             | 
| 373 | 
            +
             | 
| 336 374 | 
             
                define_unary_op :not, '!'
         | 
| 337 375 | 
             
                define_unary_op :~
         | 
| 338 376 | 
             
                define_unary_op :-@, :-
         | 
| @@ -0,0 +1,147 @@ | |
| 1 | 
            +
            # multiarray - Lazy multi-dimensional arrays for Ruby
         | 
| 2 | 
            +
            # Copyright (C) 2010 Jan Wedekind
         | 
| 3 | 
            +
            #
         | 
| 4 | 
            +
            # This program is free software: you can redistribute it and/or modify
         | 
| 5 | 
            +
            # it under the terms of the GNU General Public License as published by
         | 
| 6 | 
            +
            # the Free Software Foundation, either version 3 of the License, or
         | 
| 7 | 
            +
            # (at your option) any later version.
         | 
| 8 | 
            +
            #
         | 
| 9 | 
            +
            # This program is distributed in the hope that it will be useful,
         | 
| 10 | 
            +
            # but WITHOUT ANY WARRANTY; without even the implied warranty of
         | 
| 11 | 
            +
            # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
         | 
| 12 | 
            +
            # GNU General Public License for more details.
         | 
| 13 | 
            +
            #
         | 
| 14 | 
            +
            # You should have received a copy of the GNU General Public License
         | 
| 15 | 
            +
            # along with this program.  If not, see <http://www.gnu.org/licenses/>.
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            # Namespace of Hornetseye computer vision library
         | 
| 18 | 
            +
            module Hornetseye
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              # Class for representing masking operations
         | 
| 21 | 
            +
              class Mask < Node
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                class << self
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  # Check whether objects of this class are finalised computations
         | 
| 26 | 
            +
                  #
         | 
| 27 | 
            +
                  # @return [Boolean] Returns +false+.
         | 
| 28 | 
            +
                  #
         | 
| 29 | 
            +
                  # @private
         | 
| 30 | 
            +
                  def finalised?
         | 
| 31 | 
            +
                    false
         | 
| 32 | 
            +
                  end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                # Constructor
         | 
| 37 | 
            +
                #
         | 
| 38 | 
            +
                # @param [Node] dest Target array to write histogram to.
         | 
| 39 | 
            +
                # @param [Node] source Source array with values to apply mask to.
         | 
| 40 | 
            +
                # @param [Node] m Boolean array with values of mask.
         | 
| 41 | 
            +
                # @param [Node] index Counter for maintaining size of result.
         | 
| 42 | 
            +
                #
         | 
| 43 | 
            +
                # @private
         | 
| 44 | 
            +
                def initialize( dest, source, m, index )
         | 
| 45 | 
            +
                  @dest, @source, @m, @index = dest, source, m, index
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                # Get unique descriptor of this object
         | 
| 49 | 
            +
                #
         | 
| 50 | 
            +
                # @param [Hash] hash Labels for any variables.
         | 
| 51 | 
            +
                #
         | 
| 52 | 
            +
                # @return [String] Descriptor of this object,
         | 
| 53 | 
            +
                #
         | 
| 54 | 
            +
                # @private
         | 
| 55 | 
            +
                def descriptor( hash )
         | 
| 56 | 
            +
                  "Mask(#{@dest.descriptor( hash )},#{@source.descriptor( hash )}," +
         | 
| 57 | 
            +
                    "#{@m.descriptor( hash )},#{@index.descriptor( hash )})"
         | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                # Get type of result of delayed operation
         | 
| 61 | 
            +
                #
         | 
| 62 | 
            +
                # @return [Class] Type of result.
         | 
| 63 | 
            +
                #
         | 
| 64 | 
            +
                # @private
         | 
| 65 | 
            +
                def array_type
         | 
| 66 | 
            +
                  @dest.array_type
         | 
| 67 | 
            +
                end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                # Perform masking operation
         | 
| 70 | 
            +
                #
         | 
| 71 | 
            +
                # @return [Node] Result of computation
         | 
| 72 | 
            +
                #
         | 
| 73 | 
            +
                # @private
         | 
| 74 | 
            +
                def demand
         | 
| 75 | 
            +
                  if variables.empty?
         | 
| 76 | 
            +
                    index = @index.simplify
         | 
| 77 | 
            +
                    if @m.dimension > 0
         | 
| 78 | 
            +
                      @m.shape.last.times do |i|
         | 
| 79 | 
            +
                        m = @m.element INT.new( i )
         | 
| 80 | 
            +
                        source = @source.element INT.new( i )
         | 
| 81 | 
            +
                        Mask.new( @dest, source, m, index ).demand
         | 
| 82 | 
            +
                      end  
         | 
| 83 | 
            +
                    else
         | 
| 84 | 
            +
                      @m.simplify.get.if do
         | 
| 85 | 
            +
                        Store.new( @dest.element( index ), @source ).demand
         | 
| 86 | 
            +
                        index.store index + 1
         | 
| 87 | 
            +
                      end
         | 
| 88 | 
            +
                    end
         | 
| 89 | 
            +
                    @index.store index
         | 
| 90 | 
            +
                    @dest
         | 
| 91 | 
            +
                  else
         | 
| 92 | 
            +
                    super
         | 
| 93 | 
            +
                  end
         | 
| 94 | 
            +
                end
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                # Substitute variables
         | 
| 97 | 
            +
                #
         | 
| 98 | 
            +
                # Substitute the variables with the values given in the hash.
         | 
| 99 | 
            +
                #
         | 
| 100 | 
            +
                # @param [Hash] hash Substitutions to apply.
         | 
| 101 | 
            +
                #
         | 
| 102 | 
            +
                # @return [Node] Term with substitutions applied.
         | 
| 103 | 
            +
                #
         | 
| 104 | 
            +
                # @private
         | 
| 105 | 
            +
                def subst( hash )
         | 
| 106 | 
            +
                  self.class.new @dest.subst( hash ), @source.subst( hash ), @m.subst( hash ),
         | 
| 107 | 
            +
                                 @index.subst( hash )
         | 
| 108 | 
            +
                end
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                # Get variables contained in this term
         | 
| 111 | 
            +
                #
         | 
| 112 | 
            +
                # @return [Set] Returns list of variables.
         | 
| 113 | 
            +
                #
         | 
| 114 | 
            +
                # @private
         | 
| 115 | 
            +
                def variables
         | 
| 116 | 
            +
                  @dest.variables + @source.variables + @m.variables + @index.variables
         | 
| 117 | 
            +
                end
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                # Strip of all values
         | 
| 120 | 
            +
                #
         | 
| 121 | 
            +
                # Split up into variables, values, and a term where all values have been
         | 
| 122 | 
            +
                # replaced with variables.
         | 
| 123 | 
            +
                #
         | 
| 124 | 
            +
                # @return [Array<Array,Node>] Returns an array of variables, an array of
         | 
| 125 | 
            +
                # values, and the term based on variables.
         | 
| 126 | 
            +
                #
         | 
| 127 | 
            +
                # @private
         | 
| 128 | 
            +
                def strip
         | 
| 129 | 
            +
                  stripped = [ @dest, @source, @m, @index ].collect { |value| value.strip }
         | 
| 130 | 
            +
                  return stripped.inject( [] ) { |vars,elem| vars + elem[ 0 ] },
         | 
| 131 | 
            +
                       stripped.inject( [] ) { |values,elem| values + elem[ 1 ] },
         | 
| 132 | 
            +
                       self.class.new( *stripped.collect { |elem| elem[ 2 ] } )
         | 
| 133 | 
            +
                end
         | 
| 134 | 
            +
             | 
| 135 | 
            +
                # Check whether this term is compilable
         | 
| 136 | 
            +
                #
         | 
| 137 | 
            +
                # @return [Boolean] Returns whether this term is compilable.
         | 
| 138 | 
            +
                #
         | 
| 139 | 
            +
                # @private
         | 
| 140 | 
            +
                def compilable?
         | 
| 141 | 
            +
                  [ @dest, @source, @m, @index ].all? { |value| value.compilable? }
         | 
| 142 | 
            +
                end
         | 
| 143 | 
            +
             | 
| 144 | 
            +
              end
         | 
| 145 | 
            +
             | 
| 146 | 
            +
            end
         | 
| 147 | 
            +
             | 
| @@ -24,11 +24,13 @@ module Hornetseye | |
| 24 24 |  | 
| 25 25 | 
             
                  # Create new multi-dimensional array
         | 
| 26 26 | 
             
                  #
         | 
| 27 | 
            -
                  # @param [Class]  | 
| 28 | 
            -
                  # @param [Array<Integer>] * | 
| 27 | 
            +
                  # @param [Class] element_type The type of the elements.
         | 
| 28 | 
            +
                  # @param [Array<Integer>] *array_shape The shape of the multi-dimensional array.
         | 
| 29 29 | 
             
                  #
         | 
| 30 30 | 
             
                  # @return [Node] Returns uninitialised native array.
         | 
| 31 | 
            -
                  def new(  | 
| 31 | 
            +
                  def new( element_type, *array_shape )
         | 
| 32 | 
            +
                    typecode = element_type.typecode
         | 
| 33 | 
            +
                    shape = element_type.shape + array_shape
         | 
| 32 34 | 
             
                    options = shape.last.is_a?( Hash ) ? shape.pop : {}
         | 
| 33 35 | 
             
                    count = options[ :count ] || 1
         | 
| 34 36 | 
             
                    if shape.empty?
         | 
| @@ -1,5 +1,5 @@ | |
| 1 1 | 
             
            # multiarray - Lazy multi-dimensional arrays for Ruby
         | 
| 2 | 
            -
            # Copyright (C) 2010 Jan Wedekind
         | 
| 2 | 
            +
            # Copyright (C) 2010, 2011 Jan Wedekind
         | 
| 3 3 | 
             
            #
         | 
| 4 4 | 
             
            # This program is free software: you can redistribute it and/or modify
         | 
| 5 5 | 
             
            # it under the terms of the GNU General Public License as published by
         | 
| @@ -569,6 +569,59 @@ module Hornetseye | |
| 569 569 | 
             
                  left
         | 
| 570 570 | 
             
                end
         | 
| 571 571 |  | 
| 572 | 
            +
                # Select values from array using a mask
         | 
| 573 | 
            +
                #
         | 
| 574 | 
            +
                # @param [Node] m Mask to apply to this array.
         | 
| 575 | 
            +
                #
         | 
| 576 | 
            +
                # @return [Node] The masked array.
         | 
| 577 | 
            +
                def mask( m )
         | 
| 578 | 
            +
                  check_shape m
         | 
| 579 | 
            +
                  left = MultiArray.new typecode, *( shape.first( dimension - m.dimension ) +
         | 
| 580 | 
            +
                                                     [ m.size ] )
         | 
| 581 | 
            +
                  index = Hornetseye::Pointer( INT ).new
         | 
| 582 | 
            +
                  index.store INT.new( 0 )
         | 
| 583 | 
            +
                  block = Mask.new left, self, m, index
         | 
| 584 | 
            +
                  if block.compilable?
         | 
| 585 | 
            +
                    GCCFunction.run block
         | 
| 586 | 
            +
                  else
         | 
| 587 | 
            +
                    block.demand
         | 
| 588 | 
            +
                  end
         | 
| 589 | 
            +
                  left[ 0 ... index[] ].roll
         | 
| 590 | 
            +
                end
         | 
| 591 | 
            +
             | 
| 592 | 
            +
                # Distribute values in a new array using a mask
         | 
| 593 | 
            +
                #
         | 
| 594 | 
            +
                # @param [Node] m Mask for inverse masking operation.
         | 
| 595 | 
            +
                # @option options [Object] :default (typecode.default) Default value for elements
         | 
| 596 | 
            +
                #         where mask is +false+.
         | 
| 597 | 
            +
                # @option options [Boolean] :safe (true) Ensure that the size of this size is
         | 
| 598 | 
            +
                #         sufficient.
         | 
| 599 | 
            +
                #
         | 
| 600 | 
            +
                # @return [Node] The result of the inverse masking operation.
         | 
| 601 | 
            +
                def unmask( m, options = {} )
         | 
| 602 | 
            +
                  options = { :safe => true, :default => typecode.default }.merge options
         | 
| 603 | 
            +
                  default = options[ :default ]
         | 
| 604 | 
            +
                  default = typecode.new default unless default.is_a? Node
         | 
| 605 | 
            +
                  m.check_shape default
         | 
| 606 | 
            +
                  if options[ :safe ]
         | 
| 607 | 
            +
                    if m.to_ubyte.sum > shape.last
         | 
| 608 | 
            +
                      raise "#{m.to_ubyte.sum} value(s) of the mask are true but the last " +
         | 
| 609 | 
            +
                        "dimension of the array for unmasking only has #{shape.last} value(s)"
         | 
| 610 | 
            +
                    end
         | 
| 611 | 
            +
                  end
         | 
| 612 | 
            +
                  left = Hornetseye::MultiArray( array_type.element_type, *m.shape ).
         | 
| 613 | 
            +
                         coercion( default.array_type ).new
         | 
| 614 | 
            +
                  index = Hornetseye::Pointer( INT ).new
         | 
| 615 | 
            +
                  index.store INT.new( 0 )
         | 
| 616 | 
            +
                  block = Unmask.new left, self, m, index, default
         | 
| 617 | 
            +
                  if block.compilable?
         | 
| 618 | 
            +
                    GCCFunction.run block
         | 
| 619 | 
            +
                  else
         | 
| 620 | 
            +
                    block.demand
         | 
| 621 | 
            +
                  end
         | 
| 622 | 
            +
                  left
         | 
| 623 | 
            +
                end
         | 
| 624 | 
            +
             | 
| 572 625 | 
             
                # Mirror the array
         | 
| 573 626 | 
             
                #
         | 
| 574 627 | 
             
                # @param [Array<Integer>] dimensions The dimensions which should be flipped.
         | 
    
        data/lib/multiarray/sequence.rb
    CHANGED
    
    | @@ -24,12 +24,12 @@ module Hornetseye | |
| 24 24 |  | 
| 25 25 | 
             
                  # Allocate new uniform array
         | 
| 26 26 | 
             
                  #
         | 
| 27 | 
            -
                  # @param [Class]  | 
| 27 | 
            +
                  # @param [Class] element_type Type of array elements.
         | 
| 28 28 | 
             
                  # @param [Integer] size Number of elements.
         | 
| 29 29 | 
             
                  #
         | 
| 30 30 | 
             
                  # @return [Node] Returns uninitialised native array.
         | 
| 31 | 
            -
                  def new(  | 
| 32 | 
            -
                    MultiArray.new  | 
| 31 | 
            +
                  def new( element_type, size )
         | 
| 32 | 
            +
                    MultiArray.new element_type, size
         | 
| 33 33 | 
             
                  end
         | 
| 34 34 |  | 
| 35 35 | 
             
                  # Import array from string
         | 
| @@ -117,6 +117,13 @@ module Hornetseye | |
| 117 117 | 
             
                    end
         | 
| 118 118 | 
             
                  end
         | 
| 119 119 |  | 
| 120 | 
            +
                  # Generate random number array
         | 
| 121 | 
            +
                  #
         | 
| 122 | 
            +
                  # Generate integer or floating point random numbers in the range 0 ... n.
         | 
| 123 | 
            +
                  #
         | 
| 124 | 
            +
                  # @param [Integer,Float] n Upper boundary for random numbers
         | 
| 125 | 
            +
                  #
         | 
| 126 | 
            +
                  # @return [Node] Array with random numbers.
         | 
| 120 127 | 
             
                  def random( n = 1 )
         | 
| 121 128 | 
             
                    n = typecode.maxint.new n unless n.is_a? Node
         | 
| 122 129 | 
             
                    retval = new
         | 
| @@ -0,0 +1,154 @@ | |
| 1 | 
            +
            # multiarray - Lazy multi-dimensional arrays for Ruby
         | 
| 2 | 
            +
            # Copyright (C) 2011 Jan Wedekind
         | 
| 3 | 
            +
            #
         | 
| 4 | 
            +
            # This program is free software: you can redistribute it and/or modify
         | 
| 5 | 
            +
            # it under the terms of the GNU General Public License as published by
         | 
| 6 | 
            +
            # the Free Software Foundation, either version 3 of the License, or
         | 
| 7 | 
            +
            # (at your option) any later version.
         | 
| 8 | 
            +
            #
         | 
| 9 | 
            +
            # This program is distributed in the hope that it will be useful,
         | 
| 10 | 
            +
            # but WITHOUT ANY WARRANTY; without even the implied warranty of
         | 
| 11 | 
            +
            # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
         | 
| 12 | 
            +
            # GNU General Public License for more details.
         | 
| 13 | 
            +
            #
         | 
| 14 | 
            +
            # You should have received a copy of the GNU General Public License
         | 
| 15 | 
            +
            # along with this program.  If not, see <http://www.gnu.org/licenses/>.
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            # Namespace of Hornetseye computer vision library
         | 
| 18 | 
            +
            module Hornetseye
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              # Class for representing inverse masking operations
         | 
| 21 | 
            +
              class Unmask < Node
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                class << self
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  # Check whether objects of this class are finalised computations
         | 
| 26 | 
            +
                  #
         | 
| 27 | 
            +
                  # @return [Boolean] Returns +false+.
         | 
| 28 | 
            +
                  #
         | 
| 29 | 
            +
                  # @private
         | 
| 30 | 
            +
                  def finalised?
         | 
| 31 | 
            +
                    false
         | 
| 32 | 
            +
                  end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                # Constructor
         | 
| 37 | 
            +
                #
         | 
| 38 | 
            +
                # @param [Node] dest Target array to write histogram to.
         | 
| 39 | 
            +
                # @param [Node] source Source array with values to apply mask to.
         | 
| 40 | 
            +
                # @param [Node] m Boolean array with values of mask.
         | 
| 41 | 
            +
                # @param [Node] default Default value for unaffected elements.
         | 
| 42 | 
            +
                #
         | 
| 43 | 
            +
                # @private
         | 
| 44 | 
            +
                def initialize( dest, source, m, index, default )
         | 
| 45 | 
            +
                  @dest, @source, @m, @index, @default = dest, source, m, index, default
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                # Get unique descriptor of this object
         | 
| 49 | 
            +
                #
         | 
| 50 | 
            +
                # @param [Hash] hash Labels for any variables.
         | 
| 51 | 
            +
                #
         | 
| 52 | 
            +
                # @return [String] Descriptor of this object,
         | 
| 53 | 
            +
                #
         | 
| 54 | 
            +
                # @private
         | 
| 55 | 
            +
                def descriptor( hash )
         | 
| 56 | 
            +
                  "Unmask(#{@dest.descriptor( hash )},#{@source.descriptor( hash )}," +
         | 
| 57 | 
            +
                    "#{@m.descriptor( hash )},#{@index.descriptor( hash )}," +
         | 
| 58 | 
            +
                    "#{@default.descriptor( hash )})"
         | 
| 59 | 
            +
                end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                # Get type of result of delayed operation
         | 
| 62 | 
            +
                #
         | 
| 63 | 
            +
                # @return [Class] Type of result.
         | 
| 64 | 
            +
                #
         | 
| 65 | 
            +
                # @private
         | 
| 66 | 
            +
                def array_type
         | 
| 67 | 
            +
                  @dest.array_type
         | 
| 68 | 
            +
                end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
                # Perform masking operation
         | 
| 71 | 
            +
                #
         | 
| 72 | 
            +
                # @return [Node] Result of computation
         | 
| 73 | 
            +
                #
         | 
| 74 | 
            +
                # @private
         | 
| 75 | 
            +
                def demand
         | 
| 76 | 
            +
                  if variables.empty?
         | 
| 77 | 
            +
                    index = @index.simplify
         | 
| 78 | 
            +
                    if @m.dimension > 0
         | 
| 79 | 
            +
                      @m.shape.last.times do |i|
         | 
| 80 | 
            +
                        m = @m.element INT.new( i )
         | 
| 81 | 
            +
                        dest = @dest.element INT.new( i )
         | 
| 82 | 
            +
                        default = @default.dimension > 0 ?
         | 
| 83 | 
            +
                                  @default.element( INT.new( i ) ) : @default
         | 
| 84 | 
            +
                        Unmask.new( dest, @source, m, index, default ).demand
         | 
| 85 | 
            +
                      end  
         | 
| 86 | 
            +
                    else
         | 
| 87 | 
            +
                      @m.simplify.get.if_else( proc do
         | 
| 88 | 
            +
                        Store.new( @dest, @source.element( index ) ).demand
         | 
| 89 | 
            +
                        index.store index + 1
         | 
| 90 | 
            +
                      end, proc do
         | 
| 91 | 
            +
                        Store.new( @dest, @default ).demand
         | 
| 92 | 
            +
                      end )
         | 
| 93 | 
            +
                    end
         | 
| 94 | 
            +
                    @index.store index
         | 
| 95 | 
            +
                    @dest
         | 
| 96 | 
            +
                  else
         | 
| 97 | 
            +
                    super
         | 
| 98 | 
            +
                  end
         | 
| 99 | 
            +
                end
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                # Substitute variables
         | 
| 102 | 
            +
                #
         | 
| 103 | 
            +
                # Substitute the variables with the values given in the hash.
         | 
| 104 | 
            +
                #
         | 
| 105 | 
            +
                # @param [Hash] hash Substitutions to apply.
         | 
| 106 | 
            +
                #
         | 
| 107 | 
            +
                # @return [Node] Term with substitutions applied.
         | 
| 108 | 
            +
                #
         | 
| 109 | 
            +
                # @private
         | 
| 110 | 
            +
                def subst( hash )
         | 
| 111 | 
            +
                  self.class.new @dest.subst( hash ), @source.subst( hash ), @m.subst( hash ),
         | 
| 112 | 
            +
                                 @index.subst( hash ), @default.subst( hash )
         | 
| 113 | 
            +
                end
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                # Get variables contained in this term
         | 
| 116 | 
            +
                #
         | 
| 117 | 
            +
                # @return [Set] Returns list of variables.
         | 
| 118 | 
            +
                #
         | 
| 119 | 
            +
                # @private
         | 
| 120 | 
            +
                def variables
         | 
| 121 | 
            +
                  @dest.variables + @source.variables + @m.variables + @index.variables +
         | 
| 122 | 
            +
                    @default.variables
         | 
| 123 | 
            +
                end
         | 
| 124 | 
            +
             | 
| 125 | 
            +
                # Strip of all values
         | 
| 126 | 
            +
                #
         | 
| 127 | 
            +
                # Split up into variables, values, and a term where all values have been
         | 
| 128 | 
            +
                # replaced with variables.
         | 
| 129 | 
            +
                #
         | 
| 130 | 
            +
                # @return [Array<Array,Node>] Returns an array of variables, an array of
         | 
| 131 | 
            +
                # values, and the term based on variables.
         | 
| 132 | 
            +
                #
         | 
| 133 | 
            +
                # @private
         | 
| 134 | 
            +
                def strip
         | 
| 135 | 
            +
                  stripped = [ @dest, @source, @m, @index, @default ].
         | 
| 136 | 
            +
                    collect { |value| value.strip }
         | 
| 137 | 
            +
                  return stripped.inject( [] ) { |vars,elem| vars + elem[ 0 ] },
         | 
| 138 | 
            +
                       stripped.inject( [] ) { |values,elem| values + elem[ 1 ] },
         | 
| 139 | 
            +
                       self.class.new( *stripped.collect { |elem| elem[ 2 ] } )
         | 
| 140 | 
            +
                end
         | 
| 141 | 
            +
             | 
| 142 | 
            +
                # Check whether this term is compilable
         | 
| 143 | 
            +
                #
         | 
| 144 | 
            +
                # @return [Boolean] Returns whether this term is compilable.
         | 
| 145 | 
            +
                #
         | 
| 146 | 
            +
                # @private
         | 
| 147 | 
            +
                def compilable?
         | 
| 148 | 
            +
                  [ @dest, @source, @m, @index, @default ].all? { |value| value.compilable? }
         | 
| 149 | 
            +
                end
         | 
| 150 | 
            +
             | 
| 151 | 
            +
              end
         | 
| 152 | 
            +
             | 
| 153 | 
            +
            end
         | 
| 154 | 
            +
             | 
    
        data/test/tc_multiarray.rb
    CHANGED
    
    | @@ -705,4 +705,31 @@ class TC_MultiArray < Test::Unit::TestCase | |
| 705 705 | 
             
                             M( I, 3, 2 )[ [ 1, 2, 3 ], [ 4, 5, 6 ] ].integral
         | 
| 706 706 | 
             
              end
         | 
| 707 707 |  | 
| 708 | 
            +
              def test_mask
         | 
| 709 | 
            +
                [ O, I ].each do |t|
         | 
| 710 | 
            +
                  assert_equal M( O, 2, 2 )[ [ 1, 2 ], [ 5, 7 ] ],
         | 
| 711 | 
            +
                               M( O, 2, 3 )[ [ 1, 2 ], [ 3, 4 ], [ 5, 7 ] ].
         | 
| 712 | 
            +
                               mask( S[ true, false, true ] )
         | 
| 713 | 
            +
                  assert_equal S( O, 3 )[ 2, 5, 7 ], M( O, 3, 2 )[ [ 1, 2, 3 ], [ 4, 5, 7 ] ].
         | 
| 714 | 
            +
                               mask( M[ [ false, true, false ], [ false, true, true ] ] )
         | 
| 715 | 
            +
                  assert_raise( RuntimeError ) do
         | 
| 716 | 
            +
                    M( O, 2, 3 )[ [ 1, 2 ], [ 3, 4 ], [ 5, 7 ] ].mask S[ false, true ]
         | 
| 717 | 
            +
                  end
         | 
| 718 | 
            +
                end
         | 
| 719 | 
            +
              end
         | 
| 720 | 
            +
             | 
| 721 | 
            +
              def test_unmask
         | 
| 722 | 
            +
                [ O, I ].each do |t|
         | 
| 723 | 
            +
                  assert_equal M( t, 2, 3 )[ [ 1, 2 ], [ 4, 4 ], [ 5, 7 ] ],
         | 
| 724 | 
            +
                               M( t, 2, 2 )[ [ 1, 2 ], [ 5, 7 ] ].
         | 
| 725 | 
            +
                               unmask( S[ true, false, true ], :default => S[ 3, 4, 5 ] )
         | 
| 726 | 
            +
                  assert_equal M( t, 3, 2 )[ [ 0, 2, 0 ], [ 0, 5, 7 ] ],
         | 
| 727 | 
            +
                               S( t, 3 )[ 2, 5, 7 ].
         | 
| 728 | 
            +
                               unmask( M[ [ false, true, false ], [ false, true, true ] ],
         | 
| 729 | 
            +
                                       :default => 0 )
         | 
| 730 | 
            +
                  assert_raise( RuntimeError ) { S( t, 1 )[ 1 ].unmask M[ [ true, true ] ] }
         | 
| 731 | 
            +
                end
         | 
| 732 | 
            +
              end
         | 
| 733 | 
            +
             | 
| 708 734 | 
             
            end
         | 
| 735 | 
            +
             | 
    
        data/test/tc_sequence.rb
    CHANGED
    
    | @@ -893,4 +893,27 @@ class TC_Sequence < Test::Unit::TestCase | |
| 893 893 | 
             
                assert_equal S( I, 3 )[ 1, 3, 6 ], S( I, 3 )[ 1, 2, 3 ].integral
         | 
| 894 894 | 
             
              end
         | 
| 895 895 |  | 
| 896 | 
            +
              def test_mask
         | 
| 897 | 
            +
                assert_equal S( O, 2 )[ 2, 5 ], S( O, 3 )[ 2, 3, 5 ].
         | 
| 898 | 
            +
                             mask( S[ true, false, true ] )
         | 
| 899 | 
            +
                assert_equal S( I, 2 )[ 2, 5 ], S( I, 3 )[ 2, 3, 5 ].
         | 
| 900 | 
            +
                             mask( S[ true, false, true ] )
         | 
| 901 | 
            +
                assert_raise( RuntimeError ) { S[ 1, 2 ].mask S[ true ] }
         | 
| 902 | 
            +
              end
         | 
| 903 | 
            +
             | 
| 904 | 
            +
              def test_unmask
         | 
| 905 | 
            +
                [ O, I ].each do |t|
         | 
| 906 | 
            +
                  assert_equal S( t, 3 )[ 2, 3, 5 ],
         | 
| 907 | 
            +
                               S( t, 2 )[ 2, 5 ].unmask( S[ true, false, true ], :default => 3 )
         | 
| 908 | 
            +
                  assert_equal S( t, 3 )[ 2, 3, 5 ],
         | 
| 909 | 
            +
                               S( t, 2 )[ 2, 5 ].unmask( S[ true, false, true ],
         | 
| 910 | 
            +
                                                         :default => S[ 2, 3, 4 ] )
         | 
| 911 | 
            +
                  assert_raise( RuntimeError ) do
         | 
| 912 | 
            +
                    S( t, 1 )[ 1 ].unmask S[ true ], :default => S[ 1, 2 ]
         | 
| 913 | 
            +
                  end
         | 
| 914 | 
            +
                  assert_raise( RuntimeError ) { S( t, 1 )[ 1 ].unmask S[ true, true ] }
         | 
| 915 | 
            +
                end
         | 
| 916 | 
            +
              end
         | 
| 917 | 
            +
             | 
| 896 918 | 
             
            end
         | 
| 919 | 
            +
             | 
    
        metadata
    CHANGED
    
    | @@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version | |
| 4 4 | 
             
              prerelease: false
         | 
| 5 5 | 
             
              segments: 
         | 
| 6 6 | 
             
              - 0
         | 
| 7 | 
            -
              -  | 
| 7 | 
            +
              - 17
         | 
| 8 8 | 
             
              - 0
         | 
| 9 | 
            -
              version: 0. | 
| 9 | 
            +
              version: 0.17.0
         | 
| 10 10 | 
             
            platform: ruby
         | 
| 11 11 | 
             
            authors: 
         | 
| 12 12 | 
             
            - Jan Wedekind
         | 
| @@ -14,7 +14,7 @@ autorequire: | |
| 14 14 | 
             
            bindir: bin
         | 
| 15 15 | 
             
            cert_chain: []
         | 
| 16 16 |  | 
| 17 | 
            -
            date:  | 
| 17 | 
            +
            date: 2011-01-02 00:00:00 +01:00
         | 
| 18 18 | 
             
            default_executable: 
         | 
| 19 19 | 
             
            dependencies: 
         | 
| 20 20 | 
             
            - !ruby/object:Gem::Dependency 
         | 
| @@ -77,8 +77,10 @@ files: | |
| 77 77 | 
             
            - lib/multiarray/methods.rb
         | 
| 78 78 | 
             
            - lib/multiarray/integral.rb
         | 
| 79 79 | 
             
            - lib/multiarray/multiarray.rb
         | 
| 80 | 
            +
            - lib/multiarray/unmask.rb
         | 
| 80 81 | 
             
            - lib/multiarray/node.rb
         | 
| 81 82 | 
             
            - lib/multiarray/histogram.rb
         | 
| 83 | 
            +
            - lib/multiarray/mask.rb
         | 
| 82 84 | 
             
            - lib/multiarray/malloc.rb
         | 
| 83 85 | 
             
            - lib/multiarray/index.rb
         | 
| 84 86 | 
             
            - lib/multiarray/rgb.rb
         |