def knot( args, comp )
      n = @n.simplify
      if dimension > 0
        subargs1, subargs2, subargs3 = [], [], []
        subcomp1, subcomp2, subcomp3 = [], [], []
        args.each do |arg|
          subargs1.push proc { |i| arg.element( i - 1 ).demand }
          subargs2.push proc { |i| arg.element( i     ).demand }
          subargs3.push proc { |i| arg.element( i + 1 ).demand }
        end
        comp.each do |c|
          subcomp1.push proc { |i| c.element( i - 1 ) }
          subcomp2.push proc { |i| c.element( i     ) }
          subcomp3.push proc { |i| c.element( i + 1 ) }
        end
        self.class.new( @dest.element( INT.new( 0 ) ),
                        @source.element( INT.new( 0 ) ).demand, @default, @zero,
                        @labels, @rank, n ).
          knot( ( subargs2 + subargs3 ).collect { |p| p.call INT.new( 0 ) },
                ( subcomp2 + subcomp3 ).collect { |p| p.call INT.new( 0 ) } )
        INT.new( 1 ).upto INT.new( @source.shape.last ) - 2 do |i|
          self.class.new( @dest.element( INT.new( i ) ),
                          @source.element( INT.new( i ) ).demand, @default, @zero,
                          @labels, @rank, n ).
            knot( ( subargs1 + subargs2 + subargs3 ).collect { |p| p.call INT.new( i ) } +
                  [ @source.element( INT.new( i ) - 1 ) ],
                  ( subcomp1 + subcomp2 + subcomp3 ).collect { |p| p.call INT.new( i ) } +
                  [ @dest.element( INT.new( i ) - 1 ) ] )
        end
        i = @source.shape.last - 1
        self.class.new( @dest.element( INT.new( i ) ),
                        @source.element( INT.new( i ) ).demand, @default, @zero,
                        @labels, @rank, n ).
          knot( ( subargs1 + subargs2 ).collect { |p| p.call INT.new( i ) } +
                [ @source.element( INT.new( i ) - 1 ) ],
                ( subcomp1 + subcomp2 ).collect { |p| p.call INT.new( i ) } +
                [ @dest.element( INT.new( i ) - 1 ) ] )
      else
        @source.ne( @default ).if_else( proc do
          label = @zero.simplify
          args.zip( comp ).each do |arg,other|
            @source.eq( arg ).if do
              other = other.simplify
              proc { other.ne( @labels.element( other ).demand ) }.while do
                other.assign @labels.element( other ).demand
              end
              label.eq( @zero ).if_else( proc do
                label.assign other
              end, proc do
                label.ne( other ).if do
                  ( @rank.element( label ).demand <= @rank.element( other ).demand ).if_else( proc do
                    @labels[ other ] = label
                    @rank.element( label ).demand.eq( @rank.element( other ).demand ).if do
                      @rank[ label ] = @rank.element( other ).demand + 1
                    end
                  end, proc do
                    @labels[ label ] = other
                    label.assign other
                  end )
                end
              end )
            end
          end
          label.eq( @zero ).if do
            n.assign n + 1
            @labels[ n ] = n
            @rank[ n ] = 0
            label.assign n
          end
          @dest.store label
        end, proc do
          @dest.store INT.new( 0 )
        end )
      end
      if @n.is_a? Pointer_
        INT.new( 0 ).upto n do |i|
          l = UINT.new( i ).simplify
          proc { l.ne( @labels.element( l ).demand ) }.while do
            l.assign @labels.element( l ).demand
          end
          @labels[ INT.new( i ) ] = l
        end
        @n.store n
      else
        @n.assign n
      end
    end
def knot( args, comp )
      n = @n.simplify
      if dimension > 0
        subargs1, subargs2, subargs3 = [], [], []
        subcomp1, subcomp2, subcomp3 = [], [], []
        args.each do |arg|
          subargs1.push proc { |i| arg.element( i - 1 ).demand }
          subargs2.push proc { |i| arg.element( i     ).demand }
          subargs3.push proc { |i| arg.element( i + 1 ).demand }
        end
        comp.each do |c|
          subcomp1.push proc { |i| c.element( i - 1 ) }
          subcomp2.push proc { |i| c.element( i     ) }
          subcomp3.push proc { |i| c.element( i + 1 ) }
        end
        self.class.new( @dest.element( INT.new( 0 ) ),
                        @source.element( INT.new( 0 ) ).demand, @default, @zero,
                        @labels, @rank, n ).
          knot( ( subargs2 + subargs3 ).collect { |p| p.call INT.new( 0 ) },
                ( subcomp2 + subcomp3 ).collect { |p| p.call INT.new( 0 ) } )
        INT.new( 1 ).upto INT.new( @source.shape.last ) - 2 do |i|
          self.class.new( @dest.element( INT.new( i ) ),
                          @source.element( INT.new( i ) ).demand, @default, @zero,
                          @labels, @rank, n ).
            knot( ( subargs1 + subargs2 + subargs3 ).collect { |p| p.call INT.new( i ) } +
                  [ @source.element( INT.new( i ) - 1 ) ],
                  ( subcomp1 + subcomp2 + subcomp3 ).collect { |p| p.call INT.new( i ) } +
                  [ @dest.element( INT.new( i ) - 1 ) ] )
        end
        i = @source.shape.last - 1
        self.class.new( @dest.element( INT.new( i ) ),
                        @source.element( INT.new( i ) ).demand, @default, @zero,
                        @labels, @rank, n ).
          knot( ( subargs1 + subargs2 ).collect { |p| p.call INT.new( i ) } +
                [ @source.element( INT.new( i ) - 1 ) ],
                ( subcomp1 + subcomp2 ).collect { |p| p.call INT.new( i ) } +
                [ @dest.element( INT.new( i ) - 1 ) ] )
      else
        @source.ne( @default ).if_else( proc do
          label = @zero.simplify
          args.zip( comp ).each do |arg,other|
            @source.eq( arg ).if do
              other = other.simplify
              proc { other.ne( @labels.element( other ).demand ) }.while do
                other.assign @labels.element( other ).demand
              end
              label.eq( @zero ).if_else( proc do
                label.assign other
              end, proc do
                label.ne( other ).if do
                  ( @rank.element( label ).demand <= @rank.element( other ).demand ).if_else( proc do
                    @labels[ other ] = label
                    @rank.element( label ).demand.eq( @rank.element( other ).demand ).if do
                      @rank[ label ] = @rank.element( other ).demand + 1
                    end
                  end, proc do
                    @labels[ label ] = other
                    label.assign other
                  end )
                end
              end )
            end
          end
          label.eq( @zero ).if do
            n.assign n + 1
            @labels[ n ] = n
            @rank[ n ] = 0
            label.assign n
          end
          @dest.store label
        end, proc do
          @dest.store INT.new( 0 )
        end )
      end
      if @n.is_a? Pointer_
        INT.new( 0 ).upto n do |i|
          l = UINT.new( i ).simplify
          proc { l.ne( @labels.element( l ).demand ) }.while do
            l.assign @labels.element( l ).demand
          end
          @labels[ INT.new( i ) ] = l
        end
        @n.store n
      else
        @n.assign n
      end
    end
Recursive function to perform connected component labeling

 @param [Array<Proc>] args Array with functions for locating neighbouring elements.
 @param [Array<Proc>] comp Array with functions for locating neighbouring labels.

 @private