Class: CAMeld

Inherits:
CAView show all
Defined in:
lib/carray/meld_reduce.rb,
yard-stubs/ruby_carray.rb

Overview

Ragged concatenation view (CArray.meld(*arrays, axis:)). Welds K parents along one of their existing axes with (potentially) uneven segment lengths. Prefix-sum table #seg_offsets keeps segment boundaries explicit so segment resolution stays per-segment rather than per-cell. Ruby entry: CArray.meld / CArray#meld (lib/carray/stack.rb).

See docs/objects/CAMeld.md for the user-facing overview.

Constant Summary

Constants inherited from CArray

CArray::HAVE_COMPLEX, CArray::LAZY_BINCMP_OP_IDS, CArray::LAZY_BINCMP_TOL_OP_IDS, CArray::LAZY_BINOP_OP_IDS, CArray::LAZY_MONOP_OP_IDS, CArray::LAZY_TRIOP_OP_IDS, CArray::UNSPECIFIED, CArray::VERSION

Instance Method Summary collapse

Methods inherited from CArray

#%, #/, #<=>, #==, #T, #[], #[]=, _scan_float, _scan_int, #addr2index, addr2index, #address, align_addr, align_nearest_addr, #all, #all_masked?, #ancestors, #any, #any_masked?, #as_boolean, #as_byte, #as_cmplx128, #as_cmplx256, #as_cmplx64, #as_complex, #as_dcomplex, #as_double, #as_fixlen, #as_float, #as_float128, #as_float32, #as_float64, #as_int, #as_int16, #as_int32, #as_int64, #as_int8, #as_object, #as_short, #as_strided, #as_type, #as_uint16, #as_uint32, #as_uint64, #as_uint8, attach, #attach, attach!, #attach!, #attached?, #attr, #attrs, #axis2addr, #axis_group, big_endian?, #bin, #bin_to, #bincount, #bincount_nd, #bitarray, #bitfield, #bits, #block_view, #blocks, #boolean, boolean, #boolean?, #broadcast_to, #bsearch, #bsearch_addr, byte, #byte, #bytes, cast, #cast_with, #categorize, #choose, #clip, #clip_int16, #clip_int32, #clip_int64, #clip_int8, #clip_uint16, #clip_uint32, #clip_uint64, #clip_uint8, #cmplx128, cmplx128, #cmplx64, cmplx64, #coerce, #collect!, #collect_addr!, #collect_index!, #collect_with_addr!, #collect_with_index!, #complex, complex, #complex?, concatenate, #concatenate, #conditional, const_string, #convert, #copy, #count, #count_masked, #count_not_masked, #crop, #data_class, #data_class=, #data_type, data_type_code, #data_type_name, data_type_name, #dcomplex, dcomplex, #delete_block, #diagonal, #difference, #dim, #dim0, #dim1, #dim2, #dim3, #dim_view, #div, #div!, #divmod, #double, double, #drop_axis, dump, #dump_binary, #each, #each_addr, each_index, #each_index, #each_slab, #each_with_addr, #each_with_index, #elem_copy, #elem_decr, #elem_fetch, #elem_incr, #elem_mask, #elem_masked?, #elem_max, #elem_min, #elem_store, #elem_swap, #elem_unmask, #elements, #empty?, #endian, endian, #entity?, #eql?, #face?, #fake, #false, #farray, #field, #fields, #fields_at, #fill, #fill_copy, #first, fixlen, #fixlen, #fixlen?, fixlen_string, #flags, #flatten, #flip, #float, float, #float32, float32, #float64, float64, #float?, #fmod, #fmod!, #format, format, #frac, #freeze, from_bit_string, #from_bit_string, from_memory_view, fuse, #gather_nd, #grid, #group_by_category, #group_by_run, guard_undef, guess_type_and_bytes, #has_attr?, #has_data_class?, #has_mask?, #hash, #histogram, #histogram1d, #histogram2d, #imag, #imag=, #index, #index2addr, index2addr, #indices, #inherit_mask, #inherit_mask_replace, #initialize, #initialize_copy, #insert_axis, #insert_block, #inspect, #int, int, #int16, int16, #int32, int32, #int64, int64, #int8, int8, #integer?, #intersection, #invert_mask, #is_in, #is_masked, #is_mode, #is_not_masked, #is_real, jit_each, jit_for, jit_map, #join, #last, #lazy, #length, #linear_fetch, #linear_section, little_endian?, load, load_arrow_tensor, #load_binary, #locate_addr, #locate_nearest_addr, #lookup, #map!, #map_addr!, #map_index!, #map_slab, #map_with_addr!, #map_with_index!, #marshal_dump, #marshal_load, #mask, #mask=, #mask_array?, #mask_duplicates, #mask_eq, #mask_invalid, #mask_where, #median, meld, #meld, #members, memory_view_available?, memory_view_reject_reason, meshgrid, #mod, #mod!, #mode, montage, mosaic, #ndim, #none, #normalize_axes, normalize_axis, #normalize_axis, #normalize_index, #numeric?, #nunique, #obj_type, object, #object, #object?, #order, #pack_bits, #parent, #partition, #partition_copy, #paste, #percentile, #project, promote_list, #put_nd, #quantile, #random, #random!, #randomn, #randomn!, #rank, #read_only?, #real, #real=, #real?, #reduce_slab, #refer, #replace_where, #reshape, #resize, result_type, #roll, #root_array, #round, #same_shape?, save, #save_arrow_tensor, #scalar?, #scale, #scale!, #scatter_add!, #scatter_max!, #scatter_min!, #scatter_mul!, #scatter_replace!, #scatter_sub!, #search, #search_addr, #search_nearest, #search_nearest_addr, select, #seq, #seq!, #set_attr, #set_read_only_flag, #shape, #shift, short, #short, #shuffle, #shuffle!, #size, sizeof, #sliding_windows, #snap, #snap_to, #sort, sort_addr, #sort_addr, #sort_copy, #source_code, #span, #span!, #split, #st, stack, #stack, string, #strip_mask, struct, #swap_bytes, tabulate, #template, #then_else, #tile, time, #time, time_range, time_series, #timedelta, #to_a, #to_bit_string, #to_ca, #to_s, #to_type, #transpose, #true, uint16, #uint16, uint32, #uint32, uint64, #uint64, uint8, #uint8, #unfold, #union, union, #unique, #unmask, #valid_addr?, #valid_index?, #validity_bits, #value, #value_array?, #value_counts, #virtual?, #where, #window, #windows, wrap, wrap_memory_view, wrap_readonly, wrap_writable

Methods included from CArray::DataTypeExtension

#arange, #empty, #eye, #full, #identity, #linspace, #ones, #zeros

Constructor Details

This class inherits a constructor from CArray

Instance Method Details

#max(*args, **kw) ⇒ CArray, Numeric

Same result as CArray#max, obtained by reducing each parent and combining, so the melded array is never materialised. Falls back to the generic path when the decomposition does not apply.

Returns:



100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/carray/meld_reduce.rb', line 100

def max(*args, **kw)
  return super unless args.empty? && meld_reduce_fast_path_ok?(kw)
  axis = kw[:axis]
  if axis.nil?
    return super if parents.all? { |p| p.elements == 0 }
    parents.reject { |p| p.elements == 0 }.map(&:max).max
  elsif meld_axis_normalized?(axis)
    return super if parents.all? { |p| p.dim[meld_axis] == 0 }
    nonempty = parents.reject { |p| p.dim[meld_axis] == 0 }
    CArray.stack(nonempty.map { |p| p.max(axis: axis) }).max(axis: 0)
  else
    non_meld_axis_decompose(:max, axis)
  end
end

#mean(*args, **kw) ⇒ CArray, Numeric

Same result as CArray#mean, obtained by reducing each parent and combining, so the melded array is never materialised. Falls back to the generic path when the decomposition does not apply.

Returns:



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/carray/meld_reduce.rb', line 53

def mean(*args, **kw)
  return super unless args.empty? && meld_reduce_fast_path_ok?(kw)
  axis = kw[:axis]
  # `mean` has no identity: an empty set of contributors has no defined
  # mean (0/0 = NaN).  Punt to super, which returns UNDEF: a reduction
  # with no contributors yields the identity where one exists and UNDEF
  # where none does, and never raises.
  if axis.nil?
    return super if parents.all? { |p| p.elements == 0 }
    total_sum = parents.map(&:sum).inject(:+)
    total_count = parents.map(&:elements).inject(:+)
    total_sum / total_count.to_f
  elsif meld_axis_normalized?(axis)
    return super if parents.all? { |p| p.dim[meld_axis] == 0 }
    total_sum = parents.map { |p| p.sum(axis: axis) }.inject(:+)
    total_count = parents.map { |p| p.dim[meld_axis] }.inject(:+)
    total_sum / total_count.to_f
  else
    non_meld_axis_decompose(:mean, axis)
  end
end

#meld_axisInteger

Returns the axis along which the parents are welded (the ragged axis). Non-meld axes have uniform length across parents.

Returns:

  • (Integer)

    in [0, ndim).



98
# File 'yard-stubs/ruby_carray.rb', line 98

def meld_axis; end

#min(*args, **kw) ⇒ CArray, Numeric

Same result as CArray#min, obtained by reducing each parent and combining, so the melded array is never materialised. Falls back to the generic path when the decomposition does not apply.

Returns:



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/carray/meld_reduce.rb', line 79

def min(*args, **kw)
  return super unless args.empty? && meld_reduce_fast_path_ok?(kw)
  axis = kw[:axis]
  # `min` has no identity — empty parent list / all-empty parents punt to
  # super for UNDEF.
  if axis.nil?
    return super if parents.all? { |p| p.elements == 0 }
    parents.reject { |p| p.elements == 0 }.map(&:min).min
  elsif meld_axis_normalized?(axis)
    return super if parents.all? { |p| p.dim[meld_axis] == 0 }
    nonempty = parents.reject { |p| p.dim[meld_axis] == 0 }
    CArray.stack(nonempty.map { |p| p.min(axis: axis) }).min(axis: 0)
  else
    non_meld_axis_decompose(:min, axis)
  end
end

#n_parentsInteger

Returns the number of parent arrays welded by self.

Returns:

  • (Integer)


88
# File 'yard-stubs/ruby_carray.rb', line 88

def n_parents; end

#parentsArray<CArray>

Returns the parent arrays welded by self. The Array holds references to the constructor's inputs; identity is preserved.

Returns:



93
# File 'yard-stubs/ruby_carray.rb', line 93

def parents; end

#seg_offsetsArray<Integer>

Returns the prefix-sum offsets along #meld_axis. Length n_parents + 1; seg_offsets[k] is the starting position of parent k in the view, and seg_offsets[n_parents] equals shape[meld_axis].

Examples:

a = CArray.int32(3, 4) { 0 }
b = CArray.int32(5, 4) { 0 }
c = CArray.int32(1, 4) { 0 }
CArray.meld(a, b, c, axis: 0).seg_offsets   # => [0, 3, 8, 9]

Returns:



110
# File 'yard-stubs/ruby_carray.rb', line 110

def seg_offsets; end

#stddev(*args, **kw) ⇒ CArray, Numeric

Same result as CArray#stddev, obtained by reducing each parent and combining, so the melded array is never materialised. Falls back to the generic path when the decomposition does not apply.

Returns:



148
149
150
# File 'lib/carray/meld_reduce.rb', line 148

def stddev(*args, **kw)
  variance_family(args, kw, sample: true, sqrt: true) { super }
end

#stddevp(*args, **kw) ⇒ CArray, Numeric

Same result as CArray#stddevp, obtained by reducing each parent and combining, so the melded array is never materialised. Falls back to the generic path when the decomposition does not apply.

Returns:



156
157
158
# File 'lib/carray/meld_reduce.rb', line 156

def stddevp(*args, **kw)
  variance_family(args, kw, sample: false, sqrt: true) { super }
end

#sum(*args, **kw) ⇒ Object

---------- monoid reductions (sum / mean / min / max) ----------



37
38
39
40
41
42
43
44
45
46
47
# File 'lib/carray/meld_reduce.rb', line 37

def sum(*args, **kw)
  return super unless args.empty? && meld_reduce_fast_path_ok?(kw)
  axis = kw[:axis]
  if axis.nil?
    parents.map(&:sum).inject(:+)
  elsif meld_axis_normalized?(axis)
    parents.map { |p| p.sum(axis: axis) }.inject(:+)
  else
    non_meld_axis_decompose(:sum, axis)
  end
end

#variance(*args, **kw) ⇒ Object

---------- variance family (Welford combine along meld axis) ----------

Chan / Welford parallel merge: each parent contributes (n_k, mean_k, M2_k = Σ (x - mean_k)^2). Combine two chunks (n1, m1, M1) + (n2, m2, M2):

n = n1 + n2
δ = m2 - m1
mean = m1 + δ * n2 / n
M2   = M1 + M2 + δ² * (n1 * n2 / n)

sample variance = M2 / (n - 1) population variance = M2 / n

M2 per parent is recovered from CArray's variance:

M2_k = variance_k * (n_k - 1)   [sample-variance CArray path]

This inherits CArray's ε-close SIMD reduce contract (memo: reduction is ε-close, not bit-exact). Falls through to super when any parent has n <= 1 along the axis (sample variance undefined).



132
133
134
# File 'lib/carray/meld_reduce.rb', line 132

def variance(*args, **kw)
  variance_family(args, kw, sample: true, sqrt: false) { super }
end

#variancep(*args, **kw) ⇒ CArray, Numeric

Same result as CArray#variancep, obtained by reducing each parent and combining, so the melded array is never materialised. Falls back to the generic path when the decomposition does not apply.

Returns:



140
141
142
# File 'lib/carray/meld_reduce.rb', line 140

def variancep(*args, **kw)
  variance_family(args, kw, sample: false, sqrt: false) { super }
end