aboutsummaryrefslogtreecommitdiffstats
path: root/core/module.c
diff options
context:
space:
mode:
authoreunhhu <[email protected]>2026-10-19 01:13:07 +0100
committereunhhu <[email protected]>2026-10-19 01:13:07 +0100
commitb79f627af433a63f8f42869b124f5ef344a49352 (patch)
tree02aebc9cb63ace5040e5467949f3bec91edabf36 /core/module.c
parent7e1b3dc160906abaecfd4fe49ab2a51a3e2bfda4 (diff)
downloadpure-b79f627af433a63f8f42869b124f5ef344a49352.tar.gz
pure-b79f627af433a63f8f42869b124f5ef344a49352.zip
027's stage 5 designed and 5a made: two numbers (number, binary64, the default of literals and of counts, positions, lengths and u32 fields, whole to 2^53 exactly; i64 the exact integers past it, bits and money, never mixed, moved by number() and i64() when exact), / a number's division, // the floored quotient, i64 folds exact (only the result in range, so in any order), number folds in order unless the batch executor's 2^53 test says any order is exact, money as i64 minor units shown by .Nd, a replace carrying number, bool and i64 when exact; 5a: opcode FLOORDIV (95, 96 now): a number's floored quotient as Python's float //, exactly (a less its floored remainder, divided, to the nearest whole; a zero signed as a / b; by zero divide), a new opcode so the JIT, the tier and the batch executor leave it to the executor; unit test floor_division (7 // 2, -7 // 2, 7 // -2, 1 // 0.1 = 9, 0 // -3 = -0, 1e300 // 7, by zero); counts: b43 against b42 within 0.001% but BFS without batches -0.09%; the bank's queries (s42 and s43 in turns, six each) -0.20% to 0.00%; 008 and 027
Diffstat (limited to 'core/module.c')
-rw-r--r--core/module.c16
1 files changed, 15 insertions, 1 deletions
diff --git a/core/module.c b/core/module.c
index 71a0a25..052528c 100644
--- a/core/module.c
+++ b/core/module.c
@@ -130,7 +130,7 @@ static const struct { unsigned char pops, in[3], out; unsigned short where; unsi
/* LOOP takes its low and high, two numbers or two i64s (the operands are its argument's). */
[PURE_OP_LOOP] = {0, {0}, 0, IN_HANDLER | IN_COMPUTE, A_LOOP, O_ANY},
[PURE_OP_BREAK] = {0, {0}, 0, IN_HANDLER | IN_COMPUTE, A_NONE, O_ANY},
- [PURE_OP_FLOOR] = NUMS(1), [PURE_OP_MOD] = NUMS(2),
+ [PURE_OP_FLOOR] = NUMS(1), [PURE_OP_MOD] = NUMS(2), [PURE_OP_FLOORDIV] = NUMS(2),
[PURE_OP_I64_ADD] = I64S(2), [PURE_OP_I64_SUB] = I64S(2), [PURE_OP_I64_MUL] = I64S(2), [PURE_OP_I64_DIV] = I64S(2),
[PURE_OP_I64_MOD] = I64S(2), [PURE_OP_I64_NEG] = I64S(1), [PURE_OP_I64_MIN] = I64S(2), [PURE_OP_I64_MAX] = I64S(2),
[PURE_OP_I64_COMPARE] = {2, {T_I64, T_I64}, T_BOOL, READ, A_RELATION, O_ANY},
@@ -1526,6 +1526,16 @@ static uint32_t nesting_of(const PureModule *m) {
return most;
}
+/* a // b for numbers as Python's float floor division: the quotient of a less its floored remainder, rounded to the
+ * nearest whole (it is one but for rounding), a zero with the sign of a / b (027's stage 5). b is not 0. */
+static double floor_divide(double a, double b) {
+ double mod = fmod(a, b), quotient = (a - mod) / b;
+ if (mod != 0 && (b < 0) != (mod < 0)) quotient -= 1.0;
+ if (quotient == 0) return copysign(0.0, a / b);
+ double whole = floor(quotient);
+ return quotient - whole > 0.5 ? whole + 1.0 : whole;
+}
+
/* A name and its place among those of one namespace, in order of name and then of place. */
typedef struct { const char *name; size_t index; } Named;
static int by_name(const void *a, const void *b) {
@@ -4510,6 +4520,10 @@ static inline __attribute__((always_inline)) int step(Frame *frame, const PureOp
if (value != 0 && (value < 0) != (b < 0)) value += b;
else if (value == 0) value = copysign(0.0, b);
break;
+ case PURE_OP_FLOORDIV: /* MOD's quotient, exactly (027's stage 5): a less its remainder, divided, as Python's // */
+ if (b == 0) { kind = PURE_FAULT_DIVIDE; FAILED; }
+ value = floor_divide(a, b);
+ break;
default: value = maximum(a, b); break;
}
if (!isfinite(value)) { kind = PURE_FAULT_NON_FINITE; FAILED; }