Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 0 additions & 17 deletions src/include/sof/math/base2log.h

This file was deleted.

21 changes: 21 additions & 0 deletions src/include/sof/math/log.h
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
8 changes: 8 additions & 0 deletions src/math/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
14 changes: 14 additions & 0 deletions src/math/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 1 addition & 2 deletions src/math/base2log.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@
//
//

/* Include Files */
#include <sof/math/base2log.h>
#include <sof/math/log.h>

/* Defines Constant*/
#define BASE2LOG_WRAP_SCHAR_BITS 0xFF
Expand Down
32 changes: 32 additions & 0 deletions src/math/log_10.c
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 |
Comment thread
ShriramShastry marked this conversation as resolved.
Outdated
* +----+-----+-------+----+----+-------+--------+--------+
* |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]
*/
Comment thread
ShriramShastry marked this conversation as resolved.
Outdated
uint32_t log10_int32(uint32_t numerator)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You still need to add the inline keyword to get the optimization

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The 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 inline making any difference, at least never with -On where n > 0. The optimizer always thinks it knows better. That's why there is non-portable stuff like ALWAYS_INLINE.

(static inline is still useful in .h files to silence some warnings)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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

@ShriramShastry ShriramShastry Feb 9, 2022 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if I change to inline ln_int32() and inline log10_int32(), I could see below error

No codespell typos will be found - file '/usr/share/codespell/dictionary.txt': No such file or directory
ERROR: inline keyword should sit between storage class and type
#10: FILE: src/math/log_10.c:28:
+uint32_t inline log10_int32(uint32_t numerator)

ERROR: inline keyword should sit between storage class and type
#23: FILE: src/math/log_e.c:29:
+uint32_t inline ln_int32(uint32_t numerator)

In case I make changes in log.h like below

static inline uint32_t ln_int32(uint32_t numerator)
{
	return((uint32_t)Q_SHIFT_RND((int64_t)base2_logarithm(numerator) *
				     ONE_OVER_LOG2_E, 64, 32));
}
static inline uint32_t log10_int32(uint32_t numerator)
{
		return((uint32_t)Q_SHIFT_RND((int64_t)base2_logarithm(numerator) *
				     ONE_OVER_LOG2_10, 63, 32));
}

then log10_int32(uint32_t numerator) and ln_int32(uint32_t numerator) in log_10.c and log_e.c will be redundant, the impact of removing log_10.c and log_e.c will result in error in cmocka compilation. cmocka CmakeList.txt is using of log_10.c and log_e.c files.

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
)

{
return((uint32_t)Q_SHIFT_RND((int64_t)base2_logarithm(numerator) *
ONE_OVER_LOG2_10, 63, 32));
}
33 changes: 33 additions & 0 deletions src/math/log_e.c
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)
Comment thread
lgirdwood marked this conversation as resolved.
Outdated
{
return((uint32_t)Q_SHIFT_RND((int64_t)base2_logarithm(numerator) *
ONE_OVER_LOG2_E, 64, 32));
}
12 changes: 12 additions & 0 deletions test/cmocka/src/math/arithmetic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
)
2 changes: 1 addition & 1 deletion test/cmocka/src/math/arithmetic/base2_logarithm.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#include <cmocka.h>
#include <string.h>

#include <sof/math/base2log.h>
#include <sof/math/log.h>
#include <sof/audio/format.h>
#include <sof/string.h>
#include <sof/common.h>
Expand Down
105 changes: 105 additions & 0 deletions test/cmocka/src/math/arithmetic/base_10_logarithm.c
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 */

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just use <math.h>'s log functions, why is this table needed?

@ShriramShastry ShriramShastry Dec 21, 2021 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using book & pen/manual calculation log() calculation, In most of the cases results are more closer to Matlab/Octave log function . So i am considering matlab /octave more accurate in precision than built-in <math.h>, library functions.

@ShriramShastry ShriramShastry Dec 21, 2021 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The 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 Octave/matlab. Reference table values are compared against fix point log_10_int32 function.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The 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.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The 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 <math.h> (when available) would provide that redundancy.

/* 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);
}
104 changes: 104 additions & 0 deletions test/cmocka/src/math/arithmetic/base_e_logarithm.c
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)
Comment thread
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);
Comment thread
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);
}