Class: CASlabIterator

Inherits:
CAIterator show all
Defined in:
lib/carray/slab_iterator.rb

Overview

CASlabIterator.

Created by the C indexer dispatch when an index uses the :> slab-axis sigil (e.g. ca[nil, :>, :>]). It is a thin sugar over each_slab / map_slab / reduce_slab: :> axes become the slab handed to the block; the remaining (sliced) axes are the outer iteration space.

ca[nil, :>].each { |row| ... }       # = ca.each_slab(axis: 1)
ca[2..5, :>, :>].map { |slab| ... }  # = ca[2..5,nil,nil].map_slab(axis: [-2,-1])

Surface is intentionally minimal (each / map / reduce); to_a / count / size and other Enumerable extras are deferred.

Naming note: distinct from the C-defined CArray::SlabIterator engine in ext/carray_slab.c -- this is the Ruby-level sigil iterator that delegates to each_slab / map_slab / reduce_slab. Loaded lazily via autoload from lib/carray/autoload/autoload_base.rb on first ca[..., :>] evaluation.

Instance Attribute Summary collapse

Attributes inherited from CAIterator

#ndim, #shape

Instance Method Summary collapse

Constructor Details

#initialize(reference, slab_axes) ⇒ CASlabIterator

Built from C via CASlabIterator.new(reference, slab_axes): reference is the sliced base view (with :> axes as full range), slab_axes are the positions marked with :>.



24
25
26
27
28
29
30
31
32
# File 'lib/carray/slab_iterator.rb', line 24

def initialize (reference, slab_axes)
  @reference = reference
  @slab_axes = slab_axes
  rdim = reference.shape
  @outer_positions = (0...reference.ndim).reject { |k| slab_axes.include?(k) }.freeze
  @shape             = @outer_positions.map { |k| rdim[k] }
  @ndim            = @shape.size
  self
end

Instance Attribute Details

#reference ⇒ Object (readonly)

The array being iterated (slab exposes it as reference; block / window iterators expose theirs as source). The base has no common accessor.



36
37
38
# File 'lib/carray/slab_iterator.rb', line 36

def reference
  @reference
end

#slab_axes ⇒ Object (readonly)

The array being iterated (slab exposes it as reference; block / window iterators expose theirs as source). The base has no common accessor.



36
37
38
# File 'lib/carray/slab_iterator.rb', line 36

def slab_axes
  @slab_axes
end

Instance Method Details

#accumulate ⇒ CArray

Per-slab sum kept in the source's own data type, wrapping at its width, as the core accumulate does -- sum answers in the type the core promotes to (float64 for integers).

Returns:

  • (CArray) —

    one value per slab



155
156
157
158
159
160
161
162
163
# File 'lib/carray/slab_iterator.rb', line 155

[:sum, :accumulate, :prod, :mean, :min, :max, :variance, :stddev, :all, :any,
 :variancep, :stddevp, :minmax, :min_index, :max_index,
 :min_addr, :max_addr].each do |op|
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
    def #{op}
      @reference.#{op}(axis: @slab_axes)
    end
  RUBY
end

#all ⇒ CArray

Whether every cell of each slab is true.

Returns:

  • (CArray) —

    :boolean, one value per slab



155
156
157
158
159
160
161
162
163
# File 'lib/carray/slab_iterator.rb', line 155

[:sum, :accumulate, :prod, :mean, :min, :max, :variance, :stddev, :all, :any,
 :variancep, :stddevp, :minmax, :min_index, :max_index,
 :min_addr, :max_addr].each do |op|
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
    def #{op}
      @reference.#{op}(axis: @slab_axes)
    end
  RUBY
end

#any ⇒ CArray

Whether any cell of each slab is true.

Returns:

  • (CArray) —

    :boolean, one value per slab



155
156
157
158
159
160
161
162
163
# File 'lib/carray/slab_iterator.rb', line 155

[:sum, :accumulate, :prod, :mean, :min, :max, :variance, :stddev, :all, :any,
 :variancep, :stddevp, :minmax, :min_index, :max_index,
 :min_addr, :max_addr].each do |op|
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
    def #{op}
      @reference.#{op}(axis: @slab_axes)
    end
  RUBY
end

#count(v = <none>) ⇒ CArray

Per-slab count, delegating to reference.count(..., axis: slab_axes). No argument counts present (non-masked) cells; count(UNDEF) counts masked cells; count(v) counts cells equal to v.

Returns:

  • (CArray) —

    one count per slab



170
171
172
173
174
175
# File 'lib/carray/slab_iterator.rb', line 170

def count (*args)
  return count_not_masked if args.empty?
  # CABlock / CAWindow shadow #count with a geometry accessor, and @reference
  # may be such a view, so dispatch CArray#count explicitly for count(v).
  CArray.instance_method(:count).bind_call(@reference, *args, axis: @slab_axes)
end

#count_masked ⇒ CArray

Per-slab count of masked cells.

Returns:



187
188
189
# File 'lib/carray/slab_iterator.rb', line 187

def count_masked
  @reference.count_masked(axis: @slab_axes)
end

#count_not_masked ⇒ CArray

Per-slab count of present (non-masked) cells.

Returns:



180
181
182
# File 'lib/carray/slab_iterator.rb', line 180

def count_not_masked
  @reference.count_not_masked(axis: @slab_axes)
end

#cumcount ⇒ CArray

Per-slab running count of present cells (int64), reference-shaped.

Returns:



323
324
325
326
327
328
329
# File 'lib/carray/slab_iterator.rb', line 323

[:cumsum, :cumprod, :cummax, :cummin, :cumcount].each do |op|
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
    def #{op}
      @reference.#{op}(axis: single_scan_axis(:#{op}))
    end
  RUBY
end

#cummax ⇒ CArray

Per-slab inclusive running maximum (reference data type), reference-shaped.

Returns:



323
324
325
326
327
328
329
# File 'lib/carray/slab_iterator.rb', line 323

[:cumsum, :cumprod, :cummax, :cummin, :cumcount].each do |op|
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
    def #{op}
      @reference.#{op}(axis: single_scan_axis(:#{op}))
    end
  RUBY
end

#cummin ⇒ CArray

Per-slab inclusive running minimum (reference data type), reference-shaped.

Returns:



323
324
325
326
327
328
329
# File 'lib/carray/slab_iterator.rb', line 323

[:cumsum, :cumprod, :cummax, :cummin, :cumcount].each do |op|
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
    def #{op}
      @reference.#{op}(axis: single_scan_axis(:#{op}))
    end
  RUBY
end

#cumprod ⇒ CArray

Per-slab inclusive running product (float64), reference-shaped.

Returns:



323
324
325
326
327
328
329
# File 'lib/carray/slab_iterator.rb', line 323

[:cumsum, :cumprod, :cummax, :cummin, :cumcount].each do |op|
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
    def #{op}
      @reference.#{op}(axis: single_scan_axis(:#{op}))
    end
  RUBY
end

#cumsum ⇒ CArray

Per-slab inclusive running sum (float64), reference-shaped.

Returns:



323
324
325
326
327
328
329
# File 'lib/carray/slab_iterator.rb', line 323

[:cumsum, :cumprod, :cummax, :cummin, :cumcount].each do |op|
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
    def #{op}
      @reference.#{op}(axis: single_scan_axis(:#{op}))
    end
  RUBY
end

#each({ |slab| ... }) {|slab| ... } ⇒ Enumerator, self

Yields each slab as an inner CArray. Without a block, returns an Enumerator from each_slab.

Yield Parameters:

Returns:

  • (Enumerator, self)


52
53
54
55
# File 'lib/carray/slab_iterator.rb', line 52

def each (&block)
  return @reference.each_slab(axis: @slab_axes) unless block
  @reference.each_slab(axis: @slab_axes, &block)
end

#elements ⇒ CArray

Per-slab cell count (structural, mask-independent). Every slab has the same shape, so this is a constant array shaped like the outer iteration space.

Returns:



196
197
198
199
200
201
202
203
# File 'lib/carray/slab_iterator.rb', line 196

def elements
  sz  = @slab_axes.inject(1) { |p, ax| p * @reference.shape[ax] }
  # count_not_masked gives the correct output shape (and, unlike bare #count,
  # is not shadowed by CABlock / CAWindow); overwrite with the constant size.
  out = @reference.count_not_masked(axis: @slab_axes)
  out[] = sz
  out
end

#kernel_at_index(idx) ⇒ Object

Slab view at outer index idx (Array, length = self.ndim). Returns @reference[*full_idx] where slab axes are nil (full range) and outer axes take their values from idx.



41
42
43
44
45
# File 'lib/carray/slab_iterator.rb', line 41

def kernel_at_index (idx)
  full = Array.new(@reference.ndim)        # nil at every position
  @outer_positions.each_with_index { |k, i| full[k] = idx[i] }
  @reference[*full]
end

#map({ |slab| ... }) {|slab| ... } ⇒ CArray

Returns a new CArray built by applying the block to each slab, delegating to map_slab.

Yield Parameters:

Yield Returns:

  • (Object) —

    per-slab result.

Returns:



63
64
65
# File 'lib/carray/slab_iterator.rb', line 63

def map (&block)
  @reference.map_slab(axis: @slab_axes, &block)
end

#max ⇒ CArray

Per-slab maximum.

Returns:

  • (CArray) —

    one value per slab



155
156
157
158
159
160
161
162
163
# File 'lib/carray/slab_iterator.rb', line 155

[:sum, :accumulate, :prod, :mean, :min, :max, :variance, :stddev, :all, :any,
 :variancep, :stddevp, :minmax, :min_index, :max_index,
 :min_addr, :max_addr].each do |op|
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
    def #{op}
      @reference.#{op}(axis: @slab_axes)
    end
  RUBY
end

#max_addr ⇒ CArray

Per-slab flat source address of the maximum.

Returns:

  • (CArray) —

    one flat address per slab



155
156
157
158
159
160
161
162
163
# File 'lib/carray/slab_iterator.rb', line 155

[:sum, :accumulate, :prod, :mean, :min, :max, :variance, :stddev, :all, :any,
 :variancep, :stddevp, :minmax, :min_index, :max_index,
 :min_addr, :max_addr].each do |op|
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
    def #{op}
      @reference.#{op}(axis: @slab_axes)
    end
  RUBY
end

#max_index ⇒ CArray

Per-slab position of the maximum, local to the slab axes.

Returns:

  • (CArray) —

    one index per slab



155
156
157
158
159
160
161
162
163
# File 'lib/carray/slab_iterator.rb', line 155

[:sum, :accumulate, :prod, :mean, :min, :max, :variance, :stddev, :all, :any,
 :variancep, :stddevp, :minmax, :min_index, :max_index,
 :min_addr, :max_addr].each do |op|
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
    def #{op}
      @reference.#{op}(axis: @slab_axes)
    end
  RUBY
end

#mean ⇒ CArray

Per-slab arithmetic mean.

Returns:

  • (CArray) —

    one value per slab



155
156
157
158
159
160
161
162
163
# File 'lib/carray/slab_iterator.rb', line 155

[:sum, :accumulate, :prod, :mean, :min, :max, :variance, :stddev, :all, :any,
 :variancep, :stddevp, :minmax, :min_index, :max_index,
 :min_addr, :max_addr].each do |op|
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
    def #{op}
      @reference.#{op}(axis: @slab_axes)
    end
  RUBY
end

#median ⇒ CArray

Per-slab median.

Returns:



216
217
218
219
220
221
222
# File 'lib/carray/slab_iterator.rb', line 216

def median
  if @slab_axes.size == 1
    @reference.median(axis: @slab_axes[0])
  else
    @reference.reduce_slab(axis: @slab_axes) { |s| s.median }
  end
end

#min ⇒ CArray

Per-slab minimum.

Returns:

  • (CArray) —

    one value per slab



155
156
157
158
159
160
161
162
163
# File 'lib/carray/slab_iterator.rb', line 155

[:sum, :accumulate, :prod, :mean, :min, :max, :variance, :stddev, :all, :any,
 :variancep, :stddevp, :minmax, :min_index, :max_index,
 :min_addr, :max_addr].each do |op|
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
    def #{op}
      @reference.#{op}(axis: @slab_axes)
    end
  RUBY
end

#min_addr ⇒ CArray

Per-slab flat source address of the minimum -- which source cell holds it.

Returns:

  • (CArray) —

    one flat address per slab



155
156
157
158
159
160
161
162
163
# File 'lib/carray/slab_iterator.rb', line 155

[:sum, :accumulate, :prod, :mean, :min, :max, :variance, :stddev, :all, :any,
 :variancep, :stddevp, :minmax, :min_index, :max_index,
 :min_addr, :max_addr].each do |op|
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
    def #{op}
      @reference.#{op}(axis: @slab_axes)
    end
  RUBY
end

#min_index ⇒ CArray

Per-slab position of the minimum, local to the slab axes.

Returns:

  • (CArray) —

    one index per slab



155
156
157
158
159
160
161
162
163
# File 'lib/carray/slab_iterator.rb', line 155

[:sum, :accumulate, :prod, :mean, :min, :max, :variance, :stddev, :all, :any,
 :variancep, :stddevp, :minmax, :min_index, :max_index,
 :min_addr, :max_addr].each do |op|
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
    def #{op}
      @reference.#{op}(axis: @slab_axes)
    end
  RUBY
end

#minmax ⇒ Array<CArray>

Per-slab minimum and maximum, found in one pass.

Returns:



155
156
157
158
159
160
161
162
163
# File 'lib/carray/slab_iterator.rb', line 155

[:sum, :accumulate, :prod, :mean, :min, :max, :variance, :stddev, :all, :any,
 :variancep, :stddevp, :minmax, :min_index, :max_index,
 :min_addr, :max_addr].each do |op|
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
    def #{op}
      @reference.#{op}(axis: @slab_axes)
    end
  RUBY
end

#percentile(*pers) ⇒ CArray+

Per-slab percentile(s). One argument returns one CArray; several return an array of CArrays (as CArray#percentile).

Returns:



228
229
230
231
232
233
234
235
# File 'lib/carray/slab_iterator.rb', line 228

def percentile (*pers)
  if @slab_axes.size == 1
    @reference.percentile(*pers, axis: @slab_axes[0])
  else
    rs = pers.map { |p| @reference.reduce_slab(axis: @slab_axes) { |s| s.percentile(p) } }
    pers.size == 1 ? rs[0] : rs
  end
end

#prod ⇒ CArray

Per-slab product.

Returns:

  • (CArray) —

    one value per slab



155
156
157
158
159
160
161
162
163
# File 'lib/carray/slab_iterator.rb', line 155

[:sum, :accumulate, :prod, :mean, :min, :max, :variance, :stddev, :all, :any,
 :variancep, :stddevp, :minmax, :min_index, :max_index,
 :min_addr, :max_addr].each do |op|
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
    def #{op}
      @reference.#{op}(axis: @slab_axes)
    end
  RUBY
end

#quantile ⇒ Array<CArray>

Per-slab five-number summary [min, Q1, median, Q3, max] (five CArrays), as CArray#quantile.

Returns:



241
242
243
244
245
246
247
248
249
# File 'lib/carray/slab_iterator.rb', line 241

def quantile
  if @slab_axes.size == 1
    @reference.quantile(axis: @slab_axes[0])
  else
    [0, 25, 50, 75, 100].map { |p|
      @reference.reduce_slab(axis: @slab_axes) { |s| s.percentile(p) }
    }
  end
end

#reduce({ |acc, slab| ... }) {|acc, slab| ... } ⇒ Object #reduce(init) {|acc, slab| ... } ⇒ Object

Overloads:

  • #reduce({ |acc, slab| ... }) {|acc, slab| ... } ⇒ Object

    Reduces the slabs with reduce_slab. The block-only form uses the first slab as the seed; the init form starts from init.

    Yield Parameters:

    • acc (Object) —

      running accumulator.

    • slab (CArray) —

      next slab.

    Yield Returns:

    • (Object) —

      updated accumulator.

    Returns:

    • (Object)
  • #reduce(init) {|acc, slab| ... } ⇒ Object

    Parameters:

    • init (Object) —

      initial accumulator value.

    Yield Parameters:

    Yield Returns:

    • (Object)

    Returns:

    • (Object)


80
81
82
83
84
85
86
# File 'lib/carray/slab_iterator.rb', line 80

def reduce (*args, &block)
  if args.empty?
    @reference.reduce_slab(axis: @slab_axes, &block)
  else
    @reference.reduce_slab(axis: @slab_axes, init: args[0], &block)
  end
end

#sort_addr ⇒ CArray

Per-slab sort by flat source address. Delegates to reference.sort_addr(axis: slab_axis): reference-shaped, each slab's cells carry the flat source addresses that sort that slab ascending.

Returns:

  • (CArray) —

    reference-shaped int64



263
264
265
# File 'lib/carray/slab_iterator.rb', line 263

def sort_addr
  @reference.sort_addr(axis: single_sort_axis(:sort_addr))
end

#sort_index ⇒ CArray

Per-slab sort by axis-local index (usable with take_along_axis). Delegates to reference.sort_index(axis: slab_axis): reference-shaped, the axis-local rank order within the slab axis.

Returns:

  • (CArray) —

    reference-shaped int64



272
273
274
# File 'lib/carray/slab_iterator.rb', line 272

def sort_index
  @reference.sort_index(axis: single_sort_axis(:sort_index))
end

#stddev ⇒ CArray

Per-slab sample standard deviation (divisor n - 1).

Returns:

  • (CArray) —

    one value per slab



155
156
157
158
159
160
161
162
163
# File 'lib/carray/slab_iterator.rb', line 155

[:sum, :accumulate, :prod, :mean, :min, :max, :variance, :stddev, :all, :any,
 :variancep, :stddevp, :minmax, :min_index, :max_index,
 :min_addr, :max_addr].each do |op|
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
    def #{op}
      @reference.#{op}(axis: @slab_axes)
    end
  RUBY
end

#stddevp ⇒ CArray

Per-slab population standard deviation (divisor n).

Returns:

  • (CArray) —

    one value per slab



155
156
157
158
159
160
161
162
163
# File 'lib/carray/slab_iterator.rb', line 155

[:sum, :accumulate, :prod, :mean, :min, :max, :variance, :stddev, :all, :any,
 :variancep, :stddevp, :minmax, :min_index, :max_index,
 :min_addr, :max_addr].each do |op|
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
    def #{op}
      @reference.#{op}(axis: @slab_axes)
    end
  RUBY
end

#sum ⇒ CArray

Per-slab sum.

Returns:



155
156
157
158
159
160
161
162
163
# File 'lib/carray/slab_iterator.rb', line 155

[:sum, :accumulate, :prod, :mean, :min, :max, :variance, :stddev, :all, :any,
 :variancep, :stddevp, :minmax, :min_index, :max_index,
 :min_addr, :max_addr].each do |op|
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
    def #{op}
      @reference.#{op}(axis: @slab_axes)
    end
  RUBY
end

#variance ⇒ CArray

Per-slab sample variance (divisor n - 1).

Returns:

  • (CArray) —

    one value per slab



155
156
157
158
159
160
161
162
163
# File 'lib/carray/slab_iterator.rb', line 155

[:sum, :accumulate, :prod, :mean, :min, :max, :variance, :stddev, :all, :any,
 :variancep, :stddevp, :minmax, :min_index, :max_index,
 :min_addr, :max_addr].each do |op|
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
    def #{op}
      @reference.#{op}(axis: @slab_axes)
    end
  RUBY
end

#variancep ⇒ CArray

Per-slab population variance (divisor n).

Returns:

  • (CArray) —

    one value per slab



155
156
157
158
159
160
161
162
163
# File 'lib/carray/slab_iterator.rb', line 155

[:sum, :accumulate, :prod, :mean, :min, :max, :variance, :stddev, :all, :any,
 :variancep, :stddevp, :minmax, :min_index, :max_index,
 :min_addr, :max_addr].each do |op|
  class_eval <<~RUBY, __FILE__, __LINE__ + 1
    def #{op}
      @reference.#{op}(axis: @slab_axes)
    end
  RUBY
end

#wmean(weights) ⇒ CArray

Per-slab weighted mean, weights shaped like the reference.

Returns:



292
293
294
# File 'lib/carray/slab_iterator.rb', line 292

def wmean (weights)
  @reference.wmean(weights, axis: @slab_axes)
end

#wsum(weights) ⇒ CArray

Per-slab weighted sum, weights shaped like the reference.

Returns:



285
286
287
# File 'lib/carray/slab_iterator.rb', line 285

def wsum (weights)
  @reference.wsum(weights, axis: @slab_axes)
end