diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2023-12-20 16:25:20 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2023-12-20 16:25:20 -0300 |
commit | ad0ea7813b39e76b377983138ca995189e22054f (patch) | |
tree | 087e3585a4b4bf5ae65f56b9599bbff9c361a123 /lobject.c | |
parent | 666e95a66d1a2ceb98bdf320980b3f655264a9c9 (diff) | |
download | lua-ad0ea7813b39e76b377983138ca995189e22054f.tar.gz lua-ad0ea7813b39e76b377983138ca995189e22054f.tar.bz2 lua-ad0ea7813b39e76b377983138ca995189e22054f.zip |
GC parameters encoded as floating-point bytes
This encoding brings more precision and a larger range for these
parameters.
Diffstat (limited to 'lobject.c')
-rw-r--r-- | lobject.c | 53 |
1 files changed, 52 insertions, 1 deletions
@@ -33,7 +33,7 @@ | |||
33 | ** Computes ceil(log2(x)) | 33 | ** Computes ceil(log2(x)) |
34 | */ | 34 | */ |
35 | int luaO_ceillog2 (unsigned int x) { | 35 | int luaO_ceillog2 (unsigned int x) { |
36 | static const lu_byte log_2[256] = { /* log_2[i] = ceil(log2(i - 1)) */ | 36 | static const lu_byte log_2[256] = { /* log_2[i - 1] = ceil(log2(i)) */ |
37 | 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, | 37 | 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, |
38 | 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, | 38 | 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, |
39 | 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, | 39 | 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, |
@@ -49,6 +49,57 @@ int luaO_ceillog2 (unsigned int x) { | |||
49 | return l + log_2[x]; | 49 | return l + log_2[x]; |
50 | } | 50 | } |
51 | 51 | ||
52 | /* | ||
53 | ** Encodes 'p'% as a floating-point byte, represented as (eeeeexxx). | ||
54 | ** The exponent is represented using excess-7. Mimicking IEEE 754, the | ||
55 | ** representation normalizes the number when possible, assuming an extra | ||
56 | ** 1 before the mantissa (xxx) and adding one to the exponent (eeeeexxx) | ||
57 | ** to signal that. So, the real value is (1xxx) * 2^(eeeee - 8) if | ||
58 | ** eeeee != 0, and (xxx) * 2^-7 otherwise. | ||
59 | */ | ||
60 | unsigned int luaO_codeparam (unsigned int p) { | ||
61 | if (p >= (cast(lu_mem, 0xF) << 0xF) / 128 * 100) /* overflow? */ | ||
62 | return 0xFF; /* return maximum value */ | ||
63 | else { | ||
64 | p = (p * 128u) / 100; | ||
65 | if (p <= 0xF) | ||
66 | return p; | ||
67 | else { | ||
68 | int log = luaO_ceillog2(p + 1) - 5; | ||
69 | return ((p >> log) - 0x10) | ((log + 1) << 4); | ||
70 | } | ||
71 | } | ||
72 | } | ||
73 | |||
74 | |||
75 | /* | ||
76 | ** Computes 'p' times 'x', where 'p' is a floating-point byte. | ||
77 | */ | ||
78 | l_obj luaO_applyparam (unsigned int p, l_obj x) { | ||
79 | unsigned int m = p & 0xF; /* mantissa */ | ||
80 | int e = (p >> 4); /* exponent */ | ||
81 | if (e > 0) { /* normalized? */ | ||
82 | e--; | ||
83 | m += 0x10; /* maximum 'm' is 0x1F */ | ||
84 | } | ||
85 | e -= 7; /* correct excess-7 */ | ||
86 | if (e < 0) { | ||
87 | e = -e; | ||
88 | if (x < MAX_LOBJ / 0x1F) /* multiplication cannot overflow? */ | ||
89 | return (x * m) >> e; /* multiplying first gives more precision */ | ||
90 | else if ((x >> e) < MAX_LOBJ / 0x1F) /* cannot overflow after shift? */ | ||
91 | return (x >> e) * m; | ||
92 | else /* real overflow */ | ||
93 | return MAX_LOBJ; | ||
94 | } | ||
95 | else { | ||
96 | if (x < (MAX_LOBJ / 0x1F) >> e) /* no overflow? */ | ||
97 | return (x * m) << e; /* order doesn't matter here */ | ||
98 | else /* real overflow */ | ||
99 | return MAX_LOBJ; | ||
100 | } | ||
101 | } | ||
102 | |||
52 | 103 | ||
53 | static lua_Integer intarith (lua_State *L, int op, lua_Integer v1, | 104 | static lua_Integer intarith (lua_State *L, int op, lua_Integer v1, |
54 | lua_Integer v2) { | 105 | lua_Integer v2) { |