Class: Hornetseye::Node
- Extended by:
- BOOL::Match, COMPLEX_::Match, FLOAT_::Match, Field_::Match, INT_::Match, OBJECT::Match, RGB_::Match
- Defined in:
- lib/multiarray/node.rb,
lib/multiarray/complex.rb,
lib/multiarray/operations.rb,
lib/multiarray/rgb.rb
Overview
Base class for representing native datatypes and operations (terms)
Direct Known Subclasses
Argument, Components, Diagonal, Element, ElementWise_, Histogram, Inject, Integral, Lambda, Lookup, Lut, Mask, Pointer_, Random, Store, Unmask, Variable
Class Method Summary collapse
-
.===(other) ⇒ Boolean
Category operator.
-
.basetype ⇒ Class
Base type of this data type.
-
.bool ⇒ Class
Get corresponding boolean-based datatype.
-
.byte ⇒ Class
Convert to type based on bytes.
-
.coercion_bool(other) ⇒ Class
Get boolean-based datatype for binary operation.
-
.coercion_byte(other) ⇒ Class
Get byte-based datatype for binary operation.
-
.coercion_maxint(other) ⇒ Class
Get maximum integer based datatype for binary operation.
-
.compilable? ⇒ Boolean
Check whether this term is compilable.
-
.cond(a, b) ⇒ Class
Get byte-based datatype for ternary operation.
-
.define_binary_op(op, coercion = :coercion) ⇒ Proc
Meta-programming method to define a binary operation.
-
.define_unary_op(op, conversion = :identity) ⇒ Proc
Meta-programming method to define a unary operation.
-
.descriptor(hash) ⇒ String
Get unique descriptor of this class.
-
.dimension ⇒ Array<Integer>
Get dimension of this term.
-
.finalised? ⇒ Boolean
Check whether objects of this class are finalised computations.
-
.float ⇒ Class
Convert to type based on floating point numbers.
-
.float_scalar ⇒ Class
Get corresponding type based on floating-point scalars.
-
.floating(other) ⇒ Class
Get floating point based datatype for binary operation.
-
.identity ⇒ Class
Get this data type.
-
.indgen(offset = 0, increment = 1) ⇒ Object
Generate index array of this type.
-
.match(value, context = nil) ⇒ Class
Find matching native datatype to a Ruby value.
-
.maxint ⇒ Class
Get corresponding maximal integer type.
-
.rgb? ⇒ Boolean
Check whether this object is an RGB value.
-
.scalar ⇒ Class
Get corresponding scalar type.
- .shape ⇒ Object
-
.strip ⇒ Array<Array,Node>
Strip of all values.
-
.subst(hash) ⇒ Node
Substitute variables.
-
.to_s ⇒ String
Get unique descriptor of this class.
-
.to_type(dest) ⇒ Class
Convert to different element type.
-
.typecode ⇒ Class
Element-type of this term.
-
.typecodes ⇒ Array<Class>
Get list of types of composite type.
-
.variables ⇒ Set
Get variables contained in this datatype.
Instance Method Summary collapse
-
#+@ ⇒ Node
This operation has no effect.
-
#<=>(other) ⇒ Node
Element-wise comparison of values.
-
#[](*indices) ⇒ Object, Node
Retrieve value of array element(s).
-
#[]=(*indices, value) ⇒ Object, Node
Assign value to array element(s).
- #allocate ⇒ Object
-
#b=(value) ⇒ Object
Assignment for blue channel values of RGB array.
-
#b_with_decompose ⇒ Node
Fast extraction for blue channel of RGB array.
-
#basetype ⇒ Class
Base-type of this term.
-
#between?(a, b) ⇒ Node
Check values against boundaries.
-
#check_shape(*args) ⇒ Object
Check arguments for compatible shape.
-
#clip(range = 0 .. 0xFF) ⇒ Node
Clip values to specified range.
-
#coerce(other) ⇒ Array<Node>
Coerce with other object.
-
#collect(&action) ⇒ Node
(also: #map)
Perform element-wise operation on array.
-
#compilable? ⇒ Boolean
Check whether this term is compilable.
-
#components(options = {}) ⇒ Node
Perform connected component labeling.
-
#conditional(a, b) ⇒ Node
Element-wise conditional selection of values.
-
#convolve(filter) ⇒ Node
Convolution with other array of same dimension.
-
#decompose(i) ⇒ Node
Decompose composite elements.
-
#demand ⇒ Node, Object
Reevaluate computation.
-
#descriptor(hash) ⇒ String
Get unique descriptor of this object.
-
#diagonal(initial = nil, options = {}) { ... } ⇒ Node
Apply accumulative operation over elements diagonally.
-
#dilate(n = 3) ⇒ Node
Dilation.
-
#dimension ⇒ Array<Integer>
Get dimension of this term.
-
#downsample(*rate, options = {}) ⇒ Node
Downsampling of arrays.
-
#dup ⇒ Node
Duplicate object.
- #each(&action) ⇒ Object
-
#empty? ⇒ Boolean
Check whether this object is an empty array.
-
#eq_with_multiarray(other) ⇒ Boolean
Equality operator.
-
#erode(n = 3) ⇒ Node
Erosion.
-
#fill!(value = typecode.default) ⇒ Node
Fill array with a value.
-
#finalised? ⇒ Boolean
Check whether this object is a finalised computation.
-
#flip(*dimensions) ⇒ Node
Mirror the array.
-
#fmod_with_float(other) ⇒ Node
Modulo operation for floating point numbers.
-
#force ⇒ Node, Object
Force delayed computation unless in lazy mode.
-
#g=(value) ⇒ Object
Assignment for green channel values of RGB array.
-
#g_with_decompose ⇒ Node
Fast extraction for green channel of RGB array.
-
#gauss_blur(sigma, max_error = 1.0 / 0x100) ⇒ Node
Gaussian blur.
-
#gauss_gradient(sigma, direction, max_error = 1.0 / 0x100) ⇒ Node
Gauss gradient.
-
#get ⇒ Node, Object
Extract native value if this is an element.
-
#height ⇒ Integer
Get height of two-dimensional array.
-
#histogram(*ret_shape, options = {}) ⇒ Node
Compute histogram of this array.
-
#histogram(*ret_shape, options = {}) ⇒ Node
Compute colour histogram of this array.
-
#if(&action) ⇒ Object
Conditional operation.
-
#if_else(action1, action2) ⇒ Object
Conditional operation.
-
#imag=(value) ⇒ Object
Assignment for imaginary values of complex array.
-
#imag_with_decompose ⇒ Node
Fast extraction of imaginary values of complex array.
-
#inject(*args, &action) ⇒ Object
Perform cummulative operation on array.
-
#inspect(indent = nil, lines = nil) ⇒ String
Display information about this object.
-
#integral ⇒ Node
Compute integral image.
-
#lut(table, options = {}) ⇒ Node
Perform element-wise lookup.
-
#lut_with_rgb(table, options = {}) ⇒ Node
Perform element-wise lookup with colour values.
-
#malloc ⇒ GCCValue
Generate code for memory allocation.
-
#mask(m) ⇒ Node
Select values from array using a mask.
- #matched? ⇒ Boolean
-
#max(initial = nil) ⇒ Object
Find maximum value of array.
-
#mean ⇒ Object
Compute average of array.
-
#memorise ⇒ Node
Duplicate array expression if it is not in row-major format.
-
#memory ⇒ Malloc, ...
Get memory object.
-
#min(initial = nil) ⇒ Object
Find minimum value of array.
-
#normalise(range = 0 .. 0xFF) ⇒ Node
Normalise values of array.
-
#prod ⇒ Object
Compute product of array.
-
#r=(value) ⇒ Object
Assignment for red channel values of RGB array.
-
#r_with_decompose ⇒ Node
Fast extraction for red channel of RGB array.
-
#range(initial = nil) ⇒ Object
Find range of values of array.
-
#real=(value) ⇒ Object
Assignment for real values of complex array.
-
#real_with_decompose ⇒ Node
Fast extraction for real values of complex array.
-
#reshape(*ret_shape) ⇒ Node
Get array with same elements but different shape.
-
#rgb? ⇒ Boolean
Check whether this object is an RGB value.
-
#roll(n = 1) ⇒ Node
Cycle indices of array.
-
#shape ⇒ Array<Integer>
Get shape of this term.
-
#shift(*offset) ⇒ Node
Create array with shifted elements.
-
#simplify ⇒ Node, Object
Reevaluate term.
-
#size ⇒ Integer
Get size (number of elements) of this value.
-
#sobel(direction) ⇒ Node
Sobel operator.
-
#stretch(from = 0 .. 0xFF, to = 0 .. 0xFF) ⇒ Node
Stretch values from one range to another.
-
#stride(index) ⇒ Integer, NilClass
Get stride for specific index.
-
#strides ⇒ Array<Integer>, NilClass
Get strides of array.
-
#strip ⇒ Array<Array,Node>
Strip of all values.
-
#subst(hash) ⇒ Node
Substitute variables.
-
#sum ⇒ Object
Compute sum of array.
-
#swap_rgb_with_scalar ⇒ Node
Swapping colour channels for scalar values.
-
#table(filter, &action) ⇒ Node
Compute table from two arrays.
-
#to_a ⇒ Array<Object>
Convert to Ruby array of objects.
-
#to_s ⇒ String
Get unique descriptor of this object.
-
#to_type(dest) ⇒ Node
Convert array elements to different element type.
-
#to_type_with_identity(dest) ⇒ Node
Skip type conversion if it has no effect.
-
#to_type_with_rgb(dest) ⇒ Node
Convert RGB array to scalar array.
-
#transpose(*order) ⇒ Node
Lazy transpose of array.
-
#typecode ⇒ Class
Element-type of this term.
-
#unmask(m, options = {}) ⇒ Node
Distribute values in a new array using a mask.
-
#unroll(n = 1) ⇒ Node
Reverse-cycle indices of array.
-
#variables ⇒ Set
Get variables contained in this object.
-
#warp(*field, options = {}) ⇒ Node
Warp an array.
-
#width ⇒ Integer
Get width of two-dimensional array.
Methods included from Field_::Match
Methods included from FLOAT_::Match
Methods included from OBJECT::Match
Methods included from COMPLEX_::Match
Methods included from BOOL::Match
Methods included from RGB_::Match
Methods included from INT_::Match
Class Method Details
.===(other) ⇒ Boolean
Category operator
233 234 235 |
# File 'lib/multiarray/node.rb', line 233 def ===( other ) ( other == self ) or ( other.is_a? self ) or ( other.class == self ) end |
.basetype ⇒ Class
Base type of this data type
74 75 76 |
# File 'lib/multiarray/node.rb', line 74 def basetype self end |
.bool ⇒ Class
Get corresponding boolean-based datatype
127 128 129 |
# File 'lib/multiarray/node.rb', line 127 def bool BOOL end |
.byte ⇒ Class
Convert to type based on bytes
189 190 191 |
# File 'lib/multiarray/node.rb', line 189 def byte BYTE end |
.coercion_bool(other) ⇒ Class
Get boolean-based datatype for binary operation
148 149 150 |
# File 'lib/multiarray/node.rb', line 148 def coercion_bool( other ) other.coercion( self ).bool end |
.coercion_byte(other) ⇒ Class
Get byte-based datatype for binary operation
198 199 200 |
# File 'lib/multiarray/node.rb', line 198 def coercion_byte( other ) coercion( other ).byte end |
.coercion_maxint(other) ⇒ Class
Get maximum integer based datatype for binary operation
164 165 166 |
# File 'lib/multiarray/node.rb', line 164 def coercion_maxint( other ) coercion( other ).maxint end |
.compilable? ⇒ Boolean
Check whether this term is compilable
268 269 270 |
# File 'lib/multiarray/node.rb', line 268 def compilable? true end |
.cond(a, b) ⇒ Class
Get byte-based datatype for ternary operation
208 209 210 |
# File 'lib/multiarray/node.rb', line 208 def cond(a, b) a.coercion b end |
.define_binary_op(op, coercion = :coercion) ⇒ Proc
Meta-programming method to define a binary operation
56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/multiarray/operations.rb', line 56 def define_binary_op(op, coercion = :coercion) define_method op do |other| other = Node.match(other, typecode).new other unless other.matched? if dimension == 0 and variables.empty? and other.dimension == 0 and other.variables.empty? target = typecode.send coercion, other.typecode target.new simplify.get.send(op, other.simplify.get) else Hornetseye::ElementWise(proc { |x,y| x.send op, y }, op, proc { |t,u| t.send coercion, u } ). new(self, other).force end end end |
.define_unary_op(op, conversion = :identity) ⇒ Proc
Meta-programming method to define a unary operation
33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/multiarray/operations.rb', line 33 def define_unary_op(op, conversion = :identity) Node.class_eval do define_method op do if dimension == 0 and variables.empty? target = typecode.send conversion target.new simplify.get.send(op) else Hornetseye::ElementWise(proc { |x| x.send op }, op, proc { |t| t.send conversion }). new(self).force end end end end |
.descriptor(hash) ⇒ String
Get unique descriptor of this class
45 46 47 |
# File 'lib/multiarray/node.rb', line 45 def descriptor( hash ) name end |
.dimension ⇒ Array<Integer>
Get dimension of this term
104 105 106 |
# File 'lib/multiarray/node.rb', line 104 def dimension 0 end |
.finalised? ⇒ Boolean
Check whether objects of this class are finalised computations
277 278 279 |
# File 'lib/multiarray/node.rb', line 277 def finalised? true end |
.float ⇒ Class
Convert to type based on floating point numbers
173 174 175 |
# File 'lib/multiarray/node.rb', line 173 def float DFLOAT end |
.float_scalar ⇒ Class
Get corresponding type based on floating-point scalars
141 142 143 |
# File 'lib/multiarray/node.rb', line 141 def float_scalar float.scalar end |
.floating(other) ⇒ Class
Get floating point based datatype for binary operation
180 181 182 |
# File 'lib/multiarray/node.rb', line 180 def floating( other ) other.coercion( self ).float end |
.identity ⇒ Class
Get this data type
113 114 115 |
# File 'lib/multiarray/node.rb', line 113 def identity self end |
.indgen(offset = 0, increment = 1) ⇒ Object
Generate index array of this type
97 98 99 |
# File 'lib/multiarray/node.rb', line 97 def indgen( offset = 0, increment = 1 ) offset end |
.match(value, context = nil) ⇒ Class
Find matching native datatype to a Ruby value
56 57 58 59 60 |
# File 'lib/multiarray/node.rb', line 56 def match( value, context = nil ) retval = fit value retval = retval.align context.basetype if context retval end |
.maxint ⇒ Class
Get corresponding maximal integer type
157 158 159 |
# File 'lib/multiarray/node.rb', line 157 def maxint self end |
.rgb? ⇒ Boolean
Check whether this object is an RGB value
120 121 122 |
# File 'lib/multiarray/node.rb', line 120 def rgb? false end |
.scalar ⇒ Class
Get corresponding scalar type
134 135 136 |
# File 'lib/multiarray/node.rb', line 134 def scalar self end |
.shape ⇒ Object
87 88 89 |
# File 'lib/multiarray/node.rb', line 87 def shape [] end |
.strip ⇒ Array<Array,Node>
Strip of all values
Split up into variables, values, and a term where all values have been replaced with variables.
values, and the term based on variables.
246 247 248 |
# File 'lib/multiarray/node.rb', line 246 def strip return [], [], self end |
.subst(hash) ⇒ Node
Substitute variables
Substitute the variables with the values given in the hash.
259 260 261 |
# File 'lib/multiarray/node.rb', line 259 def subst( hash ) hash[ self ] || self end |
.to_s ⇒ String
Get unique descriptor of this class
The method calls descriptor( {} ).
34 35 36 |
# File 'lib/multiarray/node.rb', line 34 def to_s descriptor( {} ) end |
.to_type(dest) ⇒ Class
Convert to different element type
217 218 219 |
# File 'lib/multiarray/node.rb', line 217 def to_type( dest ) dest end |
.typecode ⇒ Class
Element-type of this term
65 66 67 |
# File 'lib/multiarray/node.rb', line 65 def typecode self end |
.typecodes ⇒ Array<Class>
Get list of types of composite type
83 84 85 |
# File 'lib/multiarray/node.rb', line 83 def typecodes [ self ] end |
.variables ⇒ Set
Get variables contained in this datatype
226 227 228 |
# File 'lib/multiarray/node.rb', line 226 def variables Set[] end |
Instance Method Details
#+@ ⇒ Node
This operation has no effect
112 113 114 |
# File 'lib/multiarray/operations.rb', line 112 def +@ self end |
#<=>(other) ⇒ Node
Element-wise comparison of values
261 262 263 264 265 |
# File 'lib/multiarray/operations.rb', line 261 def <=>(other) Hornetseye::lazy do (self < other).conditional -1, (self > other).conditional(1, 0) end.force end |
#[](*indices) ⇒ Object, Node
Retrieve value of array element(s)
549 550 551 552 553 554 555 556 557 558 559 560 |
# File 'lib/multiarray/node.rb', line 549 def []( *indices ) if indices.empty? force else if indices.last.is_a? Range view = slice indices.last.min, indices.last.size else view = element indices.last end view[ *indices[ 0 ... -1 ] ] end end |
#[]=(*indices, value) ⇒ Object, Node
Assign value to array element(s)
595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 |
# File 'lib/multiarray/node.rb', line 595 def []=( *indices ) value = indices.pop value = typecode.new value unless value.matched? if indices.empty? check_shape value unless compilable? and value.compilable? and dimension > 0 Store.new(self, value).demand else GCCFunction.run Store.new(self, value) end value else if indices.last.is_a? Range view = slice indices.last.min, indices.last.size else view = element indices.last end view[*indices[0 ... -1]] = value end end |
#allocate ⇒ Object
287 288 289 |
# File 'lib/multiarray/node.rb', line 287 def allocate Hornetseye::MultiArray(typecode, dimension).new *shape end |
#b=(value) ⇒ Object
Assignment for blue channel values of RGB array
612 613 614 615 616 617 618 619 620 621 622 |
# File 'lib/multiarray/rgb.rb', line 612 def b=(value) if typecode < RGB_ decompose( 2 )[] = value elsif typecode == OBJECT self[] = Hornetseye::lazy do r * RGB.new( 1, 0, 0 ) + g * RGB.new( 0, 1, 0 ) + value * RGB.new( 0, 0, 1 ) end else raise "Cannot assign blue channel to elements of type #{typecode.inspect}" end end |
#b_with_decompose ⇒ Node
Fast extraction for blue channel of RGB array
595 596 597 598 599 600 601 602 603 |
# File 'lib/multiarray/rgb.rb', line 595 def b_with_decompose if typecode == OBJECT or is_a?(Variable) or Thread.current[:lazy] b_without_decompose elsif typecode < RGB_ decompose 2 else self end end |
#basetype ⇒ Class
Base-type of this term
301 302 303 |
# File 'lib/multiarray/node.rb', line 301 def basetype self.class.basetype end |
#between?(a, b) ⇒ Node
Check values against boundaries
468 469 470 |
# File 'lib/multiarray/operations.rb', line 468 def between?( a, b ) Hornetseye::lazy { ( self >= a ).and self <= b }.force end |
#check_shape(*args) ⇒ Object
Check arguments for compatible shape
The method will throw an exception if one of the arguments has an incompatible shape.
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 |
# File 'lib/multiarray/node.rb', line 570 def check_shape(*args) _shape = shape args.each do |arg| _arg_shape = arg.shape if _shape.size < _arg_shape.size raise "#{arg.inspect} has #{arg.dimension} dimension(s) " + "but should not have more than #{dimension}" end if ( _shape + _arg_shape ).all? { |s| s.is_a? Integer } if _shape.last( _arg_shape.size ) != _arg_shape raise "#{arg.inspect} has shape #{arg.shape.inspect} " + "(does not match last value(s) of #{shape.inspect})" end end end end |
#clip(range = 0 .. 0xFF) ⇒ Node
Clip values to specified range
503 504 505 506 507 508 509 |
# File 'lib/multiarray/operations.rb', line 503 def clip( range = 0 .. 0xFF ) if range.exclude_end? raise "Clipping does not support ranges with end value " + "excluded (such as #{range})" end collect { |x| x.major( range.begin ).minor range.end } end |
#coerce(other) ⇒ Array<Node>
Coerce with other object
690 691 692 693 694 695 696 |
# File 'lib/multiarray/node.rb', line 690 def coerce(other) if other.matched? return other, self else return Node.match(other, self).new(other), self end end |
#collect(&action) ⇒ Node Also known as: map
Perform element-wise operation on array
324 325 326 327 328 329 |
# File 'lib/multiarray/operations.rb', line 324 def collect(&action) var = Variable.new typecode block = action.call var conversion = proc { |t| t.to_type action.call(Variable.new(t.typecode)).typecode } Hornetseye::ElementWise( action, block.to_s, conversion ).new( self ).force end |
#compilable? ⇒ Boolean
Check whether this term is compilable
531 532 533 |
# File 'lib/multiarray/node.rb', line 531 def compilable? typecode.compilable? end |
#components(options = {}) ⇒ Node
Perform connected component labeling
781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 |
# File 'lib/multiarray/operations.rb', line 781 def components( = {} ) if shape.any? { |x| x <= 1 } raise "Every dimension must be greater than 1 (shape was #{shape})" end = { :target => UINT, :default => typecode.default }.merge target = [ :target ] default = [ :default ] default = typecode.new default unless default.matched? left = Hornetseye::MultiArray(target, dimension).new *shape labels = Sequence.new target, size; labels[0] = 0 rank = Sequence.uint size; rank[0] = 0 n = Hornetseye::Pointer( INT ).new; n.store INT.new( 0 ) block = Components.new left, self, default, target.new(0), labels, rank, n if block.compilable? Hornetseye::GCCFunction.run block else block.demand end labels = labels[0 .. n.demand.get] left.lut labels.lut(labels.histogram(labels.size, :weight => target.new(1)). minor(1).integral - 1) end |
#conditional(a, b) ⇒ Node
Element-wise conditional selection of values
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
# File 'lib/multiarray/operations.rb', line 212 def conditional(a, b) a = Node.match(a, b.matched? ? b : nil).new a unless a.matched? b = Node.match(b, a.matched? ? a : nil).new b unless b.matched? if dimension == 0 and variables.empty? and a.dimension == 0 and a.variables.empty? and b.dimension == 0 and b.variables.empty? target = typecode.cond a.typecode, b.typecode target.new simplify.get.conditional(proc { a.simplify.get }, proc { b.simplify.get }) else Hornetseye::ElementWise(proc { |x,y,z| x.conditional y, z }, :conditional, proc { |t,u,v| t.cond u, v }). new(self, a, b).force end end |
#convolve(filter) ⇒ Node
Convolution with other array of same dimension
616 617 618 619 620 621 |
# File 'lib/multiarray/operations.rb', line 616 def convolve( filter ) filter = Node.match( filter, typecode ).new filter unless filter.matched? array = self (dimension - filter.dimension).times { array = array.roll } array.table(filter) { |a,b| a * b }.diagonal { |s,x| s + x } end |
#decompose(i) ⇒ Node
Decompose composite elements
This method decomposes composite elements into array.
703 704 705 |
# File 'lib/multiarray/node.rb', line 703 def decompose( i ) self end |
#demand ⇒ Node, Object
Reevaluate computation
645 646 647 |
# File 'lib/multiarray/node.rb', line 645 def demand self end |
#descriptor(hash) ⇒ String
Get unique descriptor of this object
500 501 502 |
# File 'lib/multiarray/node.rb', line 500 def descriptor( hash ) 'Node()' end |
#diagonal(initial = nil, options = {}) { ... } ⇒ Node
Apply accumulative operation over elements diagonally
This method is used internally to implement convolutions.
560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 |
# File 'lib/multiarray/operations.rb', line 560 def diagonal( initial = nil, = {} ) if dimension == 0 demand else if initial initial = Node.match( initial ).new initial unless initial.matched? initial_typecode = initial.typecode else initial_typecode = typecode end index0 = Variable.new Hornetseye::INDEX( nil ) index1 = Variable.new Hornetseye::INDEX( nil ) index2 = Variable.new Hornetseye::INDEX( nil ) var1 = [ :var1 ] || Variable.new( initial_typecode ) var2 = [ :var2 ] || Variable.new( typecode ) block = [ :block ] || yield( var1, var2 ) value = element( index1 ).element( index2 ). diagonal initial, :block => block, :var1 => var1, :var2 => var2 term = Diagonal.new( value, index0, index1, index2, initial, block, var1, var2 ) index0.size = index1.size Lambda.new( index0, term ).force end end |
#dilate(n = 3) ⇒ Node
Dilation
The dilation operation works on boolean as well as scalar values.
642 643 644 645 |
# File 'lib/multiarray/operations.rb', line 642 def dilate( n = 3 ) filter = Hornetseye::lazy( *( [ n ] * dimension ) ) { 0 } table( filter ) { |a,b| a }.diagonal { |m,x| m.major x } end |
#dimension ⇒ Array<Integer>
Get dimension of this term
386 387 388 |
# File 'lib/multiarray/node.rb', line 386 def dimension shape.size end |
#downsample(*rate, options = {}) ⇒ Node
Downsampling of arrays
921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 |
# File 'lib/multiarray/operations.rb', line 921 def downsample( *rate ) = rate.last.is_a?( Hash ) ? rate.pop : {} = { :offset => rate.collect { |r| r - 1 } }.merge offset = [ :offset ] if rate.size != dimension raise "#{rate.size} sampling rate(s) given but array has " + "#{dimension} dimension(s)" end if offset.size != dimension raise "#{offset.size} sampling offset(s) given but array has " + "#{dimension} dimension(s)" end ret_shape = ( 0 ... dimension ).collect do |i| ( shape[i] + rate[i] - 1 - offset[i] ).div rate[i] end field = ( 0 ... dimension ).collect do |i| Hornetseye::lazy( *ret_shape ) { |*args| args[i] * rate[i] + offset[i] } end warp *( field + [ :safe => false ] ) end |
#dup ⇒ Node
Duplicate object
507 508 509 510 511 |
# File 'lib/multiarray/node.rb', line 507 def dup retval = Hornetseye::MultiArray(typecode, dimension).new *shape retval[] = self retval end |
#each(&action) ⇒ Object
390 391 392 393 394 395 396 |
# File 'lib/multiarray/operations.rb', line 390 def each( &action ) if dimension > 0 shape.last.times { |i| element( INT.new( i ) ).each &action } else action.call demand.get end end |
#empty? ⇒ Boolean
Check whether this object is an empty array
372 373 374 |
# File 'lib/multiarray/node.rb', line 372 def empty? size == 0 end |
#eq_with_multiarray(other) ⇒ Boolean
Equality operator
401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 |
# File 'lib/multiarray/operations.rb', line 401 def eq_with_multiarray(other) if other.matched? if variables.empty? if other.typecode == typecode and other.shape == shape Hornetseye::finalise { eq(other).inject true, :and } else false end else eq_without_multiarray other end else false end end |
#erode(n = 3) ⇒ Node
Erosion
The erosion operation works on boolean as well as scalar values.
630 631 632 633 |
# File 'lib/multiarray/operations.rb', line 630 def erode( n = 3 ) filter = Hornetseye::lazy( *( [ n ] * dimension ) ) { 0 } table( filter ) { |a,b| a }.diagonal { |m,x| m.minor x } end |
#fill!(value = typecode.default) ⇒ Node
Fill array with a value
539 540 541 542 |
# File 'lib/multiarray/operations.rb', line 539 def fill!( value = typecode.default ) self[] = value self end |
#finalised? ⇒ Boolean
Check whether this object is a finalised computation
540 541 542 |
# File 'lib/multiarray/node.rb', line 540 def finalised? self.class.finalised? end |
#flip(*dimensions) ⇒ Node
Mirror the array
863 864 865 866 867 868 869 870 871 872 |
# File 'lib/multiarray/operations.rb', line 863 def flip( *dimensions ) field = ( 0 ... dimension ).collect do |i| if dimensions.member? i Hornetseye::lazy( *shape ) { |*args| shape[i] - 1 - args[i] } else Hornetseye::lazy( *shape ) { |*args| args[i] } end end warp *( field + [ :safe => false ] ) end |
#fmod_with_float(other) ⇒ Node
Modulo operation for floating point numbers
This operation takes account of the problem that ‘%’ does not work with floating-point numbers in C.
122 123 124 125 126 127 128 129 |
# File 'lib/multiarray/operations.rb', line 122 def fmod_with_float( other ) other = Node.match( other, typecode ).new other unless other.matched? if typecode < FLOAT_ or other.typecode < FLOAT_ fmod other else fmod_without_float other end end |
#force ⇒ Node, Object
Force delayed computation unless in lazy mode
656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 |
# File 'lib/multiarray/node.rb', line 656 def force if finalised? get elsif (dimension > 0 and Thread.current[:lazy]) or not variables.empty? self elsif compilable? retval = allocate GCCFunction.run Store.new(retval, self) retval.demand.get else retval = allocate Store.new(retval, self).demand retval.demand.get end end |
#g=(value) ⇒ Object
Assignment for green channel values of RGB array
580 581 582 583 584 585 586 587 588 589 590 |
# File 'lib/multiarray/rgb.rb', line 580 def g=(value) if typecode < RGB_ decompose( 1 )[] = value elsif typecode == OBJECT self[] = Hornetseye::lazy do r * RGB.new( 1, 0, 0 ) + value * RGB.new( 0, 1, 0 ) + b * RGB.new( 0, 0, 1 ) end else raise "Cannot assign green channel to elements of type #{typecode.inspect}" end end |
#g_with_decompose ⇒ Node
Fast extraction for green channel of RGB array
563 564 565 566 567 568 569 570 571 |
# File 'lib/multiarray/rgb.rb', line 563 def g_with_decompose if typecode == OBJECT or is_a?(Variable) or Thread.current[:lazy] g_without_decompose elsif typecode < RGB_ decompose 1 else self end end |
#gauss_blur(sigma, max_error = 1.0 / 0x100) ⇒ Node
Gaussian blur
666 667 668 669 670 671 672 673 |
# File 'lib/multiarray/operations.rb', line 666 def gauss_blur( sigma, max_error = 1.0 / 0x100 ) filter_type = DFLOAT.align typecode filter = Sequence[ *Array.gauss_blur_filter( sigma, max_error / dimension ) ]. to_type filter_type ( dimension - 1 ).downto( 0 ).inject self do |retval,i| retval.convolve filter end end |
#gauss_gradient(sigma, direction, max_error = 1.0 / 0x100) ⇒ Node
Gauss gradient
682 683 684 685 686 687 688 689 690 691 692 693 694 |
# File 'lib/multiarray/operations.rb', line 682 def gauss_gradient( sigma, direction, max_error = 1.0 / 0x100 ) filter_type = DFLOAT.align typecode gradient = Sequence[ *Array.gauss_gradient_filter( sigma, max_error / dimension ) ]. to_type filter_type blur = Sequence[ *Array.gauss_blur_filter( sigma, max_error / dimension ) ]. to_type filter_type ( dimension - 1 ).downto( 0 ).inject self do |retval,i| filter = i == direction ? gradient : blur retval.convolve filter end.force end |
#get ⇒ Node, Object
Extract native value if this is an element
402 403 404 |
# File 'lib/multiarray/node.rb', line 402 def get self end |
#height ⇒ Integer
Get height of two-dimensional array
315 316 317 |
# File 'lib/multiarray/node.rb', line 315 def height shape[1] end |
#histogram(*ret_shape, options = {}) ⇒ Node
Compute histogram of this array
705 706 707 708 709 710 711 712 713 714 715 716 717 |
# File 'lib/multiarray/operations.rb', line 705 def histogram( *ret_shape ) = ret_shape.last.is_a?( Hash ) ? ret_shape.pop : {} = { :weight => UINT.new( 1 ), :safe => true }.merge unless [:weight].matched? [:weight] = Node.match([:weight]).maxint.new [:weight] end if ( shape.first != 1 or dimension == 1 ) and ret_shape.size == 1 [ self ].histogram *( ret_shape + [ ] ) else ( 0 ... shape.first ).collect { |i| unroll[i] }. histogram *( ret_shape + [ ] ) end end |
#histogram(*ret_shape, options = {}) ⇒ Node
Compute colour histogram of this array
The array is decomposed to its colour channels and a histogram is computed.
649 650 651 652 653 654 655 |
# File 'lib/multiarray/rgb.rb', line 649 def histogram_with_rgb( *ret_shape ) if typecode < RGB_ [ r, g, b ].histogram *ret_shape else histogram_without_rgb *ret_shape end end |
#if(&action) ⇒ Object
Conditional operation
242 243 244 |
# File 'lib/multiarray/operations.rb', line 242 def if( &action ) simplify.get.if &action end |
#if_else(action1, action2) ⇒ Object
Conditional operation
252 253 254 |
# File 'lib/multiarray/operations.rb', line 252 def if_else( action1, action2 ) simplify.get.if_else action1, action2 end |
#imag=(value) ⇒ Object
Assignment for imaginary values of complex array
1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 |
# File 'lib/multiarray/complex.rb', line 1039 def imag=(value) if typecode < COMPLEX_ decompose( 1 )[] = value elsif typecode == OBJECT self[] = Hornetseye::lazy do real + value * Complex::I end else raise "Cannot assign imaginary values to elements of type #{typecode.inspect}" end end |
#imag_with_decompose ⇒ Node
Fast extraction of imaginary values of complex array
1022 1023 1024 1025 1026 1027 1028 1029 1030 |
# File 'lib/multiarray/complex.rb', line 1022 def imag_with_decompose if typecode == OBJECT or is_a?(Variable) or Thread.current[:lazy] imag_without_decompose elsif typecode < COMPLEX_ decompose 1 else Hornetseye::lazy( *shape ) { typecode.new( 0 ) } end end |
#inject(initial = nil, options = {}, &action) ⇒ Object #inject(initial = nil, symbol) ⇒ Object
Perform cummulative operation on array
351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 |
# File 'lib/multiarray/operations.rb', line 351 def inject(*args, &action) = args.last.is_a?(Hash) ? args.pop : {} unless action or [:block] unless [1, 2].member? args.size raise "Inject expected 1 or 2 arguments but got #{args.size}" end initial, symbol = args[-2], args[-1] action = proc { |a,b| a.send symbol, b } else raise "Inject expected 0 or 1 arguments but got #{args.size}" if args.size > 1 initial = args.empty? ? nil : args.first end unless initial.nil? initial = Node.match( initial ).new initial unless initial.matched? initial_typecode = initial.typecode else initial_typecode = typecode end var1 = [ :var1 ] || Variable.new( initial_typecode ) var2 = [ :var2 ] || Variable.new( typecode ) block = [ :block ] || action.call( var1, var2 ) if dimension == 0 if initial block.subst(var1 => initial, var2 => self).simplify else demand end else index = Variable.new Hornetseye::INDEX( nil ) value = element( index ).inject nil, :block => block, :var1 => var1, :var2 => var2 value = typecode.new value unless value.matched? if initial.nil? and index.size.get == 0 raise "Array was empty and no initial value for injection was given" end Inject.new( value, index, initial, block, var1, var2 ).force end end |
#inspect(indent = nil, lines = nil) ⇒ String
Display information about this object
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 |
# File 'lib/multiarray/node.rb', line 424 def inspect( indent = nil, lines = nil ) if variables.empty? if dimension == 0 and not indent "#{typecode.inspect}(#{force.inspect})" else if indent prepend = '' else prepend = "#{Hornetseye::MultiArray(typecode, dimension).inspect}:\n" indent = 0 lines = 0 end if empty? retval = '[]' else retval = '[ ' for i in 0 ... shape.last x = element i if x.dimension > 0 if i > 0 retval += ",\n " lines += 1 if lines >= 10 retval += '...' if indent == 0 break end retval += ' ' * indent end str = x.inspect indent + 1, lines lines += str.count "\n" retval += str if lines >= 10 retval += '...' if indent == 0 break end else retval += ', ' if i > 0 str = x.force.inspect if retval.size + str.size >= 74 - '...'.size - '[ ]'.size * indent.succ retval += '...' break else retval += str end end end retval += ' ]' unless lines >= 10 end prepend + retval end else to_s end end |
#integral ⇒ Node
Compute integral image
764 765 766 767 768 769 770 771 772 773 |
# File 'lib/multiarray/operations.rb', line 764 def integral left = allocate block = Integral.new left, self if block.compilable? GCCFunction.run block else block.demand end left end |
#lut(table, options = {}) ⇒ Node
Perform element-wise lookup
726 727 728 729 730 731 732 |
# File 'lib/multiarray/operations.rb', line 726 def lut( table, = {} ) if ( shape.first != 1 or dimension == 1 ) and table.dimension == 1 [ self ].lut table, else ( 0 ... shape.first ).collect { |i| unroll[i] }.lut table, end end |
#lut_with_rgb(table, options = {}) ⇒ Node
Perform element-wise lookup with colour values
666 667 668 669 670 671 672 |
# File 'lib/multiarray/rgb.rb', line 666 def lut_with_rgb( table, = {} ) if typecode < RGB_ [ r, g, b ].lut table, else lut_without_rgb table, end end |
#malloc ⇒ GCCValue
Generate code for memory allocation
233 234 235 |
# File 'lib/multiarray/operations.rb', line 233 def malloc get.malloc end |
#mask(m) ⇒ Node
Select values from array using a mask
810 811 812 813 814 815 816 817 818 819 820 821 822 823 |
# File 'lib/multiarray/operations.rb', line 810 def mask( m ) check_shape m left = MultiArray.new typecode, *( shape.first( dimension - m.dimension ) + [ m.size ] ) index = Hornetseye::Pointer( INT ).new index.store INT.new( 0 ) block = Mask.new left, self, m, index if block.compilable? GCCFunction.run block else block.demand end left[0 ... index[]].roll end |
#matched? ⇒ Boolean
283 284 285 |
# File 'lib/multiarray/node.rb', line 283 def matched? true end |
#max(initial = nil) ⇒ Object
Find maximum value of array
433 434 435 |
# File 'lib/multiarray/operations.rb', line 433 def max( initial = nil ) inject initial, :major end |
#mean ⇒ Object
Compute average of array
454 455 456 |
# File 'lib/multiarray/operations.rb', line 454 def mean sum / size end |
#memorise ⇒ Node
Duplicate array expression if it is not in row-major format
329 330 331 332 333 334 335 336 337 338 339 340 341 342 |
# File 'lib/multiarray/node.rb', line 329 def memorise if memory contiguous_strides = (0 ... dimension).collect do |i| shape[0 ... i].inject 1, :* end if strides == contiguous_strides self else dup end else dup end end |
#memory ⇒ Malloc, ...
Get memory object
347 348 349 |
# File 'lib/multiarray/node.rb', line 347 def memory nil end |
#min(initial = nil) ⇒ Object
Find minimum value of array
424 425 426 |
# File 'lib/multiarray/operations.rb', line 424 def min( initial = nil ) inject initial, :minor end |
#normalise(range = 0 .. 0xFF) ⇒ Node
Normalise values of array
477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 |
# File 'lib/multiarray/operations.rb', line 477 def normalise( range = 0 .. 0xFF ) if range.exclude_end? raise "Normalisation does not support ranges with end value " + "excluded (such as #{range})" end lower, upper = min, max if lower.is_a? RGB or upper.is_a? RGB current = [ lower.r, lower.g, lower.b ].min .. [ upper.r, upper.g, upper.b ].max else current = min .. max end if current.last != current.first factor = ( range.last - range.first ).to_f / ( current.last - current.first ) collect { |x| x * factor + ( range.first - current.first * factor ) } else self + ( range.first - current.first ) end end |
#prod ⇒ Object
Compute product of array
447 448 449 |
# File 'lib/multiarray/operations.rb', line 447 def prod Hornetseye::lazy { to_type typecode.maxint }.inject :* end |
#r=(value) ⇒ Object
Assignment for red channel values of RGB array
548 549 550 551 552 553 554 555 556 557 558 |
# File 'lib/multiarray/rgb.rb', line 548 def r=(value) if typecode < RGB_ decompose( 0 )[] = value elsif typecode == OBJECT self[] = Hornetseye::lazy do value * RGB.new( 1, 0, 0 ) + g * RGB.new( 0, 1, 0 ) + b * RGB.new( 0, 0, 1 ) end else raise "Cannot assign red channel to elements of type #{typecode.inspect}" end end |
#r_with_decompose ⇒ Node
Fast extraction for red channel of RGB array
531 532 533 534 535 536 537 538 539 |
# File 'lib/multiarray/rgb.rb', line 531 def r_with_decompose if typecode == OBJECT or is_a?(Variable) or Thread.current[:lazy] r_without_decompose elsif typecode < RGB_ decompose 0 else self end end |
#range(initial = nil) ⇒ Object
Find range of values of array
461 462 463 |
# File 'lib/multiarray/operations.rb', line 461 def range( initial = nil ) min( initial ? initial.min : nil ) .. max( initial ? initial.max : nil ) end |
#real=(value) ⇒ Object
Assignment for real values of complex array
1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 |
# File 'lib/multiarray/complex.rb', line 1007 def real=(value) if typecode < COMPLEX_ decompose( 0 )[] = value elsif typecode == OBJECT self[] = Hornetseye::lazy do value + imag * Complex::I end else self[] = value end end |
#real_with_decompose ⇒ Node
Fast extraction for real values of complex array
990 991 992 993 994 995 996 997 998 |
# File 'lib/multiarray/complex.rb', line 990 def real_with_decompose if typecode == OBJECT or is_a?(Variable) or Thread.current[:lazy] real_without_decompose elsif typecode < COMPLEX_ decompose 0 else self end end |
#reshape(*ret_shape) ⇒ Node
Get array with same elements but different shape
The method returns an array with the same elements but with a different shape. The desired shape must have the same number of elements.
197 198 199 200 201 202 203 204 |
# File 'lib/multiarray/operations.rb', line 197 def reshape(*ret_shape) target_size = ret_shape.inject 1, :* if target_size != size raise "Target is of size #{target_size} but should be of size #{size}" end Hornetseye::MultiArray(typecode, ret_shape.size). new *(ret_shape + [:memory => memorise.memory]) end |
#rgb? ⇒ Boolean
Check whether this object is an RGB value
393 394 395 |
# File 'lib/multiarray/node.rb', line 393 def rgb? typecode.rgb? end |
#roll(n = 1) ⇒ Node
Cycle indices of array
294 295 296 297 298 299 300 301 302 |
# File 'lib/multiarray/operations.rb', line 294 def roll( n = 1 ) if n < 0 unroll -n else order = ( 0 ... dimension ).to_a n.times { order = order[ 1 .. -1 ] + [ order.first ] } transpose *order end end |
#shape ⇒ Array<Integer>
Get shape of this term
379 380 381 |
# File 'lib/multiarray/node.rb', line 379 def shape self.class.shape end |
#shift(*offset) ⇒ Node
Create array with shifted elements
879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 |
# File 'lib/multiarray/operations.rb', line 879 def shift( *offset ) if offset.size != dimension raise "#{offset.size} offset(s) were given but array has " + "#{dimension} dimension(s)" end retval = Hornetseye::MultiArray(typecode, dimension).new *shape target, source, open, close = [], [], [], [] ( shape.size - 1 ).step( 0, -1 ) do |i| callcc do |pass| delta = offset[i] % shape[i] source[i] = 0 ... shape[i] - delta target[i] = delta ... shape[i] callcc do |c| open[i] = c pass.call end source[i] = shape[i] - delta ... shape[i] target[i] = 0 ... delta callcc do |c| open[i] = c pass.call end close[i].call end end retval[ *target ] = self[ *source ] for i in 0 ... shape.size callcc do |c| close[i] = c open[i].call end end retval end |
#simplify ⇒ Node, Object
Reevaluate term
679 680 681 |
# File 'lib/multiarray/node.rb', line 679 def simplify dimension == 0 ? demand.dup : demand end |
#size ⇒ Integer
Get size (number of elements) of this value
322 323 324 |
# File 'lib/multiarray/node.rb', line 322 def size shape.inject 1, :* end |
#sobel(direction) ⇒ Node
Sobel operator
652 653 654 655 656 657 658 |
# File 'lib/multiarray/operations.rb', line 652 def sobel( direction ) ( dimension - 1 ).downto( 0 ).inject self do |retval,i| filter = i == direction ? Hornetseye::Sequence(SINT)[1, 0, -1] : Hornetseye::Sequence(SINT)[1, 2, 1] Hornetseye::lazy { retval.convolve filter } end.force end |
#stretch(from = 0 .. 0xFF, to = 0 .. 0xFF) ⇒ Node
Stretch values from one range to another
517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 |
# File 'lib/multiarray/operations.rb', line 517 def stretch(from = 0 .. 0xFF, to = 0 .. 0xFF) if from.exclude_end? raise "Stretching does not support ranges with end value " + "excluded (such as #{from})" end if to.exclude_end? raise "Stretching does not support ranges with end value " + "excluded (such as #{to})" end if from.last != from.first factor = (to.last - to.first).to_f / (from.last - from.first) collect { |x| ((x - from.first) * factor).major(to.first).minor to.last } else (self <= from.first).conditional to.first, to.last end end |
#stride(index) ⇒ Integer, NilClass
Get stride for specific index
365 366 367 |
# File 'lib/multiarray/node.rb', line 365 def stride( index ) nil end |
#strides ⇒ Array<Integer>, NilClass
Get strides of array
356 357 358 |
# File 'lib/multiarray/node.rb', line 356 def strides nil end |
#strip ⇒ Array<Array,Node>
Strip of all values
Split up into variables, values, and a term where all values have been replaced with variables.
values, and the term based on variables.
634 635 636 |
# File 'lib/multiarray/node.rb', line 634 def strip return [], [], self end |
#subst(hash) ⇒ Node
Substitute variables
Substitute the variables with the values given in the hash.
522 523 524 |
# File 'lib/multiarray/node.rb', line 522 def subst( hash ) hash[ self ] || self end |
#sum ⇒ Object
Compute sum of array
440 441 442 |
# File 'lib/multiarray/operations.rb', line 440 def sum Hornetseye::lazy { to_type typecode.maxint }.inject :+ end |
#swap_rgb_with_scalar ⇒ Node
Swapping colour channels for scalar values
627 628 629 630 631 632 633 |
# File 'lib/multiarray/rgb.rb', line 627 def swap_rgb_with_scalar if typecode == OBJECT or typecode < RGB_ swap_rgb_without_scalar else self end end |
#table(filter, &action) ⇒ Node
Compute table from two arrays
Used internally to implement convolutions and other operations.
597 598 599 600 601 602 603 604 605 606 607 608 609 |
# File 'lib/multiarray/operations.rb', line 597 def table( filter, &action ) filter = Node.match( filter, typecode ).new filter unless filter.matched? if filter.dimension > dimension raise "Filter has #{filter.dimension} dimension(s) but should " + "not have more than #{dimension}" end filter = Hornetseye::lazy( 1 ) { filter } while filter.dimension < dimension if filter.dimension == 0 action.call self, filter else Hornetseye::lazy { |i,j| self[j].table filter[i], &action } end end |
#to_a ⇒ Array<Object>
Convert to Ruby array of objects
Perform pending computations and convert native array to Ruby array of objects.
412 413 414 415 416 417 418 419 |
# File 'lib/multiarray/node.rb', line 412 def to_a if dimension == 0 force else n = shape.last ( 0 ... n ).collect { |i| element( i ).to_a } end end |
#to_s ⇒ String
Get unique descriptor of this object
The method calls descriptor( {} ).
489 490 491 |
# File 'lib/multiarray/node.rb', line 489 def to_s descriptor( {} ) end |
#to_type(dest) ⇒ Node
Convert array elements to different element type
138 139 140 141 142 143 144 145 146 147 |
# File 'lib/multiarray/operations.rb', line 138 def to_type(dest) if dimension == 0 and variables.empty? target = typecode.to_type dest target.new(simplify.get).simplify else key = "to_#{dest.to_s.downcase}" Hornetseye::ElementWise( proc { |x| x.to_type dest }, key, proc { |t| t.to_type dest } ).new(self).force end end |
#to_type_with_identity(dest) ⇒ Node
Skip type conversion if it has no effect
This operation is a special case handling type conversions to the same type.
179 180 181 182 183 184 185 |
# File 'lib/multiarray/operations.rb', line 179 def to_type_with_identity( dest ) if dest == typecode self else to_type_without_identity dest end end |
#to_type_with_rgb(dest) ⇒ Node
Convert RGB array to scalar array
This operation is a special case handling colour to greyscale conversion.
156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/multiarray/operations.rb', line 156 def to_type_with_rgb(dest) if typecode < RGB_ if dest < FLOAT_ lazy { r * 0.299 + g * 0.587 + b * 0.114 }.to_type dest elsif dest < INT_ lazy { (r * 0.299 + g * 0.587 + b * 0.114).round }.to_type dest else to_type_without_rgb dest end else to_type_without_rgb dest end end |
#transpose(*order) ⇒ Node
Lazy transpose of array
Lazily compute transpose by swapping indices according to the specified order.
275 276 277 278 279 280 281 282 283 284 285 286 287 |
# File 'lib/multiarray/operations.rb', line 275 def transpose(*order) if (0 ... dimension).to_a != order.sort raise 'Each array index must be specified exactly once!' end term = self variables = shape.reverse.collect do |i| var = Variable.new Hornetseye::INDEX( i ) term = term.element var var end.reverse order.collect { |o| variables[o] }. inject(term) { |retval,var| Lambda.new var, retval } end |
#typecode ⇒ Class
Element-type of this term
294 295 296 |
# File 'lib/multiarray/node.rb', line 294 def typecode self.class.typecode end |
#unmask(m, options = {}) ⇒ Node
Distribute values in a new array using a mask
834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 |
# File 'lib/multiarray/operations.rb', line 834 def unmask( m, = {} ) = { :safe => true, :default => typecode.default }.merge default = [:default] default = typecode.new default unless default.matched? m.check_shape default if [ :safe ] if m.to_ubyte.sum > shape.last raise "#{m.to_ubyte.sum} value(s) of the mask are true but the last " + "dimension of the array for unmasking only has #{shape.last} value(s)" end end left = Hornetseye::MultiArray(typecode, dimension - 1 + m.dimension). coercion(default.typecode).new *(shape[1 .. -1] + m.shape) index = Hornetseye::Pointer(INT).new index.store INT.new(0) block = Unmask.new left, self, m, index, default if block.compilable? GCCFunction.run block else block.demand end left end |
#unroll(n = 1) ⇒ Node
Reverse-cycle indices of array
309 310 311 312 313 314 315 316 317 |
# File 'lib/multiarray/operations.rb', line 309 def unroll( n = 1 ) if n < 0 roll -n else order = ( 0 ... dimension ).to_a n.times { order = [ order.last ] + order[ 0 ... -1 ] } transpose *order end end |
#variables ⇒ Set
Get variables contained in this object
621 622 623 |
# File 'lib/multiarray/node.rb', line 621 def variables Set[] end |
#warp(*field, options = {}) ⇒ Node
Warp an array
743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 |
# File 'lib/multiarray/operations.rb', line 743 def warp( *field ) = field.last.is_a?( Hash ) ? field.pop : {} = { :safe => true, :default => typecode.default }.merge if [ :safe ] if field.size > dimension raise "Number of arrays for warp (#{field.size}) is greater than the " + "number of dimensions of source (#{dimension})" end Hornetseye::lazy do ( 0 ... field.size ). collect { |i| ( field[i] >= 0 ).and( field[i] < shape[i] ) }. inject :and end.conditional Lut.new( *( field + [ self ] ) ), [ :default ] else field.lut self, :safe => false end end |
#width ⇒ Integer
Get width of two-dimensional array
308 309 310 |
# File 'lib/multiarray/node.rb', line 308 def width shape[0] end |