[all-commits] [llvm/llvm-project] e2f065: [libc][math] Implement asinf function correctly ro...

lntue via All-commits all-commits at lists.llvm.org
Wed Sep 7 16:28:12 PDT 2022


  Branch: refs/heads/main
  Home:   https://github.com/llvm/llvm-project
  Commit: e2f065c2a3538c85ad7f6964b696dcdc1c3f95e4
      https://github.com/llvm/llvm-project/commit/e2f065c2a3538c85ad7f6964b696dcdc1c3f95e4
  Author: Tue Ly <lntue at google.com>
  Date:   2022-09-07 (Wed, 07 Sep 2022)

  Changed paths:
    M libc/config/darwin/arm/entrypoints.txt
    M libc/config/linux/aarch64/entrypoints.txt
    M libc/config/linux/x86_64/entrypoints.txt
    M libc/config/windows/entrypoints.txt
    M libc/docs/math.rst
    M libc/spec/stdc.td
    M libc/src/math/CMakeLists.txt
    A libc/src/math/asinf.h
    M libc/src/math/generic/CMakeLists.txt
    A libc/src/math/generic/asinf.cpp
    M libc/test/src/math/CMakeLists.txt
    A libc/test/src/math/asinf_test.cpp
    M libc/test/src/math/exhaustive/CMakeLists.txt
    A libc/test/src/math/exhaustive/asinf_test.cpp
    M libc/utils/MPFRWrapper/MPFRUtils.cpp
    M libc/utils/MPFRWrapper/MPFRUtils.h

  Log Message:
  -----------
  [libc][math] Implement asinf function correctly rounded for all rounding modes.

Implement asinf function correctly rounded for all rounding modes.

For `|x| <= 0.5`, we approximate `asin(x)` by
```
  asin(x) = x * P(x^2)
```
where `P(X^2) = Q(X)` is a degree-20 minimax even polynomial approximating
`asin(x)/x` on `[0, 0.5]` generated by Sollya with:
```
  > Q = fpminimax(asin(x)/x, [|0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20|],
                 [|1, D...|], [0, 0.5]);
```

When `|x| > 0.5`, we perform range reduction as follow:
Assume further that `0.5 < x <= 1`, and let:
```
  y = asin(x)
```
We will use the double angle formula:
```
  cos(2X) = 1 - 2 sin^2(X)
```
and the complement angle identity:
```
  x = sin(y) = cos(pi/2 - y)
              = 1 - 2 sin^2 (pi/4 - y/2)
```
So:
```
  sin(pi/4 - y/2) = sqrt( (1 - x)/2 )
```
And hence:
```
  pi/4 - y/2 = asin( sqrt( (1 - x)/2 ) )
```
Equivalently:
```
  asin(x) = y = pi/2 - 2 * asin( sqrt( (1 - x)/2 ) )
```
Let `u = (1 - x)/2`, then
```
  asin(x) = pi/2 - 2 * asin(u)
```
Moreover, since `0.5 < x <= 1`,
```
  0 <= u < 1/4, and 0 <= sqrt(u) < 0.5.
```
And hence we can reuse the same polynomial approximation of `asin(x)` when
`|x| <= 0.5`:
```
  asin(x) = pi/2 - 2 * u * P(u^2).
```

Performance benchmark using `perf` tool from the CORE-MATH project on Ryzen 1700:
```
$ CORE_MATH_PERF_MODE="rdtsc" ./perf.sh asinf
CORE-MATH reciprocal throughput   : 23.418
System LIBC reciprocal throughput : 27.310
LIBC reciprocal throughput        : 22.741

$ CORE_MATH_PERF_MODE="rdtsc" ./perf.sh asinf --latency
GNU libc version: 2.35
GNU libc release: stable
CORE-MATH latency   : 58.884
System LIBC latency : 62.055
LIBC latency        : 62.037
```

Reviewed By: orex, zimmermann6

Differential Revision: https://reviews.llvm.org/D133400




More information about the All-commits mailing list