def downsample( *rate )
      options = rate.last.is_a?( Hash ) ? rate.pop : {}
      options = { :offset => rate.collect { |r| r - 1 } }.merge options
      offset = options[ :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
def downsample( *rate )
      options = rate.last.is_a?( Hash ) ? rate.pop : {}
      options = { :offset => rate.collect { |r| r - 1 } }.merge options
      offset = options[ :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
Downsampling of arrays

 @overload downsample( *rate, options = {} )
   @param [Array<Integer>] rate The sampling rates for each dimension.
   @option options [Array<Integer>] :offset Sampling offsets for each dimension.

 @return [Node] The downsampled data.