Class: Array

Inherits:
Object show all
Defined in:
lib/multiarray.rb,
lib/multiarray/operations.rb

Overview

The Array class is extended with a few methods

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.gauss_blur_filter(sigma, max_error = 1.0 / 0x100) ⇒ Array

Compute Gauss blur filter

Compute a filter for approximating a Gaussian blur. The size of the filter is determined by the given error bound.

Parameters:

  • sigma (Float)

    Spread of blur filter.

  • max_error (Float) (defaults to: 1.0 / 0x100)

    Upper bound for filter error.

Returns:

  • (Array)

    An array with the filter elements.



623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
# File 'lib/multiarray.rb', line 623

def gauss_blur_filter( sigma, max_error = 1.0 / 0x100 )
  # Error function
  #
  # @param [Float] x Function argument
  # @param [Float] sigma Function parameter
  #
  # @private
  def erf(x, sigma)
    0.5 * Math.erf( x / ( Math.sqrt( 2.0 ) * sigma.abs ) )
  end
  raise 'Sigma must be greater than zero.' if sigma <= 0
  # Integral of Gauss-bell from -0.5 to +0.5.
  integral = erf( +0.5, sigma ) - erf( -0.5, sigma )
  retVal = [ integral ]
  while 1.0 - integral > max_error
    # Integral of Gauss-bell from -size2 to +size2.
    size2 = 0.5 * ( retVal.size + 2 )
    nIntegral = erf( +size2, sigma ) - erf( -size2, sigma )
    value = 0.5 * ( nIntegral - integral )
    retVal.unshift value
    retVal.push value
    integral = nIntegral
  end
  # Normalise result.
  retVal.collect { |element| element / integral }
end

.gauss_gradient_filter(sigma, max_error = 1.0 / 0x100) ⇒ Array

Compute Gauss gradient filter

Compute a filter for approximating a Gaussian gradient. The size of the filter is determined by the given error bound.

Parameters:

  • sigma (Float)

    Spread of blur filter.

  • max_error (Float) (defaults to: 1.0 / 0x100)

    Upper bound for filter error.

Returns:

  • (Array)

    An array with the filter elements.



659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
# File 'lib/multiarray.rb', line 659

def gauss_gradient_filter( sigma, max_error = 1.0 / 0x100 )
  # Gaussian function
  #
  # @param [Float] x Function argument
  # @param [Float] sigma Function parameter
  #
  # @private
  def gauss(x, sigma)
    1.0 / ( Math.sqrt( 2.0 * Math::PI ) * sigma.abs ) *
      Math.exp( -x**2 / ( 2.0 * sigma**2 ) )
  end
  raise 'Sigma must be greater than zero.' if sigma <= 0
  # Integral of Gauss-gradient from -0.5 to +0.5.
  retVal = [ gauss( +0.5, sigma ) - gauss( -0.5, sigma ) ]
  # Absolute integral of Gauss-gradient from 0.5 to infinity.
  integral = gauss( 0.5, sigma )
  sumX = 0
  while 2.0 * integral > max_error
    size2 = 0.5 * ( retVal.size + 2 )
    nIntegral = gauss( size2, sigma )
    value = integral - nIntegral
    retVal.unshift +value
    retVal.push -value
    sumX += value * ( retVal.size - 1 )
    integral = nIntegral
  end
  retVal.collect { |element| element / sumX }
end

Instance Method Details

#collect_with_index(&action) ⇒ Array<Object>

Element-wise operation based on element and its index

Same as Array#collect but with index.

Parameters:

  • &action

    Closure accepting an element and an index.

Returns:



697
698
699
# File 'lib/multiarray.rb', line 697

def collect_with_index( &action )
  zip( ( 0 ... size ).to_a ).collect &action
end

#erf(x, sigma) ⇒ Object

Error function

Parameters:

  • x (Float)

    Function argument

  • sigma (Float)

    Function parameter



630
631
632
# File 'lib/multiarray.rb', line 630

def erf(x, sigma)
  0.5 * Math.erf( x / ( Math.sqrt( 2.0 ) * sigma.abs ) )
end

#gauss(x, sigma) ⇒ Object

Gaussian function

Parameters:

  • x (Float)

    Function argument

  • sigma (Float)

    Function parameter



666
667
668
669
# File 'lib/multiarray.rb', line 666

def gauss(x, sigma)
  1.0 / ( Math.sqrt( 2.0 * Math::PI ) * sigma.abs ) *
    Math.exp( -x**2 / ( 2.0 * sigma**2 ) )
end

#histogram(*ret_shape, options = {}) ⇒ Node

Compute histogram of this array

Parameters:

  • ret_shape (Array<Integer>)

    Dimensions of resulting histogram.

Options Hash (options):

  • :weight (Node) — default: Hornetseye::UINT(1)

    Weights for computing the histogram.

  • :safe (Boolean) — default: true

    Do a boundary check before creating the histogram.

Returns:

  • (Node)

    The histogram.



913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
# File 'lib/multiarray/operations.rb', line 913

def histogram( *ret_shape )
  options = ret_shape.last.is_a?( Hash ) ? ret_shape.pop : {}
  options = { :weight => Hornetseye::UINT. new( 1 ), :safe => true }.merge options
  unless options[:weight].matched?
    options[:weight] =
      Hornetseye::Node.match( options[ :weight ] ).maxint.new options[ :weight ]
  end
  weight = options[ :weight ]
  if options[ :safe ]
    if size != ret_shape.size
      raise "Number of arrays for histogram (#{size}) differs from number of " +
            "dimensions of histogram (#{ret_shape.size})"
    end
    source_type = inject { |a,b| a.dimension > b.dimension ? a : b }
    source_type.check_shape *self
    source_type.check_shape options[ :weight ]
    for i in 0 ... size
      range = self[ i ].range 0 ... ret_shape[ i ]
      if range.begin < 0
        raise "#{i+1}th dimension of index must be in 0 ... #{ret_shape[i]} " +
              "(but was #{range.begin})"
      end
      if range.end >= ret_shape[ i ]
        raise "#{i+1}th dimension of index must be in 0 ... #{ret_shape[i]} " +
              "(but was #{range.end})"
      end
    end
  end
  left = Hornetseye::MultiArray(weight.typecode, ret_shape.size).new *ret_shape
  left[] = 0
  block = Hornetseye::Histogram.new left.sexp, weight.sexp, *self
  if block.compilable?
    Hornetseye::GCCFunction.run block
  else
    block.demand
  end
  left
end

#lut(table, options = {}) ⇒ Node

Perform element-wise lookup

Parameters:

  • table (Node)

    The lookup table (LUT).

  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • :safe (Boolean) — default: true

    Do a boundary check before creating the element-wise lookup.

Returns:

  • (Node)

    The result of the lookup operation.



959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
# File 'lib/multiarray/operations.rb', line 959

def lut( table, options = {} )
  options = { :safe => true }.merge options
  if options[ :safe ]
    if size > table.dimension
      raise "Number of arrays for lookup (#{size}) is greater than the " +
            "number of dimensions of LUT (#{table.dimension})"
    end
    source_type = inject { |a,b| a.dimension > b.dimension ? a : b }
    source_type.check_shape *self
    for i in 0 ... size
      offset = table.dimension - size
      range = self[ i ].range 0 ... table.shape[ i + offset ]
      if range.begin < 0
        raise "#{i+1}th index must be in 0 ... #{table.shape[i]} " +
              "(but was #{range.begin})"
      end
      if range.end >= table.shape[ i + offset ]
        raise "#{i+1}th index must be in 0 ... " +
              "#{table.shape[ i + offset ]} (but was #{range.end})"
      end
    end
  end
  if all? { |source| source.dimension == 0 and source.variables.empty? }
    result = table
    ( table.dimension - 1 ).downto( 0 ) do |i|
      result = result.element( self[ i ].demand ).demand
    end
    result
  else
    Hornetseye::Lut.new( *( self + [ table ] ) ).force
  end
end

#stripObject



701
702
703
704
705
# File 'lib/multiarray.rb', line 701

def strip
  collect { |arg| arg.strip }.inject [[], [], []] do |retval,s|
    [retval[0] + s[0], retval[1] + s[1], retval[2] + [s[2]]]
  end
end