aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreunhhu <[email protected]>2026-10-08 15:57:16 +0100
committereunhhu <[email protected]>2026-10-08 15:57:16 +0100
commitd371271c3fcf8ac527f2061ece9ba38f3e009e3e (patch)
tree071e7a9a05c05cce585873064f50d3fe7292b482
parent6828a7d07f9de815c858a295124f6bcde9bd861a (diff)
downloadpure-d371271c3fcf8ac527f2061ece9ba38f3e009e3e.tar.gz
pure-d371271c3fcf8ac527f2061ece9ba38f3e009e3e.zip
Batch executor, stage 3 of design 025: four-byte MUL (words_op): a product below 2^32 of whole numbers below it in four-byte lanes, past it the product's high half sends the lanes back to numbers as ADD's sum does (umull and umull2 over four lanes); matmul's products and sums stay in four bytes; seeds 1 2 3 5 23 (default and PURE_SELECT=all), the fixed sources and the unit tests pass
-rw-r--r--core/module-batch.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/core/module-batch.c b/core/module-batch.c
index 5766818..68941dc 100644
--- a/core/module-batch.c
+++ b/core/module-batch.c
@@ -410,6 +410,11 @@ static bool words_op(uint8_t op, uint32_t *restrict out, const uint32_t *restric
else if (uy) for (unsigned l = 0; l < n; ++l) over |= xs[l] < yk;
else for (unsigned l = 0; l < n; ++l) over |= xs[l] < ys[l];
break;
+ case PURE_OP_MUL: /* past 2^32: the product's high half */
+ if (ux) for (unsigned l = 0; l < n; ++l) { uint64_t p = (uint64_t)xk * ys[l]; out[l] = (uint32_t)p, over |= (uint32_t)(p >> 32); }
+ else if (uy) for (unsigned l = 0; l < n; ++l) { uint64_t p = (uint64_t)xs[l] * yk; out[l] = (uint32_t)p, over |= (uint32_t)(p >> 32); }
+ else for (unsigned l = 0; l < n; ++l) { uint64_t p = (uint64_t)xs[l] * ys[l]; out[l] = (uint32_t)p, over |= (uint32_t)(p >> 32); }
+ break;
case PURE_OP_MIN: EACH(uint32_t, a < c ? a : c); break;
case PURE_OP_MAX: EACH(uint32_t, a > c ? a : c); break;
case PURE_OP_LT: EACH(uint32_t, a < c); break;
@@ -488,7 +493,7 @@ static void numbers_test(uint8_t op, uint32_t *restrict out, const double *restr
static bool word_form(uint8_t op) {
switch (op) {
- case PURE_OP_ADD: case PURE_OP_SUB: case PURE_OP_MIN: case PURE_OP_MAX: case PURE_OP_LT: case PURE_OP_LE:
+ case PURE_OP_ADD: case PURE_OP_SUB: case PURE_OP_MUL: case PURE_OP_MIN: case PURE_OP_MAX: case PURE_OP_LT: case PURE_OP_LE:
case PURE_OP_GT: case PURE_OP_GE: case PURE_OP_EQ: case PURE_OP_NE: case PURE_OP_AND: case PURE_OP_OR: return true;
default: return false;
}