MMgr v1.0.0
Zero-heap memory manager in C11. One borrowed buffer, carved by asserted offset.
Loading...
Searching...
No Matches
pow5.h
Go to the documentation of this file.
1/* MMgr - Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2 * SPDX-License-Identifier: AGPL-3.0-or-later OR LicenseRef-Commercial OR LicenseRef-Educational
3 *
4 * Every use falls under AGPL-3.0-or-later unless you hold explicit permission, which is either a
5 * negotiated commercial licensing contract or an educator's license issued to you personally.
6 */
7/**
8 * @file pow5.h
9 * @brief Powers of five as 128-bit significands, for scaling a decimal mantissa into a binary one.
10 * @author dstroy0 (Douglas Quigg) <dquigg123@gmail.com>
11 * @date 2026-08-29
12 *
13 * @note transformo walks the bits of the decimal exponent and multiplies in one entry per set bit, and so nine
14 * entries reach 511.
15 * @note Declares no function. Both tables are static const data that outlive every call. A pointer into
16 * one stays good for the whole program [BORROWS].
17 */
18#ifndef MMGR_POW5_H
19#define MMGR_POW5_H
20
21#include "mmgr.h"
22
23EMBED_BEGIN_DECLS
24
25/**
26 * @brief Expands to 9, the number of entries in each table.
27 *
28 * @note Entry i holds five raised to two to the i, and so the nine entries run from 5^1 to 5^256.
29 * @note Carries no suffix: it sizes both tables and bounds the walk, where it converts to the signed
30 * embed_iword the loop counts in.
31 */
32#define MMGR_POW5_STEPS 9
33
34/**
35 * @brief Expands to ((1 << 9) - 1), which is 511, the largest decimal exponent the tables reach.
36 *
37 * @note Every one of the nine entries multiplied together gives 5^511.
38 * @note The expansion is a plain int constant expression, which widens to the embed_iword an exponent is
39 * carried in wherever the two are compared.
40 * @warning muto_scale bounds against this and returns infinity above it and zero below its negative;
41 * muto_scale_to_u64 does not. What keeps either off the end of the tables is the walk itself,
42 * which takes only MMGR_POW5_STEPS steps. An exponent past this loses its higher bits.
43 */
44#define MMGR_POW5_MAX ((1 << MMGR_POW5_STEPS) - 1)
45
46/**
47 * @brief One power of five, as a 128-bit significand with a binary exponent.
48 *
49 * @note The value is (hi * 2^64 + lo) * 2^e2, and hi always has its top bit set.
50 */
51typedef struct
52{
53 embed_u64 hi; /**< High 64 bits of the significand, with its top bit set. */
54 embed_u64 lo; /**< Low 64 bits of the significand. */
55 embed_iword e2; /**< Binary exponent the significand is scaled by; -722 at the widest fits a 16-bit embed_iword. */
56} MmgrPow5;
57
58/**
59 * @brief Five raised to each power of two, from 5^1 at index 0 to 5^256 at index 8.
60 *
61 * @note Entry i is the multiplier for bit i of the exponent magnitude, and the walk in muto_apply_pow10
62 * takes this table over mmgr_pow5_down whenever the decimal exponent is not negative.
63 * @note Index 0 through 5 are exact. 5^64 and up need more than 128 bits, and so the last three entries are
64 * truncated toward zero and read a little low.
65 * @note Every significand literal carries ULL to match the embed_u64 it is stored in. Each e2 is a bare int
66 * that converts to embed_iword.
67 * @note static const at header scope, and each translation unit gets its own copy, EMBED_UNUSED keeps a unit
68 * that never reads it quiet, and an entry's address stays good for the whole program [BORROWS].
69 * @warning transformo settles a positive exponent from its exact powers of ten and returns before the walk,
70 * and the only exponent reaching this table there is zero, which sets no bit.
71 */
72static const MmgrPow5 mmgr_pow5_up[MMGR_POW5_STEPS] EMBED_UNUSED = {
73 {0xA000000000000000ULL, 0x0000000000000000ULL, -125}, {0xC800000000000000ULL, 0x0000000000000000ULL, -123},
74 {0x9C40000000000000ULL, 0x0000000000000000ULL, -118}, {0xBEBC200000000000ULL, 0x0000000000000000ULL, -109},
75 {0x8E1BC9BF04000000ULL, 0x0000000000000000ULL, -90}, {0x9DC5ADA82B70B59DULL, 0xF020000000000000ULL, -53},
76 {0xC2781F49FFCFA6D5ULL, 0x3CBF6B71C76B25FBULL, 21}, {0x93BA47C980E98CDFULL, 0xC66F336C36B10137ULL, 170},
77 {0xAA7EEBFB9DF9DE8DULL, 0xDDBB901B98FEEAB7ULL, 467},
78};
79
80/**
81 * @brief The reciprocal of each mmgr_pow5_up entry, from 5^-1 at index 0 to 5^-256 at index 8.
82 *
83 * @note Entry i is the multiplier for bit i of the exponent magnitude, and the walk in muto_apply_pow10
84 * takes this table when the decimal exponent is negative.
85 * @note No negative power of five ends in binary. All nine are the exact value truncated toward zero.
86 * Every entry reads a little low and none of them round up: 5^-1 is the repeating 0xCCCC..., not the
87 * 0xCCCD... that rounding to nearest would give.
88 * @note Every significand literal carries ULL to match the embed_u64 it is stored in. Each e2 is a bare int
89 * that converts to embed_iword.
90 * @note static const at header scope, and each translation unit gets its own copy, EMBED_UNUSED keeps a unit
91 * that never reads it quiet, and an entry's address stays good for the whole program [BORROWS].
92 */
93static const MmgrPow5 mmgr_pow5_down[MMGR_POW5_STEPS] EMBED_UNUSED = {
94 {0xCCCCCCCCCCCCCCCCULL, 0xCCCCCCCCCCCCCCCCULL, -130}, {0xA3D70A3D70A3D70AULL, 0x3D70A3D70A3D70A3ULL, -132},
95 {0xD1B71758E219652BULL, 0xD3C36113404EA4A8ULL, -137}, {0xABCC77118461CEFCULL, 0xFDC20D2B36BA7C3DULL, -146},
96 {0xE69594BEC44DE15BULL, 0x4C2EBE687989A9B3ULL, -165}, {0xCFB11EAD453994BAULL, 0x67DE18EDA5814AF2ULL, -202},
97 {0xA87FEA27A539E9A5ULL, 0x3F2398D747B36224ULL, -276}, {0xDDD0467C64BCE4A0ULL, 0xAC7CB3F6D05DDBDEULL, -425},
98 {0xC0314325637A1939ULL, 0xFA911155FEFB5308ULL, -722},
99};
100
101/**
102 * @brief Asserts MMGR_POW5_MAX is at least 511.
103 *
104 * @note A double's decimal exponent stays well inside 511, and so nine steps cover every value one can hold.
105 */
106EMBED_STATIC_ASSERT(MMGR_POW5_MAX >= 511, "the tables do not reach the exponents a double can carry");
107
108EMBED_END_DECLS
109
110#endif
The embedded_types headers every module builds on.
static const MmgrPow5 mmgr_pow5_down[MMGR_POW5_STEPS]
The reciprocal of each mmgr_pow5_up entry, from 5^-1 at index 0 to 5^-256 at index 8.
Definition pow5.h:93
static const MmgrPow5 mmgr_pow5_up[MMGR_POW5_STEPS]
Five raised to each power of two, from 5^1 at index 0 to 5^256 at index 8.
Definition pow5.h:72
#define MMGR_POW5_STEPS
Expands to 9, the number of entries in each table.
Definition pow5.h:32
#define MMGR_POW5_MAX
Expands to ((1 << 9) - 1), which is 511, the largest decimal exponent the tables reach.
Definition pow5.h:44
One power of five, as a 128-bit significand with a binary exponent.
Definition pow5.h:52
embed_u64 lo
Definition pow5.h:54
embed_u64 hi
Definition pow5.h:53
embed_iword e2
Definition pow5.h:55