xref: /llvm-project/libc/src/math/docs/add_math_function.md (revision 62cd050b635cbb201dd08188696448cf5ab23260)
1a2b3e6beSTue Ly# How to add a new math function to LLVM-libc
2a2b3e6beSTue Ly
3a2b3e6beSTue LyThis document is to serve as a cookbook for adding a new math function
4a2b3e6beSTue Lyimplementation to LLVM libc.  To add a new function, apart from the actual
5a2b3e6beSTue Lyimplementation, one has to follow a few other steps to setup proper registration
6a2b3e6beSTue Lyand shipping of the new function.  Each of these steps will be described in
7a2b3e6beSTue Lydetail below.
8a2b3e6beSTue Ly
9a2b3e6beSTue Ly## Registration
10a2b3e6beSTue Ly
11a2b3e6beSTue LyTo register the function's entry points for supported OSes and architectures,
12a2b3e6beSTue Lytogether with its specifications:
13a2b3e6beSTue Ly
14a2b3e6beSTue Ly- Add entry points `libc.src.math.func` to the following files:
15a2b3e6beSTue Ly```
16a2b3e6beSTue Ly  libc/config/linux/<arch>/entrypoints.txt
17a2b3e6beSTue Ly  libc/config/windows/entrypoints.txt
18a2b3e6beSTue Ly```
19a2b3e6beSTue Ly- Add function specs to the file:
20a2b3e6beSTue Ly```
21*62cd050bSRoland McGrath  libc/include/math.yaml
22a2b3e6beSTue Ly```
23a2b3e6beSTue Ly
24a2b3e6beSTue Ly## Implementation
25a2b3e6beSTue Ly
26a2b3e6beSTue LyThe function's actual implementation and its corresponding header should be
27a2b3e6beSTue Lyadded to the following locations:
28a2b3e6beSTue Ly
29a2b3e6beSTue Ly- Add `add_math_entrypoint_object(<func>)` to:
30a2b3e6beSTue Ly```
31a2b3e6beSTue Ly  libc/src/math/CMakeLists.txt
32a2b3e6beSTue Ly```
33b6bc9d72SGuillaume Chatelet- Add function declaration (under `LIBC_NAMESPACE` namespace) to:
34a2b3e6beSTue Ly```
35a2b3e6beSTue Ly  libc/src/math/<func>.h
36a2b3e6beSTue Ly```
37a2b3e6beSTue Ly- Add function definition to:
38a2b3e6beSTue Ly```
39a2b3e6beSTue Ly  libc/src/math/generic/<func>.cpp
40a2b3e6beSTue Ly```
41a2b3e6beSTue Ly- Add the corresponding `add_entrypoint_object` to:
42a2b3e6beSTue Ly```
43a2b3e6beSTue Ly  libc/src/math/generic/CMakeLists.txt
44a2b3e6beSTue Ly```
45a2b3e6beSTue Ly- Add architectural specific implementations to:
46a2b3e6beSTue Ly```
47a2b3e6beSTue Ly  libc/src/math/<arch>/<func>.cpp
48a2b3e6beSTue Ly```
49a2b3e6beSTue Ly
50a2b3e6beSTue Ly### Floating point utility
51a2b3e6beSTue Ly
52a2b3e6beSTue Ly- Floating point utilities and math functions that are also used internally are
53a2b3e6beSTue Lylocated at:
54a2b3e6beSTue Ly```
55a2b3e6beSTue Ly  libc/src/__support/FPUtils
56a2b3e6beSTue Ly```
57a2b3e6beSTue Ly- These are preferred to be included as header-only.
58a2b3e6beSTue Ly- To manipulate bits of floating point numbers, use the template class
59b6bc9d72SGuillaume Chatelet`LIBC_NAMESPACE::fputil::FPBits<>` in the header file:
60a2b3e6beSTue Ly```
61a2b3e6beSTue Ly  libc/src/__support/FPUtils/FPBits.h
62a2b3e6beSTue Ly```
63a2b3e6beSTue Ly
64a2b3e6beSTue Ly## Testing
65a2b3e6beSTue Ly
66a2b3e6beSTue Ly### MPFR utility
67a2b3e6beSTue Ly
68a2b3e6beSTue LyIn addition to the normal testing macros such as `EXPECT_EQ, ASSERT_THAT, ...`
69a2b3e6beSTue Lythere are two special macros `ASSERT_MPFR_MATCH` and `EXPECT_MPFR_MATCH` to
70a2b3e6beSTue Lycompare your outputs with the corresponding MPFR function.  In
71a2b3e6beSTue Lyorder for your new function to be supported by these two macros,
72a2b3e6beSTue Lythe following files will need to be updated:
73a2b3e6beSTue Ly
74b6bc9d72SGuillaume Chatelet- Add the function enum to `LIBC_NAMESPACE::testing::mpfr::Operation` in the
75a2b3e6beSTue Lyheader file:
76a2b3e6beSTue Ly```
77a2b3e6beSTue Ly  libc/utils/MPFRWrapper/MPFRUtils.h
78a2b3e6beSTue Ly```
79a2b3e6beSTue Ly- Add support for `func` in the `MPFRNumber` class and the corresponding link
80a2b3e6beSTue Lybetween the enum and its call to the file:
81a2b3e6beSTue Ly```
82a2b3e6beSTue Ly  libc/utils/MPFRWrapper/MPFRUtils.cpp
83a2b3e6beSTue Ly```
84a2b3e6beSTue Ly
85a2b3e6beSTue Ly### Unit tests
86a2b3e6beSTue Ly
87a2b3e6beSTue LyBesides the usual testing macros like `EXPECT_EQ, ASSERT_TRUE, ...` there are
88a2b3e6beSTue Lytesting macros specifically used for floating point values, such as
89a2b3e6beSTue Ly`EXPECT_FP_EQ, ASSERT_FP_LE, ...`
90a2b3e6beSTue Ly
9184c899b2STue Ly- Add smoke tests (simple cases and zeros / inf / nan inputs or outputs) to:
9284c899b2STue Ly```
9384c899b2STue Ly  libc/test/src/math/smoke/<func>_test.cpp
9484c899b2STue Ly```
9584c899b2STue Ly- Add unit test that might require MPFR to:
96a2b3e6beSTue Ly```
979369aa14STue Ly  libc/test/src/math/<func>_test.cpp
98a2b3e6beSTue Ly```
9984c899b2STue Ly- Add the corresponding entry points to:
100a2b3e6beSTue Ly```
10184c899b2STue Ly  libc/test/src/math/smoke/CMakeLists.txt
102a2b3e6beSTue Ly  libc/test/src/math/CMakeLists.txt
103a2b3e6beSTue Ly```
104a2b3e6beSTue Ly
105a2b3e6beSTue Ly### Exhaustive tests
106a2b3e6beSTue Ly
107a2b3e6beSTue LyExhaustive tests are long-running tests that are not included when you run
108a2b3e6beSTue Ly`ninja check-libc`.  These exhaustive tests are added and manually run in
109a2b3e6beSTue Lyorder to find exceptional cases for your function's implementation.
110a2b3e6beSTue Ly
111a2b3e6beSTue Ly- Add an exhaustive test to:
112a2b3e6beSTue Ly```
1139369aa14STue Ly  libc/test/src/math/exhaustive/<func>_test.cpp
114a2b3e6beSTue Ly```
115a2b3e6beSTue Ly- Add the corresponding entry point to:
116a2b3e6beSTue Ly```
117a2b3e6beSTue Ly  libc/test/src/math/exhaustive/CMakeLists.txt
118a2b3e6beSTue Ly```
1199532074aSTue Ly- The template class `LlvmLibcExhaustiveMathTest` located at:
120e11e973eSTue Ly```
121e11e973eSTue Ly  libc/test/src/math/exhaustive/exhaustive_test.h
122e11e973eSTue Ly```
1239532074aSTue Lycan be used for conveniently parallelizing the exhaustive tests.
124a2b3e6beSTue Ly
125a2b3e6beSTue Ly### Performance tests
126a2b3e6beSTue Ly
127a2b3e6beSTue LyPerformance tests compare your function's implementation with the system libc
128a2b3e6beSTue Lyimplementation (which is very often glibc).
129a2b3e6beSTue Ly
130a2b3e6beSTue Ly- Add a performance test to:
131a2b3e6beSTue Ly```
132d99bb014Slntue  libc/test/src/math/performance_testing/<func>_perf.cpp
133a2b3e6beSTue Ly```
134a2b3e6beSTue Ly- Add the corresponding entry point to:
135a2b3e6beSTue Ly```
136d99bb014Slntue  libc/test/src/math/performance_testing/CMakeLists.txt
137a2b3e6beSTue Ly```
138a2b3e6beSTue Ly
139a2b3e6beSTue Ly## Build and Run
140a2b3e6beSTue Ly
141a2b3e6beSTue Ly- Check out the LLVM source tree:
142a2b3e6beSTue Ly```
143a2b3e6beSTue Ly  $ git clone https://github.com/llvm/llvm-project.git
144a2b3e6beSTue Ly```
145a2b3e6beSTue Ly
146a2b3e6beSTue Ly- Setup projects with CMake:
147a2b3e6beSTue Ly```
148a2b3e6beSTue Ly  $ cd llvm-project
149a2b3e6beSTue Ly  $ mkdir build
150a2b3e6beSTue Ly  $ cd build
151a2b3e6beSTue Ly  $ cmake ../llvm -G Ninja \
152a2b3e6beSTue Ly  -DLLVM_ENABLE_PROJECTS="llvm;libc" \
153a2b3e6beSTue Ly  -DCMAKE_BUILD_TYPE=Debug \
154a2b3e6beSTue Ly  -DCMAKE_C_COMPILER=clang \
155a2b3e6beSTue Ly  -DCMAKE_CXX_COMPILER=clang++
156a2b3e6beSTue Ly```
157a2b3e6beSTue Ly
158a2b3e6beSTue Ly- Build the whole `libc`:
159a2b3e6beSTue Ly```
160a48c4a45STue Ly  $ ninja libc
161a2b3e6beSTue Ly```
162a2b3e6beSTue Ly
163a2b3e6beSTue Ly- Run all unit tests:
164a2b3e6beSTue Ly```
165a2b3e6beSTue Ly  $ ninja check-libc
166a2b3e6beSTue Ly```
167a2b3e6beSTue Ly
16884c899b2STue Ly- Run math smoke tests only:
16984c899b2STue Ly```
17084c899b2STue Ly  $ ninja libc-math-smoke-tests
17184c899b2STue Ly```
17284c899b2STue Ly
17384c899b2STue Ly- Run math smoke and unit tests:
17484c899b2STue Ly```
17584c899b2STue Ly  $ ninja libc-math-unittests
17684c899b2STue Ly```
17784c899b2STue Ly
178a2b3e6beSTue Ly- Build and Run a specific unit test:
179a2b3e6beSTue Ly```
180721f1495SJob Henandez Lara  $ ninja libc.test.src.math.<func>_test.__unit__
181a2b3e6beSTue Ly  $ projects/libc/test/src/math/libc.test.src.math.<func>_test
182a2b3e6beSTue Ly```
183a2b3e6beSTue Ly
184a2b3e6beSTue Ly- Build and Run exhaustive test (might take hours to run):
185a2b3e6beSTue Ly```
186a2b3e6beSTue Ly  $ ninja libc.test.src.math.exhaustive.<func>_test
187e11e973eSTue Ly  $ projects/libc/test/src/math/exhaustive/libc.test.src.math.exhaustive.<func>_test
188a2b3e6beSTue Ly```
189a2b3e6beSTue Ly
190a2b3e6beSTue Ly- Build and Run performance test:
191a2b3e6beSTue Ly```
192d99bb014Slntue  $ ninja libc.test.src.math.performance_testing.<func>_perf
193d99bb014Slntue  $ projects/libc/test/src/math/performance_testing/libc.test.src.math.performance_testing.<func>_perf
194a2b3e6beSTue Ly  $ cat <func>_perf.log
195a2b3e6beSTue Ly```
196a2b3e6beSTue Ly
197a2b3e6beSTue Ly## Code reviews
198a2b3e6beSTue Ly
199d3455f4dSCyuriaWe use GitHub's inbuilt pull request system for code review:
200a2b3e6beSTue Ly```
201d3455f4dSCyuria  https://docs.github.com/articles/about-collaborative-development-models
202d3455f4dSCyuria  https://docs.github.com/articles/about-pull-requests
203a2b3e6beSTue Ly```
204