diff options
| author | eunhhu <[email protected]> | 2026-10-19 01:31:39 +0100 |
|---|---|---|
| committer | eunhhu <[email protected]> | 2026-10-19 01:31:39 +0100 |
| commit | 809a83a5764ec0f0c84b96c43a20cfb906eee031 (patch) | |
| tree | fe255be70914400060d810ec9ecd68c0edf1305e /core/module.c | |
| parent | b79f627af433a63f8f42869b124f5ef344a49352 (diff) | |
| download | pure-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.c | 21 |
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; |
