Skip to content
This repository was archived by the owner on Aug 5, 2022. It is now read-only.

Commit 870d928

Browse files
grgustafJimmy Huang
authored andcommitted
[util] Add functions to pack 32-bit ints into 16 bits - magic! (#428)
The idea is to scale back accuracy as the number gets large, with the thought that this could be used for something like timer interval where a few seconds probably don't matter when you're waiting an hour. Comes with free unit tests that prove it actually works! Signed-off-by: Geoff Gustafson <geoff@linux.intel.com>
1 parent 3254c5c commit 870d928

File tree

3 files changed

+71
-0
lines changed

3 files changed

+71
-0
lines changed

src/zjs_unit_tests.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,42 @@ static void test_default_convert_pin()
5656
zjs_assert(dev == 0 && pin == -1, "convert pin failure case");
5757
}
5858

59+
// Test zjs_util int compression functions
60+
61+
static int check_compress_reversible(uint32_t num)
62+
{
63+
// checks whether uncompressing compressed value returns exact match
64+
uint32_t reversed = zjs_uncompress_16_to_32(zjs_compress_32_to_16(num));
65+
return num == reversed;
66+
}
67+
68+
static int check_compress_close(uint32_t num)
69+
{
70+
// checks whether uncompressing compressed value is within 0.05% of original
71+
// 11-bit mantissa means 1/2048 ~= 0.05%
72+
uint32_t reversed = zjs_uncompress_16_to_32(zjs_compress_32_to_16(num));
73+
double ratio = reversed * 1.0 / num;
74+
return ratio >= 0.9995 && ratio <= 1.0005;
75+
}
76+
77+
static void test_compress_32()
78+
{
79+
// expect these to be returned exactly
80+
zjs_assert(check_compress_reversible(0), "compression of 0");
81+
zjs_assert(check_compress_reversible(0x0cab), "compression of 0x0cab");
82+
zjs_assert(check_compress_reversible(0x7fff), "compression of 0x7fff");
83+
84+
// these should be close
85+
zjs_assert(check_compress_close(0x8000), "compression of 0x8000");
86+
zjs_assert(check_compress_close(0xdeadbeef), "compression of 0xdeadbeef");
87+
zjs_assert(check_compress_close(0xffffffff), "compression of 0xffffffff");
88+
}
89+
5990
void zjs_run_unit_tests()
6091
{
6192
test_hex_to_byte();
6293
test_default_convert_pin();
94+
test_compress_32();
6395

6496
printf("TOTAL - %d of %d passed\n", passed, total);
6597
exit(!(passed == total));

src/zjs_util.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,42 @@ void zjs_default_convert_pin(uint32_t orig, int *dev, int *pin) {
204204
}
205205
}
206206

207+
// when accuracy isn't as important as space
208+
uint16_t zjs_compress_32_to_16(uint32_t num)
209+
{
210+
int zeroes = __builtin_clzl(num);
211+
if (sizeof(unsigned long) > 4) {
212+
zeroes -= (sizeof(unsigned long) - 4) * 8;
213+
}
214+
215+
if (zeroes >= 17)
216+
return (uint16_t)num;
217+
218+
// take the top 16 bits
219+
uint16_t compressed = (num << zeroes) >> 16;
220+
221+
// clear the bottom five bits to save leading zeroes
222+
compressed &= 0xffe0;
223+
224+
// save the number of zeroes in bottom five bits
225+
return compressed | (uint16_t)zeroes;
226+
}
227+
228+
uint32_t zjs_uncompress_16_to_32(uint16_t num)
229+
{
230+
if ((num & 0x8000) == 0)
231+
return (uint32_t)num;
232+
233+
// take top 11 bits
234+
uint32_t uncompressed = (num & 0xffe0) >> 5;
235+
236+
// recover the number of leading zeroes
237+
int zeroes = num & 0x1f;
238+
239+
// shift back up to the right point
240+
return uncompressed << (21 - zeroes);
241+
}
242+
207243
jerry_value_t zjs_error(const char *error)
208244
{
209245
ZJS_PRINT("%s\n", error);

src/zjs_util.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ bool zjs_hex_to_byte(char *buf, uint8_t *byte);
6161

6262
void zjs_default_convert_pin(uint32_t orig, int *dev, int *pin);
6363

64+
uint16_t zjs_compress_32_to_16(uint32_t num);
65+
uint32_t zjs_uncompress_16_to_32(uint16_t num);
66+
6467
jerry_value_t zjs_error(const char *error);
6568

6669
#endif // __zjs_util_h__

0 commit comments

Comments
 (0)