aboutsummaryrefslogtreecommitdiffstats
path: root/core/module.c
diff options
context:
space:
mode:
authoreunhhu <[email protected]>2026-10-19 01:53:40 +0100
committereunhhu <[email protected]>2026-10-19 01:53:40 +0100
commitdefb2cf06a9b5db9429ca368d8c2af127a5c9c3d (patch)
treeb13c94eb334ce2a5055854791900f8702ba9fc3b /core/module.c
parent809a83a5764ec0f0c84b96c43a20cfb906eee031 (diff)
downloadpure-defb2cf06a9b5db9429ca368d8c2af127a5c9c3d.tar.gz
pure-defb2cf06a9b5db9429ca368d8c2af127a5c9c3d.zip
027's 5c: money as i64 minor units shown by .Nd: NUM_TEXT's decimal form takes digits (bits 20-24 as FIXED's), an integer's last N digits written after a point (1234 at two is 12.34, -5 -0.05, 0 0.00; width and zeros after the sign), verification allowing digits on FIXED and DECIMAL alone; unit test: ten rows of formats_and_held (-2^63 at two, 25 digits, a number's whole 1234, its 12.5 a limit); TPC-C's money i64 cents and its rates ten-thousandths (tables, messages, load, the transactions), SQLite's INTEGER columns and int64 bindings alike, the comparison now exact (no 1e-9 tolerance): after 20,000 transactions every row of every table the same (grouped SQLite too) and 3.3.2 holding on both; counts: b45 against b44 BFS without batches +0.09%, the rest within 0.001%; the bank's queries (s44 and s45 in turns, six each) in_credit -0.59%, per_branch -0.34%, ranks -0.20%, the rest within 0.01%, the seven answers the same bytes; 008 (NUM_TEXT's digits, a message row's i64 cells), 027 and 092
Diffstat (limited to 'core/module.c')
-rw-r--r--core/module.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/core/module.c b/core/module.c
index ca5b0e2..3657843 100644
--- a/core/module.c
+++ b/core/module.c
@@ -453,10 +453,10 @@ PURE_COLD static bool names_arg(const PureModule *m, unsigned kind, uint32_t arg
case A_POSITION: case A_JOINED: return arg <= 1;
case A_HELD: return (arg & ~(uint32_t)PURE_HELD_APPEND) < PURE_MODULE_HELD;
case A_FUNCTION: return arg < m->functions;
- case A_FORMAT: { /* a type; a width, zeros, a form fitting it and digits for FIXED alone */
+ case A_FORMAT: { /* a type; a width, zeros, a form fitting it and digits for FIXED and DECIMAL alone */
uint32_t type = arg & 3, form = arg >> PURE_FORMAT_FORM & 7, digits = arg >> PURE_FORMAT_DIGITS & 31;
return type <= 2 && !(arg & 0xFC) && !(arg >> 25) && form <= PURE_FORMAT_FIXED && (type != 1 || !form) &&
- (form != PURE_FORMAT_FIXED || type == 0) && (form == PURE_FORMAT_FIXED || !digits);
+ (form != PURE_FORMAT_FIXED || type == 0) && (form == PURE_FORMAT_FIXED || form == PURE_FORMAT_DECIMAL || !digits);
}
case A_RELATION: return arg <= PURE_NOT_EQUAL;
case A_KEYED: return state_of(m, arg, PURE_STATE_LIST) && m->state_key[arg];
@@ -2942,7 +2942,8 @@ static __attribute__((cold, noinline)) int kept_step(PureApp *app, PureArena *ar
}
/* NUM_TEXT's text of v in a format (the argument past its type, PureFormat): false where an integer's form meets a
- * number that is not a whole one within 2^53. */
+ * number that is not a whole one within 2^53. DECIMAL with digits writes the integer in minor units: its last
+ * digits after a point (money's cents: 1234 at two is 12.34, -5 is -0.05). */
static bool formatted(Slot v, uint32_t arg, char *out, size_t *length) {
unsigned type = arg & 3, width = arg >> PURE_FORMAT_WIDTH & 0xFF, form = arg >> PURE_FORMAT_FORM & 7,
digits = arg >> PURE_FORMAT_DIGITS & 31;
@@ -2960,10 +2961,14 @@ static bool formatted(Slot v, uint32_t arg, char *out, size_t *length) {
unsigned base = form == PURE_FORMAT_DECIMAL ? 10 : form <= PURE_FORMAT_HEX_UPPER ? 16 : form == PURE_FORMAT_BINARY ? 2 : 8;
const char *set = form == PURE_FORMAT_HEX_UPPER ? "0123456789ABCDEF" : "0123456789abcdef";
char reversed[64];
- unsigned count = 0;
+ unsigned count = 0, places = form == PURE_FORMAT_DECIMAL && digits ? digits - 1 : 0;
do reversed[count++] = set[magnitude % base], magnitude /= base; while (magnitude);
+ while (count <= places) reversed[count++] = '0'; /* a digit before the point */
if (i < 0) body[n++] = '-';
- while (count) body[n++] = reversed[--count];
+ for (; count; --count) {
+ if (count == places) body[n++] = '.';
+ body[n++] = reversed[count - 1];
+ }
} else
n = type == 2 ? (size_t)snprintf(body, sizeof(body), "%" PRId64, v.i64)
: type ? (size_t)snprintf(body, sizeof(body), "%s", v.num ? "true" : "false") : pure_format_number(v.num, body);