diff --git a/src/include/sof/math/base2log.h b/src/include/sof/math/base2log.h deleted file mode 100644 index d73aba16338d..000000000000 --- a/src/include/sof/math/base2log.h +++ /dev/null @@ -1,17 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Copyright(c) 2021 Intel Corporation. All rights reserved. - * - * Author: Shriram Shastry - * - */ - -#ifndef __SOF_MATH_BASE_TWO_LOGARITHM_H__ -#define __SOF_MATH_BASE_TWO_LOGARITHM_H__ - -/* Include Files */ -#include -/* Function Declarations */ -int32_t base2_logarithm(uint32_t u); - -#endif diff --git a/src/include/sof/math/log.h b/src/include/sof/math/log.h new file mode 100644 index 000000000000..78ab8ce64c3c --- /dev/null +++ b/src/include/sof/math/log.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + * + * Author: Shriram Shastry + * + */ + +#ifndef __SOF_MATH_BASE_LOGARITHM_H__ +#define __SOF_MATH_BASE_LOGARITHM_H__ + +#include + +#define ONE_OVER_LOG2_10 2647887844335ULL /* 1/log2(10),Q1.43 */ +#define ONE_OVER_LOG2_E 6096987078286ULL /* 1/log2(exp(1)), Q1.43 */ +/* Function Declarations */ +int32_t base2_logarithm(uint32_t u); +uint32_t ln_int32(uint32_t numerator); +uint32_t log10_int32(uint32_t numerator); + +#endif diff --git a/src/math/CMakeLists.txt b/src/math/CMakeLists.txt index 943f6dfb8d9f..7fc00f65989f 100644 --- a/src/math/CMakeLists.txt +++ b/src/math/CMakeLists.txt @@ -18,6 +18,14 @@ if(CONFIG_MATH_DECIBELS) add_local_sources(sof decibels.c) endif() +if(CONFIG_NATURAL_LOGARITHM_FIXED) + add_local_sources(sof log_e.c) +endif() + +if(CONFIG_COMMON_LOGARITHM_FIXED) + add_local_sources(sof log_10.c) +endif() + if(CONFIG_POWER_FIXED) add_local_sources(sof power.c) endif() diff --git a/src/math/Kconfig b/src/math/Kconfig index f21c80bd7ae6..bb4689d55d02 100644 --- a/src/math/Kconfig +++ b/src/math/Kconfig @@ -38,6 +38,20 @@ config SQRT_FIXED to calculate square root.square function having positive number y as input and return the positive number x multiplied by itself (squared) +config NATURAL_LOGARITHM_FIXED + bool "Natural Logarithm function" + default n + help + This option builds Natural Logarithm function (loge(N)) which is the logarithm to + the base e. + +config COMMON_LOGARITHM_FIXED + bool "Common Logarithm function" + default n + help + This option builds common Logarithm function (log10(N)) which is the logarithm to + the base 10. + config NUMBERS_GCD bool "Greatest common divisor" default n diff --git a/src/math/base2log.c b/src/math/base2log.c index 3b6b73e581bb..5ca3967d9a85 100644 --- a/src/math/base2log.c +++ b/src/math/base2log.c @@ -6,8 +6,7 @@ // // -/* Include Files */ -#include +#include /* Defines Constant*/ #define BASE2LOG_WRAP_SCHAR_BITS 0xFF diff --git a/src/math/log_10.c b/src/math/log_10.c new file mode 100644 index 000000000000..61a885551883 --- /dev/null +++ b/src/math/log_10.c @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: BSD-3-Clause/ +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// Author: Shriram Shastry +// +// + +#include +#include +/** + * Base-10 logarithm log10(x) + * + * loge = (u) computes the base-10 logarithm of + * u using lookup table. + * input u must be scalar/real number and positive + * + * +------------------+-----------------+--------+--------+ + * | inpfxp |log10(returntype)| inpfxp | loge | + * +----+-----+-------+----+----+-------+--------+--------+ + * |WLen| FLen|Signbit|WLen|FLen|Signbit| Qformat| Qformat| + * +----+-----+-------+----+----+-------+--------+--------+ + * | 32 | 0 | 0 | 32 | 28 | 0 | 32.0 | 4.28 | + * +------------------+-----------------+--------+--------+ + * Arguments : uint32_t numerator [1 to 4294967295, Q32.0] + * Return Type : uint32_t UQ4.28 [0 to 9.6329499409] + */ +uint32_t log10_int32(uint32_t numerator) +{ + return((uint32_t)Q_SHIFT_RND((int64_t)base2_logarithm(numerator) * + ONE_OVER_LOG2_10, 63, 32)); +} diff --git a/src/math/log_e.c b/src/math/log_e.c new file mode 100644 index 000000000000..14d899265bb6 --- /dev/null +++ b/src/math/log_e.c @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// Author: Shriram Shastry +// +// + +#include +#include +/** + * Base-e logarithm loge(x) + * + * loge = (u) computes the base-e logarithm of + * u using lookup table. + * input u must be scalar/real number and positive + * + * +------------------+-----------------+--------+--------+ + * | inpfxp |loge (returntype)| inpfxp | loge | + * +----+-----+-------+----+----+-------+--------+--------+ + * |WLen| FLen|Signbit|WLen|FLen|Signbit| Qformat| Qformat| + * +----+-----+-------+----+----+-------+--------+--------+ + * | 32 | 0 | 0 | 32 | 27 | 0 | 32.0 | 5.27 | + * +------------------+-----------------+--------+--------+ + * + * Arguments : uint32_t numerator [1 to 4294967295- Q32.0] + * Return Type : uint32_t UQ5.27 [ 0 to 22.1808076352] + */ +uint32_t ln_int32(uint32_t numerator) +{ + return((uint32_t)Q_SHIFT_RND((int64_t)base2_logarithm(numerator) * + ONE_OVER_LOG2_E, 64, 32)); +} diff --git a/test/cmocka/src/math/arithmetic/CMakeLists.txt b/test/cmocka/src/math/arithmetic/CMakeLists.txt index 5657f0b87487..abf85ce1684b 100644 --- a/test/cmocka/src/math/arithmetic/CMakeLists.txt +++ b/test/cmocka/src/math/arithmetic/CMakeLists.txt @@ -14,3 +14,15 @@ cmocka_test(square_root square_root.c ${PROJECT_SOURCE_DIR}/src/math/sqrt_int16.c ) + +cmocka_test(base_10_logarithm + base_10_logarithm.c + ${PROJECT_SOURCE_DIR}/src/math/log_10.c + ${PROJECT_SOURCE_DIR}/src/math/base2log.c +) + +cmocka_test(base_e_logarithm + base_e_logarithm.c + ${PROJECT_SOURCE_DIR}/src/math/log_e.c + ${PROJECT_SOURCE_DIR}/src/math/base2log.c +) diff --git a/test/cmocka/src/math/arithmetic/base2_logarithm.c b/test/cmocka/src/math/arithmetic/base2_logarithm.c index be1c23527451..c66ee2c074ff 100644 --- a/test/cmocka/src/math/arithmetic/base2_logarithm.c +++ b/test/cmocka/src/math/arithmetic/base2_logarithm.c @@ -13,7 +13,7 @@ #include #include -#include +#include #include #include #include diff --git a/test/cmocka/src/math/arithmetic/base_10_logarithm.c b/test/cmocka/src/math/arithmetic/base_10_logarithm.c new file mode 100644 index 000000000000..cb5e7c027d5e --- /dev/null +++ b/test/cmocka/src/math/arithmetic/base_10_logarithm.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// Author: Shriram Shastry +// +// + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "log2_tables.h" +/* 'Error[max] = 0.0000071279028671,THD = -102.9407645424143993 ' */ +/* 'Error[max] = rms(log10() - double(log10_int32()))' */ +/* 'THD = 20*log10(Error[max])' */ +#define CMP_TOLERANCE 0.0000071279028671 +/* Natural logarithm log10(X) reference table generated by matlab/Octave */ +/* UQ4.28 */ +static const double common_log10_ref_table[] = { + 0.0000000000000000, 7.6373246662453802, 7.9383546619093615, 8.1144459209650428, + 8.2393846575733427, 8.3362946705813989, 8.4154759166290241, 8.4824227062596371, + 8.5404146532373240, 8.5915671756847054, 8.6373246662453802, 8.6787173514036056, + 8.7165059122930053, 8.7512680193222625, 8.7834527026386606, 8.8134159259684335, + 8.8414446495269665, 8.8677735882125130, 8.8925971719048302, 8.9160782677250818, + 8.9383546624098908, 8.9595439614559940, 8.9797473475226131, 8.9990525026982162, + 9.0175359083740947, 9.0352646753178405, 9.0522980146012202, 9.0686884307751292, + 9.0844826979451199, 9.0997226644895282, 9.1144459212987297, 9.1286863604025754, + 9.1424746448781171, 9.1558386064266184, 9.1688035835820649, 9.1813927108816724, + 9.1936271672907388, 9.2055263908534872, 9.2171082633890631, 9.2283892737852433, + 9.2393846580738721, 9.2501085234534361, 9.2605739571199752, 9.2707931222905753, + 9.2807773431865943, 9.2905371804656394, 9.3000824983621975, 9.3094225246070792, + 9.3185659040380759, 9.3275207466824899, 9.3362946709818218, 9.3448948427358882, + 9.3533280102652014, 9.3616005362239267, 9.3697184264391105, 9.3776873561036460, + 9.3855126936091011, 9.3931995222691196, 9.4007526601535094, 9.4081766782268659, + 9.4154759169627091, 9.4226545015843630, 9.4297163562280168, 9.4366652161756566, + 9.4435046406985137, 9.4502380233502628, 9.4568686022422757, 9.4633994693944423, + 9.4698335793932600, 9.4761737574178788, 9.4824227066886628, 9.4885830153874373, + 9.4946571630937573, 9.5006475267772306, 9.5065563863821918, 9.5123859300375031, + 9.5181382589213257, 9.5238153918078847, 9.5294192693208828, 9.5349517579159713, + 9.5404146536127215, 9.5458096854947918, 9.5511385189953373, 9.5564027589832818, + 9.5616039526647825, 9.5667435923129869, 9.5718231178381536, 9.5768439193242560, + 9.5818073388505756, 9.5867146733402073, 9.5915671761296206, 9.5963660590064990, + 9.6011124940261787, 9.6058076152298781, 9.6104525202710605, 9.6150482719557271, + 9.6195958997020572, 9.6240964009244330, 9.6285507423464711, 9.6329598611462810}; + +/* testvector in Q32.0 */ +static const uint32_t uv[100] = { + 1ULL, 43383509ULL, 86767017ULL, 130150525ULL, 173534033ULL, 216917541ULL, + 260301049ULL, 303684557ULL, 347068065ULL, 390451573ULL, 433835081ULL, 477218589ULL, + 520602097ULL, 563985605ULL, 607369113ULL, 650752621ULL, 694136129ULL, 737519638ULL, + 780903146ULL, 824286654ULL, 867670162ULL, 911053670ULL, 954437178ULL, 997820686ULL, + 1041204194ULL, 1084587702ULL, 1127971210ULL, 1171354718ULL, 1214738226ULL, 1258121734ULL, + 1301505242ULL, 1344888750ULL, 1388272258ULL, 1431655766ULL, 1475039274ULL, 1518422782ULL, + 1561806290ULL, 1605189798ULL, 1648573306ULL, 1691956814ULL, 1735340322ULL, 1778723830ULL, + 1822107338ULL, 1865490846ULL, 1908874354ULL, 1952257862ULL, 1995641370ULL, 2039024878ULL, + 2082408386ULL, 2125791894ULL, 2169175403ULL, 2212558911ULL, 2255942419ULL, 2299325927ULL, + 2342709435ULL, 2386092943ULL, 2429476451ULL, 2472859959ULL, 2516243467ULL, 2559626975ULL, + 2603010483ULL, 2646393991ULL, 2689777499ULL, 2733161007ULL, 2776544515ULL, 2819928023ULL, + 2863311531ULL, 2906695039ULL, 2950078547ULL, 2993462055ULL, 3036845563ULL, 3080229071ULL, + 3123612579ULL, 3166996087ULL, 3210379595ULL, 3253763103ULL, 3297146611ULL, 3340530119ULL, + 3383913627ULL, 3427297135ULL, 3470680643ULL, 3514064151ULL, 3557447659ULL, 3600831168ULL, + 3644214676ULL, 3687598184ULL, 3730981692ULL, 3774365200ULL, 3817748708ULL, 3861132216ULL, + 3904515724ULL, 3947899232ULL, 3991282740ULL, 4034666248ULL, 4078049756ULL, 4121433264ULL, + 4164816772ULL, 4208200280ULL, 4251583788ULL, 4294967295ULL}; + +static void test_math_arithmetic_base10log_fixed(void **state) +{ + (void)state; + + double clogfxp; + double diff; + int i; + + for (i = 0; i < ARRAY_SIZE(common_log10_ref_table); i++) { + clogfxp = log10_int32(uv[i]); + diff = fabs(common_log10_ref_table[i] - (double)clogfxp / (1 << 28)); + + if (diff > CMP_TOLERANCE) { + printf("%s: diff for %.16f: val = %16d, log10() = %.16f\n", __func__, diff, + uv[i], clogfxp / (1 << 28)); + assert_true(diff <= CMP_TOLERANCE); + } + } +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_math_arithmetic_base10log_fixed) + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + + return cmocka_run_group_tests(tests, NULL, NULL); +} diff --git a/test/cmocka/src/math/arithmetic/base_e_logarithm.c b/test/cmocka/src/math/arithmetic/base_e_logarithm.c new file mode 100644 index 000000000000..1c9dc2f44a7e --- /dev/null +++ b/test/cmocka/src/math/arithmetic/base_e_logarithm.c @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: BSD-3-Clause +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// Author: Shriram Shastry + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "log2_tables.h" +/* 'Error[max] = 0.0000164133276926,THD(-dBc) = -95.6960671942683234' */ +/* 'Error[max] = rms(log() - double(log_int32()))' */ +/* 'THD = 20*log10(Error[max])' */ +#define CMP_TOLERANCE 0.0000164133276926 + +/* Natural logarithm loge(X) reference table generated by matlab/Octave */ +/* UQ5.27 */ +static const double natural_log_lookup_table[] = { + 0.0000000000000000, 17.5855899268523359, 18.2787371074122831, 18.6842022155204468, + 18.9718842879722267, 19.1950278392864391, 19.3773493960803940, 19.5315000759076511, + 19.6650314685321739, 19.7828145041885577, 19.8881750198463827, 19.9834851996507084, + 20.0704965766403376, 20.1505392860869676, 20.2246472581140395, 20.2936401294912301, + 20.3581786505327571, 20.4188032722644479, 20.4759616860290699, 20.5300289072319480, + 20.5813222015588408, 20.6301123656733907, 20.6766323812583899, 20.7210841437836706, + 20.7636437581607112, 20.8044657526425461, 20.8436864657603671, 20.8814267937103786, + 20.9177944378507625, 20.9528857576336485, 20.9867873092828354, 21.0195771320810394, + 21.0513258303723845, 21.0820974890173112, 21.1119504521464485, 21.1409379890003279, + 21.1691088659487328, 21.1965078407425196, 21.2231760877918916, 21.2491515741640455, + 21.2744693821187845, 21.2991619946810467, 21.3232595462333343, 21.3467900436180038, + 21.3697795618183370, 21.3922524176471107, 21.4142313243436178, 21.4357375295432568, + 21.4567909387206548, 21.4774102259037889, 21.4976129332024932, 21.5174155604805932, + 21.5368336463203107, 21.5558818412742781, 21.5745739742703257, 21.5929231129229997, + 21.6109416184107097, 21.6286411954956677, 21.6460329381935921, 21.6631273715394208, + 21.6799344898427790, 21.6964637917813938, 21.7127243130127638, 21.7287246543415016, + 21.7444730112924880, 21.7599771978118319, 21.7752446699265008, 21.7902825472754031, + 21.8050976330453672, 21.8196964324517815, 21.8340851698895619, 21.8482698048676056, + 21.8622560468288185, 21.8760493689479993, 21.8896550209909755, 21.9030780413106569, + 21.9163232680485471, 21.9293953496040821, 21.9422987544284780, 21.9550377801946830, + 21.9676165623906030, 21.9800390823784895, 21.9923091749598925, 22.0044305354820757, + 22.0164067265188734, 22.0282411841561903, 22.0399372239099236, 22.0514980465667030, + 22.0629267423782807, 22.0742262976204415, 22.0853995982070579, 22.0964494343823858, + 22.1073785049035614, 22.1181894209970018, 22.1288847101032040, 22.1394668194234150, + 22.1499381192805984, 22.1603009063062437, 22.1705574064637361, 22.1807097776854185}; + +/* testvector in Q32.0 */ +static const uint32_t uv[100] = { + 1ULL, 43383509ULL, 86767017ULL, 130150525ULL, 173534033ULL, 216917541ULL, + 260301049ULL, 303684557ULL, 347068065ULL, 390451573ULL, 433835081ULL, 477218589ULL, + 520602097ULL, 563985605ULL, 607369113ULL, 650752621ULL, 694136129ULL, 737519638ULL, + 780903146ULL, 824286654ULL, 867670162ULL, 911053670ULL, 954437178ULL, 997820686ULL, + 1041204194ULL, 1084587702ULL, 1127971210ULL, 1171354718ULL, 1214738226ULL, 1258121734ULL, + 1301505242ULL, 1344888750ULL, 1388272258ULL, 1431655766ULL, 1475039274ULL, 1518422782ULL, + 1561806290ULL, 1605189798ULL, 1648573306ULL, 1691956814ULL, 1735340322ULL, 1778723830ULL, + 1822107338ULL, 1865490846ULL, 1908874354ULL, 1952257862ULL, 1995641370ULL, 2039024878ULL, + 2082408386ULL, 2125791894ULL, 2169175403ULL, 2212558911ULL, 2255942419ULL, 2299325927ULL, + 2342709435ULL, 2386092943ULL, 2429476451ULL, 2472859959ULL, 2516243467ULL, 2559626975ULL, + 2603010483ULL, 2646393991ULL, 2689777499ULL, 2733161007ULL, 2776544515ULL, 2819928023ULL, + 2863311531ULL, 2906695039ULL, 2950078547ULL, 2993462055ULL, 3036845563ULL, 3080229071ULL, + 3123612579ULL, 3166996087ULL, 3210379595ULL, 3253763103ULL, 3297146611ULL, 3340530119ULL, + 3383913627ULL, 3427297135ULL, 3470680643ULL, 3514064151ULL, 3557447659ULL, 3600831168ULL, + 3644214676ULL, 3687598184ULL, 3730981692ULL, 3774365200ULL, 3817748708ULL, 3861132216ULL, + 3904515724ULL, 3947899232ULL, 3991282740ULL, 4034666248ULL, 4078049756ULL, 4121433264ULL, + 4164816772ULL, 4208200280ULL, 4251583788ULL, 4294967295ULL}; + +static void test_math_arithmetic_base_e_log_fixed(void **state) +{ + (void)state; + + double logefxp; + double diff; + int i; + + for (i = 0; i < ARRAY_SIZE(natural_log_lookup_table); i++) { + logefxp = ln_int32(uv[i]); + diff = fabs(natural_log_lookup_table[i] - (double)logefxp / (1 << 27)); + + if (diff > CMP_TOLERANCE) { + printf("%s: diff for %.16f: value = %16d, log() = %.16f\n", __func__, diff, + uv[i], logefxp / (1 << 27)); + assert_true(diff <= CMP_TOLERANCE); + } + } +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test(test_math_arithmetic_base_e_log_fixed) + }; + + cmocka_set_message_output(CM_OUTPUT_TAP); + + return cmocka_run_group_tests(tests, NULL, NULL); +}