Math: Complex: Calculate complex phase angle with sofm_atan2()#10629
Math: Complex: Calculate complex phase angle with sofm_atan2()#10629singalsu wants to merge 5 commits intothesofproject:mainfrom
Conversation
ec549e9 to
9971505
Compare
There was a problem hiding this comment.
Pull request overview
This PR adds a fixed-point sofm_atan2_32b() implementation (Q1.31 inputs → Q3.29 radians) and switches complex-to-polar phase calculation to use it, along with new unit-test vectors and build integration.
Changes:
- Add
src/math/atan2.cimplementingsofm_atan2_32b()via a Remez polynomial approximation. - Update
sofm_icomplex32_to_polar()to compute phase usingsofm_atan2_32b()instead ofacos_fixed_32b(). - Add and wire up atan2 unit tests + generated tables; add
Q_CONVERT_QTOD()for double-based comparisons in tests.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| test/ztest/unit/math/basic/trigonometry/trig_test.c | Adds sofm_atan2_32b() unit test using generated vectors. |
| test/ztest/unit/math/basic/trigonometry/atan2_tables.m | Octave/MATLAB script to generate fixed-point test vectors/header. |
| test/ztest/unit/math/basic/trigonometry/atan2_tables.h | Generated test vectors for atan2 validation. |
| test/ztest/unit/math/basic/trigonometry/CMakeLists.txt | Links src/math/atan2.c into trig unit-test build. |
| test/ztest/unit/math/basic/complex/test_complex_polar.c | Tightens angle tolerance to match improved phase calculation. |
| test/ztest/unit/math/basic/complex/CMakeLists.txt | Links src/math/atan2.c into complex unit-test build. |
| src/math/complex.c | Switches polar angle computation to sofm_atan2_32b(). |
| src/math/atan2.c | New implementation of fixed-point 4-quadrant atan2. |
| src/math/Kconfig | Adds MATH_ATAN2 config and ensures MATH_COMPLEX selects it. |
| src/math/CMakeLists.txt | Conditionally builds atan2.c under CONFIG_MATH_ATAN2. |
| src/include/sof/math/trig.h | Declares sofm_atan2_32b() and documents it (needs consistency fixes). |
| src/include/sof/audio/format.h | Adds Q_CONVERT_QTOD() macro used by tests. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This patch adds the four quadrant arctan function version. It is useful for fast computation of phase angle -pi to +pi in radians from a complex number (real, imaginary) value. The approximation uses a 9th order polynomial that is implemented with Horner's rule evaluation. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
The usage of Q_CONVERT_QTOF() causes build issue with llvm toolchain when assigned to a double type in ztest code: error: implicit conversion increases floating-point precision: 'float' to 'double' [-Werror,-Wdouble-promotion] Since a double is needed to fully match the accuracy of 32 bit fraction, a new macro Q_CONVERT_QTOD() is added for the purpose. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
This patch adds the test for the function. The input values table for atan are Q1.31 (x, y) pair numbers and reference angle values in Q3.29 radians. The table is computed with the double precision atan2() function in Octave and converted to fractional integers. See script atan2_tables.m. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
This patch updates the phase angle calculation in function sofm_icomple32_to_polar() with more efficient sofm_atan2() function. Calculate of angle with arctan function avoids the 64 bit divide in the previous arccos function based calculation. In 48 kHz stereo STFT processing with 1024 size FFT and hop of 256 this change saves about 14 MCPS in MTL platform (204 MCPS to 190 MCPS). Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
The atan2() function in sofm_ipolar32_to_complex() helped to increase accuracy, so the tolerance for error could be decreased to about 0.001 degrees (2.0e-5 radians). Also the print format for achieved accuracy is improved for nicer appearance. Signed-off-by: Seppo Ingalsuo <seppo.ingalsuo@linux.intel.com>
9971505 to
aecc9d3
Compare
There was a problem hiding this comment.
Pull request overview
Adds a fixed-point four-quadrant atan2 implementation and switches complex polar conversion to use it (instead of acos-based reconstruction), with accompanying unit tests and build/config wiring.
Changes:
- Introduce
sofm_atan2_32b()(Q1.31 inputs → Q3.29 radians output) behindCONFIG_MATH_ATAN2. - Update
sofm_icomplex32_to_polar()to compute phase viasofm_atan2_32b(imag, real). - Add Ztest coverage for
sofm_atan2_32b()plus generated test vectors/tables.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| test/ztest/unit/math/basic/trigonometry/trig_test.c | Adds sofm_atan2_32b() unit test using generated vectors. |
| test/ztest/unit/math/basic/trigonometry/atan2_tables.m | Adds Octave/MATLAB script to generate atan2 test vectors header. |
| test/ztest/unit/math/basic/trigonometry/atan2_tables.h | Adds generated Q31 input vectors and Q29 reference angles. |
| test/ztest/unit/math/basic/trigonometry/CMakeLists.txt | Links atan2.c into trigonometry unit test build. |
| test/ztest/unit/math/basic/complex/test_complex_polar.c | Tightens angle tolerance and adjusts test info prints. |
| test/ztest/unit/math/basic/complex/CMakeLists.txt | Links atan2.c into complex unit test build. |
| src/math/complex.c | Switches polar angle computation to sofm_atan2_32b(). |
| src/math/atan2.c | New polynomial-based atan2 implementation + exported symbol. |
| src/math/Kconfig | Adds MATH_ATAN2 option; wires complex math to select needed deps. |
| src/math/CMakeLists.txt | Builds atan2.c when CONFIG_MATH_ATAN2 is enabled. |
| src/include/sof/math/trig.h | Declares sofm_atan2_32b() and documents it. |
| src/include/sof/audio/format.h | Adds Q_CONVERT_QTOD() helper macro for tests/diagnostics. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| double delta_max = 0.0; | ||
| int32_t result_q29_max = 0; | ||
| int32_t result_q29; | ||
| int i_max = -1; | ||
| int i; |
| zassert_true(delta <= CMP_TOLERANCE_ATAN2, | ||
| "sofm_atan2 failed for input %d: (%d, %d) result %d", | ||
| i, atan2_test_y[i], atan2_test_x[i], result_q29); |
| * atan(z) = z * (C0 + z^2 * (C1 + z^2 * (C2 + z^2 * C3))) | ||
| * with Remez minimax coefficients on [0, 1]. |
| # SPDX-License-Identifier: BSD-3-Clause | ||
| # | ||
| # Copyright(c) 2026 Intel Corporation. |
No description provided.