From da7be641bac16dbe5575c0f266a10d1819ab0026 Mon Sep 17 00:00:00 2001 From: Piotr Gregor Date: Fri, 11 Mar 2016 19:27:21 +0000 Subject: [PATCH] FS-8853 enable change of resolution of fast arc cos table It is possible now to apply lower resolution to mapping of float-integer-float and decrease size of mapped file. --- src/mod/applications/mod_avmd/fast_acosf.c | 199 ++++++++++++++++++--- 1 file changed, 172 insertions(+), 27 deletions(-) diff --git a/src/mod/applications/mod_avmd/fast_acosf.c b/src/mod/applications/mod_avmd/fast_acosf.c index 6c990d2520..9710c6abc2 100644 --- a/src/mod/applications/mod_avmd/fast_acosf.c +++ b/src/mod/applications/mod_avmd/fast_acosf.c @@ -20,41 +20,71 @@ #ifdef FASTMATH -#define SIGN_MASK (0x80000000) -#define DATA_MASK (0x07FFFFF8) - -#define SIGN_UNPACK_MASK (0x01000000) -#define DATA_UNPACK_MASK (0x00FFFFFF) - -#define VARIA_DATA_MASK (0x87FFFFF8) -#define CONST_DATA_MASK (0x38000000) - -#define ACOS_TABLE_LENGTH (1 << 25) -#define ACOS_TABLE_FILENAME "/tmp/acos_table.dat" typedef union { uint32_t i; float f; } float_conv_t; -#ifdef FAST_ACOSF_TESTING -static float strip_float(float f); -#endif +/* + * Manipulate these parameters to change + * mapping's resolution. The sine tone + * of 1600Hz is detected even with 20 + * bits discarded in float integer representation + * with only slightly increased amount of false + * positives (keeping variance threshold on 0.0001). + * 12 bits seem to be good choice when there is + * a need to compute faster and/or decrease mapped file + * size on disk while keeping false positives low. + */ +#define ACOS_TABLE_CONST_EXPONENT (0x70) +#define ACOS_TABLE_CONST_EXPONENT_BITS (3) +#define ACOS_TABLE_DISCARDED_BITS (3) +/* rosolution: + 3: 15 728 640 indices spreading range [0.0, 1.0], table size on disk 134 217 728 bytes (default) + 4: 7 364 320 indices spreading range [0.0, 1.0], table size on disk 67 108 864 bytes + 5: 3 932 160 indices spreading range [0.0, 1.0], table size on disk 33 554 432 bytes + 12: 30 720 indices spreading range [0.0, 1.0], table size on disk 262 144 bytes + 16: 1 920 indices spreading range [0.0, 1.0], table size on disk 16 384 bytes + 20: 120 indices spreading range [0.0, 1.0], table size on disk 1 024 bytes + 24: 7 indices spreading range [0.0, 1.0], table size on disk 64 bytes + 26: 1 indices spreading range [0.0, 1.0], table size on disk 16 bytes +*/ +#define ACOS_TABLE_FREE_EXPONENT_BITS (7 - ACOS_TABLE_CONST_EXPONENT_BITS) +#define ACOS_TABLE_DATA_BITS (31 - ACOS_TABLE_CONST_EXPONENT_BITS - ACOS_TABLE_DISCARDED_BITS) +#define ACOS_TABLE_LENGTH (1 << (31 - ACOS_TABLE_CONST_EXPONENT_BITS - ACOS_TABLE_DISCARDED_BITS)) + +#define VARIA_DATA_MASK (0x87FFFFFF & ~((1 << ACOS_TABLE_DISCARDED_BITS) - 1)) +#define CONST_DATA_MASK (((1 << ACOS_TABLE_CONST_EXPONENT_BITS) - 1) \ + << (ACOS_TABLE_DATA_BITS - 1 + ACOS_TABLE_DISCARDED_BITS)) + +#define SIGN_UNPACK_MASK (1 << (ACOS_TABLE_DATA_BITS - 1)) +#define DATA_UNPACK_MASK ((1 << (ACOS_TABLE_DATA_BITS - 1)) - 1) + +#define SIGN_MASK (0x80000000) +#define DATA_MASK (DATA_UNPACK_MASK << ACOS_TABLE_DISCARDED_BITS) + +#define ACOS_TABLE_FILENAME "/tmp/acos_table.dat" + static uint32_t index_from_float(float f); static float float_from_index(uint32_t d); static float *acos_table = NULL; static int acos_fd = -1; + #ifdef FAST_ACOSF_TESTING -static float strip_float(float f) -{ - float_conv_t d; - d.i = d.i & (VARIA_DATA_MASK | CONST_DATA_MASK); +#define INF(x) printf("[%s] [%u]\n", #x, x) +#define INFX(x) printf("[%s] [%08x]\n", #x, x) + +static void +debug_print(void); + +static void +dump_table_summary(void); + +#endif /* FAST_ACOSF_TESTING */ - return d.i; -} -#endif extern void compute_table(void) { @@ -114,23 +144,138 @@ extern float fast_acosf(float x) return acos_table[index_from_float(x)]; } - static uint32_t index_from_float(float f) { float_conv_t d; - d.f = f; - return ((d.i & SIGN_MASK) >> 7) | ((d.i & DATA_MASK) >> 3); + return ((d.i & SIGN_MASK) >> (32 - ACOS_TABLE_DATA_BITS)) | + ((d.i & DATA_MASK) >> ACOS_TABLE_DISCARDED_BITS); } - static float float_from_index(uint32_t d) { float_conv_t f; - - f.i = ((d & SIGN_UNPACK_MASK) << 7) | ((d & DATA_UNPACK_MASK) << 3) | CONST_DATA_MASK; + f.i = ((d & SIGN_UNPACK_MASK) << (32 - ACOS_TABLE_DATA_BITS)) | + ((d & DATA_UNPACK_MASK) << ACOS_TABLE_DISCARDED_BITS) | CONST_DATA_MASK; return f.f; } +#ifdef FAST_ACOSF_TESTING + +#define INF(x) printf("[%s] [%u]\n", #x, x) +#define INFX(x) printf("[%s] [%08x]\n", #x, x) + +static void +debug_print(void) +{ + INF(ACOS_TABLE_CONST_EXPONENT); + INF(ACOS_TABLE_CONST_EXPONENT_BITS); + INF(ACOS_TABLE_FREE_EXPONENT_BITS); + INF(ACOS_TABLE_DISCARDED_BITS); + INF(ACOS_TABLE_DATA_BITS); + INF(ACOS_TABLE_LENGTH); + INFX(VARIA_DATA_MASK); + INFX(CONST_DATA_MASK); + INFX(SIGN_UNPACK_MASK); + INFX(DATA_UNPACK_MASK); + INFX(SIGN_MASK); + INFX(DATA_MASK); +} + +static void +dump_table_summary(void) +{ + uint32_t i, i_0, i_1, di; + float f; + + i = 1; + i_0 = index_from_float(0.0); + i_1 = index_from_float(1.0); + di = (i_1 - i_0)/100; + if (di == 0) di = 1; + + for (; i < ACOS_TABLE_LENGTH; i += di ) + { + f = float_from_index(i); + printf("-01i[%.10u] : ffi[%f] fa[%f] acos[%f]\n", + i, f, fast_acosf(f), acos(f)); + } + + i = 1; + for (; i < ACOS_TABLE_LENGTH; i = (i << 1)) + { + f = fast_acosf(float_from_index(i)); + printf("--i[%.10u] : fa[%f] ffi[%f]\n", + i, f, float_from_index(i)); + } + + f = 0.0; + printf("i [%d] from float [%f]\n", index_from_float(f), f); + f = 0.1; + printf("i [%d] from float [%f]\n", index_from_float(f), f); + f = 0.2; + printf("i [%d] from float [%f]\n", index_from_float(f), f); + f = 0.3; + printf("i [%d] from float [%f]\n", index_from_float(f), f); + f = 0.4; + printf("i [%d] from float [%f]\n", index_from_float(f), f); + f = 0.5; + printf("i [%d] from float [%f]\n", index_from_float(f), f); + f = 0.6; + printf("i [%d] from float [%f]\n", index_from_float(f), f); + f = 0.7; + printf("i [%d] from float [%f]\n", index_from_float(f), f); + f = 7.5; + printf("i [%d] from float [%f]\n", index_from_float(f), f); + f = 0.8; + printf("i [%d] from float [%f]\n", index_from_float(f), f); + f = 0.9; + printf("i [%d] from float [%f]\n", index_from_float(f), f); + f = 0.95; + printf("i [%d] from float [%f]\n", index_from_float(f), f); + f = 0.99; + printf("i [%d] from float [%f]\n", index_from_float(f), f); + f = 1.0; + printf("i [%d] from float [%f]\n", index_from_float(f), f); + f = 1.1; + printf("i [%d] from float [%f]\n", index_from_float(f), f); + f = 1.2; + printf("i [%d] from float [%f]\n", index_from_float(f), f); + f = 0.0; + printf("i [%d] from float [%f]\n", index_from_float(f), f); + f = -0.1; + printf("i [%d] from float [%f]\n", index_from_float(f), f); + f = -0.2; + printf("i [%d] from float [%f]\n", index_from_float(f), f); + f = -0.3; + printf("i [%d] from float [%f]\n", index_from_float(f), f); + f = -0.4; + printf("i [%d] from float [%f]\n", index_from_float(f), f); + f = -0.5; + printf("i [%d] from float [%f]\n", index_from_float(f), f); + f = -0.6; + printf("i [%d] from float [%f]\n", index_from_float(f), f); + f = -0.7; + printf("i [%d] from float [%f]\n", index_from_float(f), f); + f = -7.5; + printf("i [%d] from float [%f]\n", index_from_float(f), f); + f = -0.8; + printf("i [%d] from float [%f]\n", index_from_float(f), f); + f = -0.9; + printf("i [%d] from float [%f]\n", index_from_float(f), f); + f = -0.95; + printf("i [%d] from float [%f]\n", index_from_float(f), f); + f = -0.99; + printf("i [%d] from float [%f]\n", index_from_float(f), f); + f = -1.0; + printf("i [%d] from float [%f]\n", index_from_float(f), f); + f = -1.1; + printf("i [%d] from float [%f]\n", index_from_float(f), f); + f = -1.2; + printf("i [%d] from float [%f]\n", index_from_float(f), f); +} + +#endif /* FAST_ACOSF_TESTING */ + #endif