Repository navigation
math: Add logarithm base E and base 10 #5074
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| /* SPDX-License-Identifier: BSD-3-Clause | ||
| * | ||
| * Copyright(c) 2021 Intel Corporation. All rights reserved. | ||
| * | ||
| * Author: Shriram Shastry <malladi.sastry@linux.intel.com> | ||
| * | ||
| */ | ||
|
|
||
| #ifndef __SOF_MATH_BASE_LOGARITHM_H__ | ||
| #define __SOF_MATH_BASE_LOGARITHM_H__ | ||
|
|
||
| #include <stdint.h> | ||
|
|
||
| #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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| // SPDX-License-Identifier: BSD-3-Clause/ | ||
| // | ||
| // Copyright(c) 2021 Intel Corporation. All rights reserved. | ||
| // | ||
| // Author: Shriram Shastry <malladi.sastry@linux.intel.com> | ||
| // | ||
| // | ||
|
|
||
| #include <sof/math/log.h> | ||
| #include <sof/audio/format.h> | ||
| /** | ||
| * 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] | ||
| */ | ||
|
ShriramShastry marked this conversation as resolved.
Outdated
|
||
| uint32_t log10_int32(uint32_t numerator) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You still need to add the
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I compared gcc and clang outputs a number of times and I've never seen (
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. given we know xcc isnt the smartest sometimes i think it is still wise to have the hints for it
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if I change to In case I make changes in then |
||
| { | ||
| return((uint32_t)Q_SHIFT_RND((int64_t)base2_logarithm(numerator) * | ||
| ONE_OVER_LOG2_10, 63, 32)); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| // SPDX-License-Identifier: BSD-3-Clause | ||
| // | ||
| // Copyright(c) 2021 Intel Corporation. All rights reserved. | ||
| // | ||
| // Author: Shriram Shastry <malladi.sastry@linux.intel.com> | ||
| // | ||
| // | ||
|
|
||
| #include <sof/math/log.h> | ||
| #include <sof/audio/format.h> | ||
| /** | ||
| * 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) | ||
|
lgirdwood marked this conversation as resolved.
Outdated
|
||
| { | ||
| return((uint32_t)Q_SHIFT_RND((int64_t)base2_logarithm(numerator) * | ||
| ONE_OVER_LOG2_E, 64, 32)); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,105 @@ | ||
| // SPDX-License-Identifier: BSD-3-Clause | ||
| // | ||
| // Copyright(c) 2021 Intel Corporation. All rights reserved. | ||
| // | ||
| // Author: Shriram Shastry <malladi.sastry@linux.intel.com> | ||
| // | ||
| // | ||
|
|
||
| #include <stdio.h> | ||
| #include <stdint.h> | ||
| #include <stdarg.h> | ||
| #include <stddef.h> | ||
| #include <setjmp.h> | ||
| #include <math.h> | ||
| #include <cmocka.h> | ||
| #include <string.h> | ||
|
|
||
| #include <sof/math/log.h> | ||
| #include <sof/audio/format.h> | ||
| #include <sof/string.h> | ||
| #include <sof/common.h> | ||
| #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 */ | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not just use
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using book & pen/manual calculation
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Log table is a reference table which is derived from offline log function using
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @marc-hb we dont use C lib maths as they are not optimised for xtensa or SOF formats.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems vulnerable to a copy/paste typo. Is there some redundancy built in in the test? If not, then adding another test, very simple test using |
||
| /* 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); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,104 @@ | ||
| // SPDX-License-Identifier: BSD-3-Clause | ||
| // | ||
| // Copyright(c) 2021 Intel Corporation. All rights reserved. | ||
| // | ||
| // Author: Shriram Shastry <malladi.sastry@linux.intel.com> | ||
|
|
||
| #include <stdio.h> | ||
| #include <stdint.h> | ||
| #include <stdarg.h> | ||
| #include <stddef.h> | ||
| #include <setjmp.h> | ||
| #include <math.h> | ||
| #include <cmocka.h> | ||
| #include <string.h> | ||
|
|
||
| #include <sof/math/log.h> | ||
| #include <sof/audio/format.h> | ||
| #include <sof/string.h> | ||
| #include <sof/common.h> | ||
| #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) | ||
|
ShriramShastry marked this conversation as resolved.
Outdated
|
||
| { | ||
| (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); | ||
|
ShriramShastry marked this conversation as resolved.
Outdated
|
||
| } | ||
| } | ||
| } | ||
|
|
||
| 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); | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.