carray 3.0.4 → 3.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +205 -0
- data/carray.gemspec +1 -1
- data/ext/ca_array_pool.c +25 -1
- data/ext/ca_axis_dispatch.c +13 -20
- data/ext/ca_categorical_iterator.c +27 -20
- data/ext/ca_compare.c +4 -4
- data/ext/ca_composite_dispatch.c +9 -9
- data/ext/ca_kernel_iterator.c +6 -6
- data/ext/ca_kernel_iterator.h +112 -83
- data/ext/ca_obj_array.c +69 -19
- data/ext/ca_obj_bincmp.c +1 -0
- data/ext/ca_obj_binop.c +1 -0
- data/ext/ca_obj_bitarray.c +5 -1
- data/ext/ca_obj_bitfield.c +58 -43
- data/ext/ca_obj_byte_swap.c +2 -1
- data/ext/ca_obj_const_string.c +15 -3
- data/ext/ca_obj_face.c +42 -1
- data/ext/ca_obj_field.c +13 -3
- data/ext/ca_obj_grid.c +52 -5
- data/ext/ca_obj_monop.c +46 -10
- data/ext/ca_obj_object.c +64 -12
- data/ext/ca_obj_record.c +3 -0
- data/ext/ca_obj_reduce.c +4 -0
- data/ext/ca_obj_refer.c +18 -9
- data/ext/ca_obj_roll.c +26 -6
- data/ext/ca_obj_select.c +34 -5
- data/ext/ca_obj_shift.c +31 -7
- data/ext/ca_obj_stack.c +1 -0
- data/ext/ca_obj_stride.c +28 -19
- data/ext/ca_obj_string.c +11 -2
- data/ext/ca_obj_tile.c +27 -7
- data/ext/ca_obj_transpose.c +8 -4
- data/ext/ca_obj_triop.c +3 -0
- data/ext/ca_obj_window.c +79 -50
- data/ext/ca_op_ipower.c +4 -4
- data/ext/ca_sort_kernels.h +6 -3
- data/ext/carray.h +33 -0
- data/ext/carray_access.c +16 -3
- data/ext/carray_attribute.c +24 -0
- data/ext/carray_cast.c +243 -82
- data/ext/carray_cast_func.rb +56 -26
- data/ext/carray_conversion.c +2 -2
- data/ext/carray_core.c +3 -0
- data/ext/carray_count.c +6 -0
- data/ext/carray_element.c +9 -4
- data/ext/carray_factorize.c +20 -20
- data/ext/carray_generate.c +8 -2
- data/ext/carray_histogram.c +1 -1
- data/ext/carray_index_classifier.c +4 -4
- data/ext/carray_internal.h +12 -0
- data/ext/carray_kernels_bincmp.c +168 -168
- data/ext/carray_kernels_binop.c +900 -900
- data/ext/carray_kernels_init.c +4 -4
- data/ext/carray_kernels_moncmp.c +96 -96
- data/ext/carray_kernels_monop.c +1984 -1984
- data/ext/carray_kernels_reduce_aggregate.c +1733 -1733
- data/ext/carray_kernels_reduce_cumulative.c +642 -642
- data/ext/carray_kernels_reduce_extreme.c +1150 -1150
- data/ext/carray_kernels_reduce_variance.c +258 -258
- data/ext/carray_kernels_scan.c +128 -128
- data/ext/carray_kernels_search.c +340 -340
- data/ext/carray_kernels_sort.c +295 -304
- data/ext/carray_kernels_triop.c +114 -114
- data/ext/carray_key_windows.c +4 -0
- data/ext/carray_mask.c +45 -22
- data/ext/carray_memory_view.c +2 -2
- data/ext/carray_operator.c +5 -5
- data/ext/carray_order.c +227 -8
- data/ext/carray_random.c +18 -18
- data/ext/carray_scatter.c +24 -7
- data/ext/carray_slab.c +32 -9
- data/ext/carray_sort.c +224 -16
- data/ext/carray_sort_kernel.c +5 -7
- data/ext/carray_struct.c +35 -43
- data/ext/carray_time_text.c +4 -2
- data/ext/carray_utils.c +63 -21
- data/ext/mkkernel.rb +210 -115
- data/ext/version.h +4 -4
- data/lib/carray/attribute.rb +17 -4
- data/lib/carray/basics.rb +27 -7
- data/lib/carray/categorical.rb +30 -16
- data/lib/carray/categorical_iterator.rb +6 -6
- data/lib/carray/const_string.rb +10 -0
- data/lib/carray/data_type_extension.rb +8 -1
- data/lib/carray/fixlen_string.rb +41 -2
- data/lib/carray/frame/column_verbs.rb +4 -3
- data/lib/carray/frame/concat.rb +17 -3
- data/lib/carray/frame/frame.rb +6 -7
- data/lib/carray/frame/group.rb +100 -13
- data/lib/carray/frame/io.rb +3 -1
- data/lib/carray/fuse_source.rb +31 -2
- data/lib/carray/lazy.rb +35 -0
- data/lib/carray/methods/is_in.rb +8 -1
- data/lib/carray/segment_iterator.rb +12 -8
- data/lib/carray/serialize.rb +19 -2
- data/lib/carray/stack.rb +15 -12
- data/lib/carray/string.rb +8 -0
- data/lib/carray/string_operation_extension.rb +13 -5
- data/lib/carray/struct_builder.rb +5 -3
- data/lib/carray/time.rb +107 -68
- data/yard-stubs/ca_obj_transpose.rb +5 -4
- data/yard-stubs/carray_attribute.rb +3 -1
- data/yard-stubs/carray_cast.rb +2 -0
- data/yard-stubs/carray_conversion.rb +5 -1
- data/yard-stubs/carray_element.rb +7 -6
- data/yard-stubs/carray_mask.rb +8 -3
- data/yard-stubs/carray_math.rb +14 -4
- data/yard-stubs/carray_order.rb +100 -4
- data/yard-stubs/carray_scatter.rb +7 -5
- metadata +1 -1
data/lib/carray/time.rb
CHANGED
|
@@ -113,6 +113,13 @@ module CATimeUnitAlgebra
|
|
|
113
113
|
end
|
|
114
114
|
end
|
|
115
115
|
|
|
116
|
+
# How a refusal names an operand: a Face by its class, any other array as
|
|
117
|
+
# a CArray (a lazy expression's node classes are not the user's), anything
|
|
118
|
+
# else by its class.
|
|
119
|
+
def operand_name(x)
|
|
120
|
+
( x.is_a?(CArray) && !x.face? ) ? "CArray" : x.class.to_s
|
|
121
|
+
end
|
|
122
|
+
|
|
116
123
|
# A single value an operator meets an array with, as a one-cell array
|
|
117
124
|
# marked scalar (a CScalar) of its kind, or nil when it is not one: a
|
|
118
125
|
# duration -- a CATimedelta::Element, or a String that reads as one
|
|
@@ -138,6 +145,20 @@ module CATimeUnitAlgebra
|
|
|
138
145
|
end
|
|
139
146
|
end
|
|
140
147
|
|
|
148
|
+
# A duration String added to or subtracted from a time, as one step of its
|
|
149
|
+
# own resolution: "15 minutes" is one 15-minute step, the duration
|
|
150
|
+
# CArray.int64(1).timedelta(unit: "15 minutes") is, so it lands on a
|
|
151
|
+
# "10 minutes" grid or is refused in the same way. nil for anything else.
|
|
152
|
+
def step_operand(x)
|
|
153
|
+
return nil unless x.is_a?(String)
|
|
154
|
+
res = begin
|
|
155
|
+
CATime::Resolution.parse(x)
|
|
156
|
+
rescue ArgumentError
|
|
157
|
+
return nil
|
|
158
|
+
end
|
|
159
|
+
CATimedelta.wrap(CScalar.int64 { 1 }, unit: res)
|
|
160
|
+
end
|
|
161
|
+
|
|
141
162
|
def scalar_instant(t, unit)
|
|
142
163
|
v = begin
|
|
143
164
|
convert_instant!(t.parent, t.unit, unit)[0]
|
|
@@ -1071,7 +1092,7 @@ class CATime
|
|
|
1071
1092
|
# resolution (see §4 of docs/CATime.md).
|
|
1072
1093
|
# @return [CArray]
|
|
1073
1094
|
def ticks
|
|
1074
|
-
|
|
1095
|
+
face_storage
|
|
1075
1096
|
end
|
|
1076
1097
|
|
|
1077
1098
|
# @overload to_unit(unit)
|
|
@@ -1101,7 +1122,7 @@ class CATime
|
|
|
1101
1122
|
# @raise [RangeError] when the widened ticks overflow int64.
|
|
1102
1123
|
def to_unit(unit)
|
|
1103
1124
|
to = CATime::Resolution.parse(unit)
|
|
1104
|
-
CATimeUnitAlgebra.convert_instant_floor(
|
|
1125
|
+
CATimeUnitAlgebra.convert_instant_floor(face_storage, self.unit, to).time(unit: to)
|
|
1105
1126
|
end
|
|
1106
1127
|
|
|
1107
1128
|
# @overload +(other)
|
|
@@ -1116,7 +1137,9 @@ class CATime
|
|
|
1116
1137
|
# into whole ticks; on any other (`:W`, `"3 days"`) a month raises, as a
|
|
1117
1138
|
# fixed duration on a month or year grid does. Adding two datetimes is
|
|
1118
1139
|
# ill-defined. A single duration -- a {CATimedelta::Element} or a String
|
|
1119
|
-
# such as `"3 days"` -- is added to every cell
|
|
1140
|
+
# such as `"3 days"` -- is added to every cell; a String is one step of
|
|
1141
|
+
# its own resolution, so `"15 minutes"` on a `"10 minutes"` grid raises
|
|
1142
|
+
# as `CArray.int64(1).timedelta(unit: "15 minutes")` does.
|
|
1120
1143
|
# @param other [CATimedelta, CATimedelta::Element, String]
|
|
1121
1144
|
# (or a MemoryView producer whose +to_ca+ gives one, such as an Arrow
|
|
1122
1145
|
# duration array)
|
|
@@ -1126,17 +1149,18 @@ class CATime
|
|
|
1126
1149
|
# @raise [RangeError] when a result leaves the range of int64 ticks.
|
|
1127
1150
|
def +(other)
|
|
1128
1151
|
given, other = other, CATimeUnitAlgebra.operand(other)
|
|
1129
|
-
other = CATimeUnitAlgebra.
|
|
1152
|
+
other = CATimeUnitAlgebra.step_operand(other) ||
|
|
1153
|
+
CATimeUnitAlgebra.scalar_operand(other, unit) || other
|
|
1130
1154
|
case other
|
|
1131
1155
|
when CATimedelta
|
|
1132
1156
|
return shifted_by_months(other, 1) if moved_by_months?(other)
|
|
1133
1157
|
d = CATimeUnitAlgebra.duration_on_grid(other.parent, other.unit, unit)
|
|
1134
1158
|
d = d[0] if other.scalar?
|
|
1135
|
-
CATimeUnitAlgebra.checked_add(
|
|
1159
|
+
CATimeUnitAlgebra.checked_add(face_storage, d).time(unit: unit)
|
|
1136
1160
|
when CATime
|
|
1137
1161
|
raise TypeError, "CATime + CATime is ill-defined"
|
|
1138
1162
|
else
|
|
1139
|
-
raise TypeError, "CATime + #{given
|
|
1163
|
+
raise TypeError, "CATime + #{CATimeUnitAlgebra.operand_name(given)} is not allowed: add a duration " \
|
|
1140
1164
|
"(a CATimedelta, a CATimedelta::Element or a String such as \"3 days\")"
|
|
1141
1165
|
end
|
|
1142
1166
|
end
|
|
@@ -1155,21 +1179,22 @@ class CATime
|
|
|
1155
1179
|
# @raise [TypeError] on an unsupported operand.
|
|
1156
1180
|
def -(other)
|
|
1157
1181
|
given, other = other, CATimeUnitAlgebra.operand(other)
|
|
1158
|
-
other = CATimeUnitAlgebra.
|
|
1182
|
+
other = CATimeUnitAlgebra.step_operand(other) ||
|
|
1183
|
+
CATimeUnitAlgebra.scalar_operand(other, unit) || other
|
|
1159
1184
|
case other
|
|
1160
1185
|
when CATimedelta
|
|
1161
1186
|
return shifted_by_months(other, -1) if moved_by_months?(other)
|
|
1162
1187
|
d = CATimeUnitAlgebra.duration_on_grid(other.parent, other.unit, unit)
|
|
1163
1188
|
d = d[0] if other.scalar?
|
|
1164
|
-
CATimeUnitAlgebra.checked_sub(
|
|
1189
|
+
CATimeUnitAlgebra.checked_sub(face_storage, d).time(unit: unit)
|
|
1165
1190
|
when CATime
|
|
1166
1191
|
u = CATimeUnitAlgebra.diff_unit(unit, other.unit)
|
|
1167
|
-
a = CATimeUnitAlgebra.convert_instant!(
|
|
1192
|
+
a = CATimeUnitAlgebra.convert_instant!(face_storage, unit, u)
|
|
1168
1193
|
b = CATimeUnitAlgebra.convert_instant!(other.parent, other.unit, u)
|
|
1169
1194
|
b = b[0] if other.scalar?
|
|
1170
1195
|
CATimeUnitAlgebra.checked_sub(a, b).timedelta(unit: u)
|
|
1171
1196
|
else
|
|
1172
|
-
raise TypeError, "CATime - #{given
|
|
1197
|
+
raise TypeError, "CATime - #{CATimeUnitAlgebra.operand_name(given)} is not allowed: subtract a duration " \
|
|
1173
1198
|
"(a CATimedelta, a CATimedelta::Element or a String such as \"3 days\") " \
|
|
1174
1199
|
"or a time (a CATime, a CATime::Element, a Time, a Date or a String)"
|
|
1175
1200
|
end
|
|
@@ -1189,7 +1214,7 @@ class CATime
|
|
|
1189
1214
|
private def shifted_by_months (td, sign)
|
|
1190
1215
|
months = td.parent.int64 * (sign * CATimeUnitAlgebra.months_per_tick(td.unit))
|
|
1191
1216
|
months = months[0] if td.scalar?
|
|
1192
|
-
CATimeUnitAlgebra.shift_months(
|
|
1217
|
+
CATimeUnitAlgebra.shift_months(face_storage, unit, months).time(unit: unit)
|
|
1193
1218
|
end
|
|
1194
1219
|
|
|
1195
1220
|
# @overload pmax(other)
|
|
@@ -1255,8 +1280,9 @@ class CATime
|
|
|
1255
1280
|
# they run on the storage ticks and round the result back to the nearest
|
|
1256
1281
|
# tick of `unit`. A caller who needs a finer answer declares the grid
|
|
1257
1282
|
# first (`t.to_unit(:ms).mean`) -- the same rule linear_fetch follows.
|
|
1258
|
-
# Rounding is to nearest,
|
|
1259
|
-
#
|
|
1283
|
+
# Rounding is to nearest, and a tie goes to the later tick: rounding half
|
|
1284
|
+
# away from zero would send a tie later after 1970 and earlier before it,
|
|
1285
|
+
# so moving the data by whole days would change the answer.
|
|
1260
1286
|
|
|
1261
1287
|
# @overload mean(axis: nil, **opts)
|
|
1262
1288
|
# Returns the centroid time on `self`'s unit (§8), rounded to the
|
|
@@ -1492,7 +1518,7 @@ class CATime
|
|
|
1492
1518
|
# @return [Element, CATime] an {Element} for a scalar `addr`, `nil` when
|
|
1493
1519
|
# that single answer is undetermined.
|
|
1494
1520
|
def linear_fetch (addr, **opts)
|
|
1495
|
-
r =
|
|
1521
|
+
r = face_storage.float64.linear_fetch(addr, **opts)
|
|
1496
1522
|
case r
|
|
1497
1523
|
when CArray
|
|
1498
1524
|
# mask_invalid before the int64 cast: the cast turns a NaN into 0, which
|
|
@@ -1523,7 +1549,7 @@ class CATime
|
|
|
1523
1549
|
def to_time
|
|
1524
1550
|
if CATimeUnitAlgebra::FIXED.key?(unit.base)
|
|
1525
1551
|
f = unit.tick_ratio # exact seconds / tick (Rational)
|
|
1526
|
-
|
|
1552
|
+
face_storage.convert(:object) {|v| Time.at(v * f, in: 'UTC')}
|
|
1527
1553
|
else # calendar: exact granule midnight
|
|
1528
1554
|
(days_since_epoch * 86400).convert(:object) {|v| Time.at(v, in: 'UTC')}
|
|
1529
1555
|
end
|
|
@@ -1557,8 +1583,8 @@ class CATime
|
|
|
1557
1583
|
# @return [CArray]
|
|
1558
1584
|
def year
|
|
1559
1585
|
case unit.base
|
|
1560
|
-
when :Y then
|
|
1561
|
-
when :M then (
|
|
1586
|
+
when :Y then face_storage * unit.count + 1970
|
|
1587
|
+
when :M then (face_storage * unit.count + 1970 * 12) / 12
|
|
1562
1588
|
else CATimeCivil.civil_from_days(days_since_epoch)[0]
|
|
1563
1589
|
end
|
|
1564
1590
|
end
|
|
@@ -1568,9 +1594,9 @@ class CATime
|
|
|
1568
1594
|
# @return [CArray] integer.
|
|
1569
1595
|
def month
|
|
1570
1596
|
case unit.base
|
|
1571
|
-
when :Y then
|
|
1597
|
+
when :Y then face_storage * 0 + 1
|
|
1572
1598
|
when :M
|
|
1573
|
-
mo =
|
|
1599
|
+
mo = face_storage * unit.count + 1970 * 12
|
|
1574
1600
|
mo % 12 + 1
|
|
1575
1601
|
else CATimeCivil.civil_from_days(days_since_epoch)[1]
|
|
1576
1602
|
end
|
|
@@ -1581,7 +1607,7 @@ class CATime
|
|
|
1581
1607
|
# @return [CArray] integer.
|
|
1582
1608
|
def day
|
|
1583
1609
|
case unit.base
|
|
1584
|
-
when :Y, :M then
|
|
1610
|
+
when :Y, :M then face_storage * 0 + 1
|
|
1585
1611
|
else CATimeCivil.civil_from_days(days_since_epoch)[2]
|
|
1586
1612
|
end
|
|
1587
1613
|
end
|
|
@@ -1704,7 +1730,7 @@ class CATime
|
|
|
1704
1730
|
# writes to_unit(:D) first) -- and the result is rounded back to a tick.
|
|
1705
1731
|
def reduce_on_own_grid(op, kind, args, opts)
|
|
1706
1732
|
with_surface_fill(opts) do |o|
|
|
1707
|
-
round_and_relift(
|
|
1733
|
+
round_and_relift(face_storage.public_send(op, *args, **o), kind)
|
|
1708
1734
|
end
|
|
1709
1735
|
end
|
|
1710
1736
|
|
|
@@ -1714,14 +1740,15 @@ class CATime
|
|
|
1714
1740
|
def round_and_relift(r, kind)
|
|
1715
1741
|
case r
|
|
1716
1742
|
when Numeric
|
|
1717
|
-
v = r.round
|
|
1743
|
+
v = kind == :timedelta ? r.round : (r + 0.5).floor
|
|
1718
1744
|
kind == :timedelta ? CATimedelta::Element.new(v, unit) : Element.new(v, unit)
|
|
1719
1745
|
when CArray
|
|
1720
1746
|
# A cell with no answer arrives masked and the mask survives the cast.
|
|
1721
1747
|
# NaN does not: it has no int64 image, so a `fill_value: Float::NAN`
|
|
1722
1748
|
# cell would cast to garbage bits. mask_invalid turns it into UNDEF,
|
|
1723
1749
|
# which is what "no answer" means here.
|
|
1724
|
-
|
|
1750
|
+
near = kind == :timedelta ? r.round : (r + 0.5).floor
|
|
1751
|
+
iv = near.mask_invalid.int64
|
|
1725
1752
|
kind == :timedelta ? iv.timedelta(unit: unit) : iv.time(unit: unit)
|
|
1726
1753
|
when Array
|
|
1727
1754
|
r.map {|x| round_and_relift(x, kind)}
|
|
@@ -1781,7 +1808,7 @@ class CATimedelta
|
|
|
1781
1808
|
# measured in this array's resolution (see {CATime#ticks}).
|
|
1782
1809
|
# @return [CArray]
|
|
1783
1810
|
def ticks
|
|
1784
|
-
|
|
1811
|
+
face_storage
|
|
1785
1812
|
end
|
|
1786
1813
|
|
|
1787
1814
|
# @overload to_unit(unit)
|
|
@@ -1803,7 +1830,7 @@ class CATimedelta
|
|
|
1803
1830
|
# @raise [RangeError] when the widened ticks overflow int64.
|
|
1804
1831
|
def to_unit(unit)
|
|
1805
1832
|
to = CATime::Resolution.parse(unit)
|
|
1806
|
-
CATimeUnitAlgebra.convert_scale_trunc(
|
|
1833
|
+
CATimeUnitAlgebra.convert_scale_trunc(face_storage, self.unit, to).timedelta(unit: to)
|
|
1807
1834
|
end
|
|
1808
1835
|
|
|
1809
1836
|
# @overload +(other)
|
|
@@ -1821,16 +1848,16 @@ class CATimedelta
|
|
|
1821
1848
|
case other
|
|
1822
1849
|
when CATimedelta
|
|
1823
1850
|
u = common_duration_unit(other.unit)
|
|
1824
|
-
a = CATimeUnitAlgebra.convert_scale!(
|
|
1851
|
+
a = CATimeUnitAlgebra.convert_scale!(face_storage, unit, u)
|
|
1825
1852
|
b = CATimeUnitAlgebra.convert_scale!(other.parent, other.unit, u)
|
|
1826
1853
|
b = b[0] if other.scalar?
|
|
1827
1854
|
CATimeUnitAlgebra.checked_add(a, b).timedelta(unit: u)
|
|
1828
1855
|
when CATime
|
|
1829
1856
|
return other + self unless other.scalar? # commutative -> time's unit
|
|
1830
|
-
d = CATimeUnitAlgebra.duration_on_grid(
|
|
1857
|
+
d = CATimeUnitAlgebra.duration_on_grid(face_storage, unit, other.unit)
|
|
1831
1858
|
CATimeUnitAlgebra.checked_add(d, other.parent[0]).time(unit: other.unit)
|
|
1832
1859
|
else
|
|
1833
|
-
raise TypeError, "CATimedelta + #{given
|
|
1860
|
+
raise TypeError, "CATimedelta + #{CATimeUnitAlgebra.operand_name(given)} is not allowed"
|
|
1834
1861
|
end
|
|
1835
1862
|
end
|
|
1836
1863
|
|
|
@@ -1848,12 +1875,12 @@ class CATimedelta
|
|
|
1848
1875
|
case other
|
|
1849
1876
|
when CATimedelta
|
|
1850
1877
|
u = common_duration_unit(other.unit)
|
|
1851
|
-
a = CATimeUnitAlgebra.convert_scale!(
|
|
1878
|
+
a = CATimeUnitAlgebra.convert_scale!(face_storage, unit, u)
|
|
1852
1879
|
b = CATimeUnitAlgebra.convert_scale!(other.parent, other.unit, u)
|
|
1853
1880
|
b = b[0] if other.scalar?
|
|
1854
1881
|
CATimeUnitAlgebra.checked_sub(a, b).timedelta(unit: u)
|
|
1855
1882
|
else
|
|
1856
|
-
raise TypeError, "CATimedelta - #{given
|
|
1883
|
+
raise TypeError, "CATimedelta - #{CATimeUnitAlgebra.operand_name(given)} is not allowed"
|
|
1857
1884
|
end
|
|
1858
1885
|
end
|
|
1859
1886
|
|
|
@@ -1862,14 +1889,14 @@ class CATimedelta
|
|
|
1862
1889
|
# unit.
|
|
1863
1890
|
# @return [CATimedelta]
|
|
1864
1891
|
def abs
|
|
1865
|
-
|
|
1892
|
+
face_storage.abs.timedelta(unit: unit)
|
|
1866
1893
|
end
|
|
1867
1894
|
|
|
1868
1895
|
# @overload -@
|
|
1869
1896
|
# Returns each duration with its sign reversed, on the same unit.
|
|
1870
1897
|
# @return [CATimedelta]
|
|
1871
1898
|
def -@
|
|
1872
|
-
(-
|
|
1899
|
+
(-face_storage).timedelta(unit: unit)
|
|
1873
1900
|
end
|
|
1874
1901
|
|
|
1875
1902
|
# @overload *(other)
|
|
@@ -1879,8 +1906,8 @@ class CATimedelta
|
|
|
1879
1906
|
# @raise [TypeError] when `other` is not an Integer.
|
|
1880
1907
|
def *(other)
|
|
1881
1908
|
case other
|
|
1882
|
-
when Integer then CATimeUnitAlgebra.checked_mul(
|
|
1883
|
-
else raise TypeError, "CATimedelta * #{other
|
|
1909
|
+
when Integer then CATimeUnitAlgebra.checked_mul(face_storage, other).timedelta(unit: unit)
|
|
1910
|
+
else raise TypeError, "CATimedelta * #{CATimeUnitAlgebra.operand_name(other)} is not allowed (Integer only)"
|
|
1884
1911
|
end
|
|
1885
1912
|
end
|
|
1886
1913
|
|
|
@@ -1898,13 +1925,13 @@ class CATimedelta
|
|
|
1898
1925
|
given, other = other, CATimeUnitAlgebra.operand(other)
|
|
1899
1926
|
case other
|
|
1900
1927
|
when Integer
|
|
1901
|
-
CATimeUnitAlgebra.trunc_divide(
|
|
1928
|
+
CATimeUnitAlgebra.trunc_divide(face_storage, other).timedelta(unit: unit)
|
|
1902
1929
|
when CATimedelta
|
|
1903
1930
|
# A ratio of durations is a number, not a count of whole ticks: 90 s /
|
|
1904
1931
|
# 60 s is 1.5. Both are brought to one unit first, so the ratio does
|
|
1905
1932
|
# not depend on the units they are held in.
|
|
1906
1933
|
u = common_duration_unit(other.unit)
|
|
1907
|
-
CATimeUnitAlgebra.convert_scale!(
|
|
1934
|
+
CATimeUnitAlgebra.convert_scale!(face_storage, unit, u).to_type(:float64) /
|
|
1908
1935
|
CATimeUnitAlgebra.convert_scale!(other.parent, other.unit, u)
|
|
1909
1936
|
else raise TypeError, "CATimedelta / #{given.class} is not allowed"
|
|
1910
1937
|
end
|
|
@@ -1926,7 +1953,7 @@ class CATimedelta
|
|
|
1926
1953
|
# reduction, if any of its cells does not).
|
|
1927
1954
|
def sum(*args, **opts)
|
|
1928
1955
|
with_surface_fill(opts) { |o|
|
|
1929
|
-
exact_sum_relift(
|
|
1956
|
+
exact_sum_relift(face_storage.accumulate(*args, **o), face_storage.sum(*args, **o))
|
|
1930
1957
|
}
|
|
1931
1958
|
end
|
|
1932
1959
|
|
|
@@ -1955,7 +1982,7 @@ class CATimedelta
|
|
|
1955
1982
|
# the same answer when it fits and raises RangeError when it does not.
|
|
1956
1983
|
# @return [Element, CATimedelta]
|
|
1957
1984
|
def accumulate(*args, **opts)
|
|
1958
|
-
with_surface_fill(opts) { |o| round_and_relift(
|
|
1985
|
+
with_surface_fill(opts) { |o| round_and_relift(face_storage.accumulate(*args, **o)) }
|
|
1959
1986
|
end
|
|
1960
1987
|
|
|
1961
1988
|
# @overload cumsum(axis: nil)
|
|
@@ -1966,8 +1993,8 @@ class CATimedelta
|
|
|
1966
1993
|
# @return [CATimedelta]
|
|
1967
1994
|
# @raise [RangeError] if any cell of the running sum does not fit int64.
|
|
1968
1995
|
def cumsum(*args, **opts)
|
|
1969
|
-
exact_sum_relift(
|
|
1970
|
-
|
|
1996
|
+
exact_sum_relift(face_storage.send(:cumsum_in_own_type, *args, **opts),
|
|
1997
|
+
face_storage.cumsum(*args, **opts))
|
|
1971
1998
|
end
|
|
1972
1999
|
|
|
1973
2000
|
# @overload prod(*)
|
|
@@ -1985,7 +2012,7 @@ class CATimedelta
|
|
|
1985
2012
|
# Returns the mean duration rounded to the nearest unit count.
|
|
1986
2013
|
# @return [Element, CATimedelta]
|
|
1987
2014
|
def mean(*args, **opts)
|
|
1988
|
-
with_surface_fill(opts) { |o| round_and_relift(
|
|
2015
|
+
with_surface_fill(opts) { |o| round_and_relift(face_storage.mean(*args, **o)) }
|
|
1989
2016
|
end
|
|
1990
2017
|
|
|
1991
2018
|
# median / percentile / quantile / stddev / stddevp report on this array's
|
|
@@ -1997,7 +2024,7 @@ class CATimedelta
|
|
|
1997
2024
|
# Returns the median duration on `self`'s unit.
|
|
1998
2025
|
# @return [Element, CATimedelta]
|
|
1999
2026
|
def median(*args, **opts)
|
|
2000
|
-
with_surface_fill(opts) { |o| round_and_relift(
|
|
2027
|
+
with_surface_fill(opts) { |o| round_and_relift(face_storage.median(*args, **o)) }
|
|
2001
2028
|
end
|
|
2002
2029
|
|
|
2003
2030
|
# @overload percentile(*p, axis: nil, **opts)
|
|
@@ -2006,7 +2033,7 @@ class CATimedelta
|
|
|
2006
2033
|
# two or more give an Array).
|
|
2007
2034
|
# @return [Element, CATimedelta, Array<Element>, Array<CATimedelta>]
|
|
2008
2035
|
def percentile(*args, **opts)
|
|
2009
|
-
with_surface_fill(opts) { |o| round_and_relift(
|
|
2036
|
+
with_surface_fill(opts) { |o| round_and_relift(face_storage.percentile(*args, **o)) }
|
|
2010
2037
|
end
|
|
2011
2038
|
|
|
2012
2039
|
# @overload quantile(axis: nil, **opts)
|
|
@@ -2014,7 +2041,7 @@ class CATimedelta
|
|
|
2014
2041
|
# `self`'s unit.
|
|
2015
2042
|
# @return [Array<Element>, Array<CATimedelta>]
|
|
2016
2043
|
def quantile(*args, **opts)
|
|
2017
|
-
with_surface_fill(opts) { |o| round_and_relift(
|
|
2044
|
+
with_surface_fill(opts) { |o| round_and_relift(face_storage.quantile(*args, **o)) }
|
|
2018
2045
|
end
|
|
2019
2046
|
|
|
2020
2047
|
# @overload stddev(axis: nil, **opts)
|
|
@@ -2023,7 +2050,7 @@ class CATimedelta
|
|
|
2023
2050
|
# the precision matters.
|
|
2024
2051
|
# @return [Element, CATimedelta]
|
|
2025
2052
|
def stddev(*args, **opts)
|
|
2026
|
-
with_surface_fill(opts) { |o| round_and_relift(
|
|
2053
|
+
with_surface_fill(opts) { |o| round_and_relift(face_storage.stddev(*args, **o)) }
|
|
2027
2054
|
end
|
|
2028
2055
|
|
|
2029
2056
|
# @overload stddevp(axis: nil, **opts)
|
|
@@ -2031,7 +2058,7 @@ class CATimedelta
|
|
|
2031
2058
|
# {#stddev}.
|
|
2032
2059
|
# @return [Element, CATimedelta]
|
|
2033
2060
|
def stddevp(*args, **opts)
|
|
2034
|
-
with_surface_fill(opts) { |o| round_and_relift(
|
|
2061
|
+
with_surface_fill(opts) { |o| round_and_relift(face_storage.stddevp(*args, **o)) }
|
|
2035
2062
|
end
|
|
2036
2063
|
|
|
2037
2064
|
def round_and_relift(r)
|
|
@@ -2168,7 +2195,7 @@ class CATimedelta
|
|
|
2168
2195
|
# @return [Element, CATimedelta] an {Element} for a scalar `addr`, `nil`
|
|
2169
2196
|
# when that single answer is undetermined.
|
|
2170
2197
|
def linear_fetch (addr, **opts)
|
|
2171
|
-
r =
|
|
2198
|
+
r = face_storage.float64.linear_fetch(addr, **opts)
|
|
2172
2199
|
case r
|
|
2173
2200
|
when CArray then r.mask_invalid.round.int64.timedelta(unit: unit)
|
|
2174
2201
|
when Numeric then r.to_f.nan? ? nil : Element.new(r.round, unit)
|
|
@@ -3464,8 +3491,18 @@ class CATime
|
|
|
3464
3491
|
fl = o + q * step_ticks
|
|
3465
3492
|
return bucket_head_as_time(fl + step_ticks * n.ne(fl), mul, su)
|
|
3466
3493
|
when :round
|
|
3467
|
-
|
|
3468
|
-
|
|
3494
|
+
if mul == 1 and [:M, :Y].include?(su.base)
|
|
3495
|
+
# A month or year tick is the start of its month or year, so the
|
|
3496
|
+
# nearest head is by the instant, measured in days.
|
|
3497
|
+
fl = o + q * step_ticks
|
|
3498
|
+
here = days_since_epoch
|
|
3499
|
+
lo = fl.time(unit: su).send(:days_since_epoch)
|
|
3500
|
+
hi = (fl + step_ticks).time(unit: su).send(:days_since_epoch)
|
|
3501
|
+
q = q + (hi - here).le(here - lo) # ties -> future
|
|
3502
|
+
else
|
|
3503
|
+
r = d - q * step_ticks # 0 <= r < step_ticks
|
|
3504
|
+
q = q + r.ge((step_ticks + 1) / 2) # ties -> future; no 2*d / 2*r
|
|
3505
|
+
end
|
|
3469
3506
|
end
|
|
3470
3507
|
bucket_head_as_time(o + q * step_ticks, mul, su)
|
|
3471
3508
|
end
|
|
@@ -3517,8 +3554,10 @@ class CATime
|
|
|
3517
3554
|
# @overload round(grid = nil, unit:, origin: nil)
|
|
3518
3555
|
# {#snap} with `direction: :round` -- each element at its nearest bucket
|
|
3519
3556
|
# head, ties toward the future. Exact for odd `step_ticks` (no half-tick
|
|
3520
|
-
# loss). For a calendar bucket the nearest head is by
|
|
3521
|
-
#
|
|
3557
|
+
# loss). For a calendar bucket the nearest head is by the instant (month
|
|
3558
|
+
# lengths vary), ties toward the future. A month or year storage tick
|
|
3559
|
+
# stands for the start of its month or year, so a `:M` array rounds as
|
|
3560
|
+
# the same dates on `:D` do: 1889-07 to the year is 1889.
|
|
3522
3561
|
# @return [CATime]
|
|
3523
3562
|
def round(grid = nil, unit: nil, origin: nil)
|
|
3524
3563
|
snap(grid, unit: unit, origin: origin, direction: :round)
|
|
@@ -3604,7 +3643,7 @@ class CATime
|
|
|
3604
3643
|
|
|
3605
3644
|
# Storage ticks lifted into the numerator grid (see {#resolve_timestep_grid}).
|
|
3606
3645
|
def storage_ticks_in_numerator_grid(mul)
|
|
3607
|
-
mul == 1 ?
|
|
3646
|
+
mul == 1 ? face_storage : CATimeUnitAlgebra.widen(face_storage, mul)
|
|
3608
3647
|
end
|
|
3609
3648
|
|
|
3610
3649
|
# A bucket head computed in numerator ticks, back as a {CATime} in the
|
|
@@ -3638,15 +3677,15 @@ class CATime
|
|
|
3638
3677
|
# an empty array, or one whose every cell is masked.
|
|
3639
3678
|
def raise_if_int64_overflow(su, mul, o, step_ticks = nil, kind = nil)
|
|
3640
3679
|
return unless mul > 1 or FINE_UNITS.include?(su.base)
|
|
3641
|
-
min =
|
|
3680
|
+
min = face_storage.min
|
|
3642
3681
|
return if min == UNDEF
|
|
3643
3682
|
lo = Integer(min) * mul
|
|
3644
|
-
hi = Integer(
|
|
3683
|
+
hi = Integer(face_storage.max) * mul
|
|
3645
3684
|
chk = ->(v, w) { CATimeGrid.check_int64_range(v, w) }
|
|
3646
3685
|
chk.(lo, "ticks in bucket resolution")
|
|
3647
3686
|
chk.(hi, "ticks in bucket resolution")
|
|
3648
|
-
chk.(lo - o, "
|
|
3649
|
-
chk.(hi - o, "
|
|
3687
|
+
chk.(lo - o, "face_storage - origin")
|
|
3688
|
+
chk.(hi - o, "face_storage - origin")
|
|
3650
3689
|
if kind
|
|
3651
3690
|
chk.(bucket_head_ticks(lo, o, step_ticks, kind), "bucket head")
|
|
3652
3691
|
chk.(bucket_head_ticks(hi, o, step_ticks, kind), "bucket head")
|
|
@@ -3674,22 +3713,22 @@ class CATime
|
|
|
3674
3713
|
case res.base
|
|
3675
3714
|
when :Y
|
|
3676
3715
|
ones = CArray.int64(*shape) { 1 }
|
|
3677
|
-
CATimeCivil.days_from_civil(
|
|
3716
|
+
CATimeCivil.days_from_civil(face_storage * res.count + 1970, ones, ones)
|
|
3678
3717
|
when :M
|
|
3679
|
-
mo =
|
|
3718
|
+
mo = face_storage * res.count + 1970 * 12
|
|
3680
3719
|
y = mo / 12
|
|
3681
3720
|
m = mo - y * 12 + 1
|
|
3682
3721
|
CATimeCivil.days_from_civil(y, m, CArray.int64(*shape) { 1 })
|
|
3683
|
-
when :W then
|
|
3684
|
-
when :D then
|
|
3722
|
+
when :W then face_storage * res.count * 7
|
|
3723
|
+
when :D then face_storage * res.count
|
|
3685
3724
|
else # fixed sub-day storage
|
|
3686
3725
|
day = CATime::Resolution.new(1, :D)
|
|
3687
3726
|
r = CATimeUnitAlgebra.ratio(day, res) # storage ticks per day
|
|
3688
3727
|
if r.denominator == 1
|
|
3689
|
-
|
|
3728
|
+
face_storage / r.numerator
|
|
3690
3729
|
else # non-day-aligned tick
|
|
3691
3730
|
tr = res.tick_ratio # seconds / tick
|
|
3692
|
-
|
|
3731
|
+
face_storage * tr.numerator / (86400 * tr.denominator)
|
|
3693
3732
|
end
|
|
3694
3733
|
end
|
|
3695
3734
|
end
|
|
@@ -3702,9 +3741,9 @@ class CATime
|
|
|
3702
3741
|
# calendar-storage element has no intra-day field, so it collapses to 0.
|
|
3703
3742
|
def clock_field(fu)
|
|
3704
3743
|
r = CATimeUnitAlgebra.ratio(unit, CATime::Resolution.new(1, fu)) # fu ticks / storage tick
|
|
3705
|
-
return
|
|
3706
|
-
fi = r.denominator == 1 ?
|
|
3707
|
-
:
|
|
3744
|
+
return face_storage * 0 if r.nil? # calendar storage: no clock field
|
|
3745
|
+
fi = r.denominator == 1 ? face_storage * r.numerator # epoch-relative fu index
|
|
3746
|
+
: face_storage * r.numerator / r.denominator
|
|
3708
3747
|
cycle = fu == :h ? 24 : 60 # hour 0..23; min/sec 0..59
|
|
3709
3748
|
fi % cycle
|
|
3710
3749
|
end
|
|
@@ -3725,12 +3764,12 @@ class CATime
|
|
|
3725
3764
|
return k if kind == :index
|
|
3726
3765
|
head = CATimeGrid.calendar_bucket_head_ticks(k, st, su, origin)
|
|
3727
3766
|
return head.time(unit: su) if kind == :floor
|
|
3728
|
-
return
|
|
3767
|
+
return face_storage.eq(head) if kind == :on
|
|
3729
3768
|
head_next = CATimeGrid.calendar_bucket_head_ticks(k + 1, st, su, origin)
|
|
3730
3769
|
sel = # boolean 0/1: pick head_next?
|
|
3731
3770
|
case kind
|
|
3732
|
-
when :ceil then
|
|
3733
|
-
when :round then (head_next -
|
|
3771
|
+
when :ceil then face_storage.ne(head) # on-boundary keeps head
|
|
3772
|
+
when :round then (head_next - face_storage).le(face_storage - head) # nearest, ties -> future
|
|
3734
3773
|
end
|
|
3735
3774
|
(head + (head_next - head) * sel).time(unit: su)
|
|
3736
3775
|
end
|
|
@@ -23,14 +23,15 @@ class CArray
|
|
|
23
23
|
# @return [CATranspose]
|
|
24
24
|
# @overload transpose(*imap)
|
|
25
25
|
# Returns a {CATranspose} view of `self` permuted by `imap`, a
|
|
26
|
-
# permutation of `0 ... self.ndim
|
|
27
|
-
# `view[i_0, ..., i_{n-1}]` aliases parent element with
|
|
28
|
-
# sourced from `i` at position `imap[k]`.
|
|
26
|
+
# permutation of `0 ... self.ndim`; a negative axis counts from the
|
|
27
|
+
# end. Element `view[i_0, ..., i_{n-1}]` aliases parent element with
|
|
28
|
+
# axis `k` sourced from `i` at position `imap[k]`.
|
|
29
29
|
# @param imap [Array<Integer>] permutation of `0 ... ndim`.
|
|
30
30
|
# @return [CATranspose]
|
|
31
31
|
# @raise [ArgumentError] when `imap.length != ndim`.
|
|
32
32
|
# @raise [ArgumentError] when an entry of `imap` is out of range
|
|
33
|
-
# or
|
|
33
|
+
# or names an axis given before.
|
|
34
|
+
# @raise [TypeError] when an entry of `imap` is not an Integer.
|
|
34
35
|
def transpose(*imap); end
|
|
35
36
|
|
|
36
37
|
# Alias of {#transpose}.
|
|
@@ -103,7 +103,9 @@ class CArray
|
|
|
103
103
|
|
|
104
104
|
# @overload parent
|
|
105
105
|
# Returns the parent CArray of `self`, or `nil` if `self` has no
|
|
106
|
-
# parent (i.e. is an entity).
|
|
106
|
+
# parent (i.e. is an entity). For a Face (CATime, CARecord, ...) it
|
|
107
|
+
# is a read-only view of the storage; a Face whose storage may be
|
|
108
|
+
# written names a method for it (`CATime#ticks`).
|
|
107
109
|
# @return [CArray, nil]
|
|
108
110
|
def parent; end
|
|
109
111
|
|
data/yard-stubs/carray_cast.rb
CHANGED
|
@@ -472,6 +472,8 @@ class CArray
|
|
|
472
472
|
#
|
|
473
473
|
# - CArray instance -> its `data_type`
|
|
474
474
|
# - Symbol / String / Class -> data_type representation (name lookup)
|
|
475
|
+
# - MemoryView producer -> the data_type its format names; one whose
|
|
476
|
+
# format carray cannot read is refused, as an operator refuses it
|
|
475
477
|
# - Integer / Float / Complex / true / false / nil / Object -> *value*,
|
|
476
478
|
# data_type inferred (3 -> `:int64`, 3.14 -> `:float64`,
|
|
477
479
|
# 1+2i -> `:cmplx128`, ...)
|
|
@@ -63,7 +63,11 @@ class CArray
|
|
|
63
63
|
|
|
64
64
|
# @overload to_s
|
|
65
65
|
# Equivalent to `dump_binary` with no arguments. Returns the raw
|
|
66
|
-
# element bytes of `self` as a binary String.
|
|
66
|
+
# element bytes of `self` as a binary String. Ruby uses `to_s` where
|
|
67
|
+
# it puts an object into text, so such text holds the bytes: a
|
|
68
|
+
# `Ractor.make_shareable` refusal of a view, for one, raises
|
|
69
|
+
# `ArgumentError: string contains null byte` in place of its own
|
|
70
|
+
# message. Use `inspect` for a readable form.
|
|
67
71
|
# @return [String]
|
|
68
72
|
def to_s; end
|
|
69
73
|
|
|
@@ -5,12 +5,13 @@
|
|
|
5
5
|
class CArray
|
|
6
6
|
# @!group Element access
|
|
7
7
|
#
|
|
8
|
-
# `elem_*` methods are
|
|
9
|
-
# accept `idx` as
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
#
|
|
8
|
+
# `elem_*` methods are the fastest way to reach one cell when you
|
|
9
|
+
# hold its per-axis index. They accept `idx` as an `Array<Integer>`
|
|
10
|
+
# (one index per axis) or an Integer (flat address into the
|
|
11
|
+
# row-major element sequence). An index is read as `[]` reads one:
|
|
12
|
+
# an Integer, or a Float with no fraction. The result is the same as `[]` /
|
|
13
|
+
# `[]=` for that cell; the key parsing and view construction of
|
|
14
|
+
# the general indexer are skipped.
|
|
14
15
|
|
|
15
16
|
# @overload elem_swap(idx1, idx2)
|
|
16
17
|
# Exchanges the values (and mask states, if any) at positions
|
data/yard-stubs/carray_mask.rb
CHANGED
|
@@ -30,6 +30,10 @@ class CArray
|
|
|
30
30
|
# Nothing in a value array is masked, so `unmask` on it does nothing,
|
|
31
31
|
# while a write that would mask a cell (`UNDEF`, `mask=`,
|
|
32
32
|
# `invert_mask`) raises TypeError.
|
|
33
|
+
#
|
|
34
|
+
# On a Face the data slot is read through the Face. A {CACategorical}
|
|
35
|
+
# cell excluded by the sentinel code has no label, so its value reads
|
|
36
|
+
# as `nil` (the codes are in `codes`).
|
|
33
37
|
# @return [CArray]
|
|
34
38
|
def value; end
|
|
35
39
|
|
|
@@ -180,10 +184,11 @@ class CArray
|
|
|
180
184
|
# of `self` and the masks of each array in `others`. Mutates
|
|
181
185
|
# `self`.
|
|
182
186
|
# @param others [Array<CArray>] arrays whose mask states are
|
|
183
|
-
# OR-ed into `self`.
|
|
187
|
+
# OR-ed into `self`.
|
|
184
188
|
# @return [self]
|
|
185
189
|
# @raise [ArgumentError] if an array in `others` other than a scalar
|
|
186
|
-
# has
|
|
190
|
+
# has a different number of elements from `self`.
|
|
191
|
+
# @raise [TypeError] if an argument is not a CArray.
|
|
187
192
|
def inherit_mask(*others); end
|
|
188
193
|
|
|
189
194
|
# @overload inherit_mask_replace(*others)
|
|
@@ -194,7 +199,7 @@ class CArray
|
|
|
194
199
|
# new mask of `self`.
|
|
195
200
|
# @return [self]
|
|
196
201
|
# @raise [ArgumentError] if an array in `others` other than a scalar
|
|
197
|
-
# has
|
|
202
|
+
# has a different number of elements from `self`.
|
|
198
203
|
def inherit_mask_replace(*others); end
|
|
199
204
|
|
|
200
205
|
# @overload count_masked
|