aboutsummaryrefslogtreecommitdiffstats
path: root/core/module.c
diff options
context:
space:
mode:
authoreunhhu <[email protected]>2026-10-19 01:31:39 +0100
committereunhhu <[email protected]>2026-10-19 01:31:39 +0100
commit809a83a5764ec0f0c84b96c43a20cfb906eee031 (patch)
treefe255be70914400060d810ec9ecd68c0edf1305e /core/module.c
parentb79f627af433a63f8f42869b124f5ef344a49352 (diff)
downloadpure-809a83a5764ec0f0c84b96c43a20cfb906eee031.tar.gz
pure-809a83a5764ec0f0c84b96c43a20cfb906eee031.zip
027's 5b: an i64 sum exact: its items gathered in a 128-bit integer and only the result checked against the range (overflow past it), so a sum past the range midway and back in it at the end is the answer and an i64 sum's order is none of its business; the batch executor's folds are numbers' lanes alone, summed in the items' order, as before; 008's FOLD says so; counts: b44 against b43 within 0.04% (BFS without batches -0.03%); the bank's queries (s43 and s44 in turns, six each) per_branch -1.32% (all six below s43's lowest: a larger Fold lays the number sum's loop otherwise), in_credit -0.72%, ranks -0.26%, the rest within 0.01%, the seven queries' answers the same bytes on both; 008 and 027
Diffstat (limited to 'core/module.c')
-rw-r--r--core/module.c21
1 files changed, 12 insertions, 9 deletions
diff --git a/core/module.c b/core/module.c
index 052528c..ca5b0e2 100644
--- a/core/module.c
+++ b/core/module.c
@@ -3283,9 +3283,11 @@ static bool run_lanes(const PureModule *m, const PureValue *values, PureBlock bl
typedef struct { uint64_t *keys; size_t capacity, count; bool marked; } Seen;
/* A fold's running value: what count, sum, max, min, first or distinct has
- * so far, over numbers (total) or i64s (whole; a sum past the range
- * overflows and ends the fold). */
-typedef struct { unsigned how; bool integer, overflow; double total; int64_t whole; bool any, done; Seen seen; } Fold;
+ * so far, over numbers (total) or i64s (whole; an i64 sum exactly, in sum:
+ * only the result past the range overflows, so its items' order is none of
+ * its business: 027's stage 5). */
+__extension__ typedef __int128 Wide;
+typedef struct { unsigned how; bool integer; double total; int64_t whole; Wide sum; bool any, done; Seen seen; } Fold;
static size_t seen_slot(uint64_t bits, size_t capacity) {
bits ^= bits >> 33, bits *= 0xff51afd7ed558ccdu, bits ^= bits >> 33;
@@ -3353,8 +3355,7 @@ static bool fold_number(Fold *fold, size_t row, double value, double counts) {
return true;
}
-/* One item run as written: a number's, or an i64's (a sum past the range
- * overflows and ends the fold; count and first take no i64). */
+/* One item run as written: a number's, or an i64's (count and first take no i64). */
static bool fold_in(Fold *fold, size_t row, PureValue value, double counts) {
if (!fold->integer) return fold_number(fold, row, value.num, counts);
if (counts == 0) return true;
@@ -3365,9 +3366,8 @@ static bool fold_in(Fold *fold, size_t row, PureValue value, double counts) {
fold->any = true;
return !full;
}
- if (fold->how == PURE_FOLD_SUM) {
- if (__builtin_add_overflow(fold->whole, v, &fold->whole)) fold->overflow = fold->done = true;
- } else if (!fold->any || (fold->how == PURE_FOLD_MAX ? v > fold->whole : v < fold->whole))
+ if (fold->how == PURE_FOLD_SUM) fold->sum += v; /* (a Wide holds 2^64 items' worth) */
+ else if (!fold->any || (fold->how == PURE_FOLD_MAX ? v > fold->whole : v < fold->whole))
fold->whole = v;
fold->any = true;
return true;
@@ -4202,7 +4202,10 @@ static inline __attribute__((always_inline)) int step(Frame *frame, const PureOp
free(fold.seen.keys);
if (status != PURE_OK) STOPPED(status);
}
- if (fold.overflow) { kind = PURE_FAULT_OVERFLOW; FAILED; }
+ if (fold.integer && fold.how == PURE_FOLD_SUM) { /* the exact sum, if an i64 holds it */
+ if (fold.sum > INT64_MAX || fold.sum < INT64_MIN) { kind = PURE_FAULT_OVERFLOW; FAILED; }
+ fold.whole = (int64_t)fold.sum;
+ }
if (!fold.any && (fold.how == PURE_FOLD_MAX || fold.how == PURE_FOLD_MIN || fold.how == PURE_FOLD_FIRST)) {
kind = PURE_FAULT_NOT_FOUND;
FAILED;