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