- 
                Notifications
    You must be signed in to change notification settings 
- Fork 15k
[libc][math][c23] Implement C23 math function atanpif16 #150400
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
          
     Merged
      
      
    
  
     Merged
                    Changes from 12 commits
      Commits
    
    
            Show all changes
          
          
            21 commits
          
        
        Select commit
          Hold shift + click to select a range
      
      1c1135b
              
                feat: add the implementatio of `atanpif16`
              
              
                hulxv 1a5d472
              
                add entries
              
              
                hulxv 9269370
              
                add unit tests for `atanpif16`
              
              
                hulxv bdae514
              
                add exhaustive test for `atanpif16`
              
              
                hulxv 3d0beca
              
                improve `atanpif16` implementation
              
              
                hulxv f2e6a46
              
                Merge branch 'main' into libc/math/teagt/impl-atanpif16
              
              
                hulxv 2499fc9
              
                formatting
              
              
                hulxv 5d08800
              
                fix conflicts
              
              
                hulxv c8ffe9b
              
                fix conflcts
              
              
                hulxv 1e3a59f
              
                missed blank line
              
              
                hulxv e06c286
              
                missed blank line
              
              
                hulxv fad9a76
              
                check `atanpi` in float16
              
              
                hulxv 5d9362a
              
                fix format
              
              
                hulxv a5f5f1c
              
                fix atanpi mpfr number
              
              
                hulxv cefc075
              
                improvements
              
              
                hulxv 0da444c
              
                add missed depends
              
              
                hulxv 669c7e0
              
                fix: wrong condition in mpfr
              
              
                hulxv 5b69a72
              
                formatting
              
              
                hulxv 0a234b6
              
                fix  `MPFRNumber::atanpi()`
              
              
                hulxv ed38cad
              
                use `cpp::array` instead of regular array
              
              
                hulxv c5493aa
              
                enhancements
              
              
                hulxv File filter
Filter by extension
Conversations
          Failed to load comments.   
        
        
          
      Loading
        
  Jump to
        
          Jump to file
        
      
      
          Failed to load files.   
        
        
          
      Loading
        
  Diff view
Diff view
There are no files selected for viewing
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| //===-- Implementation header for atanpif16 ---------------------*- C++ -*-===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception. | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|  | ||
| #ifndef LLVM_LIBC_SRC_MATH_ATANPIF16_H | ||
| #define LLVM_LIBC_SRC_MATH_ATANPIF16_H | ||
|  | ||
| #include "src/__support/macros/config.h" | ||
| #include "src/__support/macros/properties/types.h" | ||
|  | ||
| namespace LIBC_NAMESPACE_DECL { | ||
|  | ||
| float16 atanpif16(float16 x); | ||
|  | ||
| } // namespace LIBC_NAMESPACE_DECL | ||
|  | ||
| #endif // LLVM_LIBC_SRC_MATH_ASINF16_H | 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,155 @@ | ||
| //===-- Half-precision atanpi function ------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|  | ||
| #include "src/math/atanpif16.h" | ||
| #include "hdr/errno_macros.h" | ||
| #include "hdr/fenv_macros.h" | ||
| #include "src/__support/FPUtil/FEnvImpl.h" | ||
| #include "src/__support/FPUtil/FPBits.h" | ||
| #include "src/__support/FPUtil/PolyEval.h" | ||
| #include "src/__support/FPUtil/cast.h" | ||
| #include "src/__support/FPUtil/multiply_add.h" | ||
| #include "src/__support/FPUtil/sqrt.h" | ||
|  | ||
| namespace LIBC_NAMESPACE_DECL { | ||
|  | ||
| // Using Python's SymPy library, we can obtain the polynomial approximation of | ||
| // arctan(x)/pi. The steps are as follows: | ||
| // >>> from sympy import * | ||
| // >>> import math | ||
| // >>> x = symbols('x') | ||
| // >>> print(series(atan(x)/math.pi, x, 0, 17)) | ||
| // | ||
| // Output: | ||
| // 0.318309886183791*x - 0.106103295394597*x**3 + 0.0636619772367581*x**5 - | ||
| // 0.0454728408833987*x**7 + 0.0353677651315323*x**9 - 0.0289372623803446*x**11 | ||
| // + 0.0244853758602916*x**13 - 0.0212206590789194*x**15 + O(x**17) | ||
| // | ||
| // We will assign this 19-degree Taylor polynomial as g(x). This polynomial | ||
|         
                  hulxv marked this conversation as resolved.
              Outdated
          
            Show resolved
            Hide resolved | ||
| // approximation is accurate for arctan(x)/pi when |x| is in the range [0, 0.5]. | ||
| // | ||
| // | ||
| // To compute arctan(x) for all real x, we divide the domain into the following | ||
| // cases: | ||
| // | ||
| // * Case 1: |x| <= 0.5 | ||
| // In this range, the direct polynomial approximation is used: | ||
| // arctan(x)/pi = sign(x) * g(|x|) | ||
| // or equivalently, arctan(x) = sign(x) * pi * g(|x|). | ||
| // | ||
| // * Case 2: 0.5 < |x| <= 1 | ||
| // We use the double-angle identity for the tangent function, specifically: | ||
| // arctan(x) = 2 * arctan(x / (1 + sqrt(1 + x^2))). | ||
| // Applying this, we have: | ||
| // arctan(x)/pi = sign(x) * 2 * arctan(x')/pi, | ||
| // where x' = |x| / (1 + sqrt(1 + x^2)). | ||
| // Thus, arctan(x)/pi = sign(x) * 2 * g(x') | ||
| // | ||
| // When |x| is in (0.5, 1], the value of x' will always fall within the | ||
| // interval [0.207, 0.414], which is within the accurate range of g(x). | ||
| // | ||
| // * Case 3: |x| > 1 | ||
| // For values of |x| greater than 1, we use the reciprocal transformation | ||
| // identity: | ||
| // arctan(x) = pi/2 - arctan(1/x) for x > 0. | ||
| // For any x (real number), this generalizes to: | ||
| // arctan(x)/pi = sign(x) * (1/2 - arctan(1/|x|)/pi). | ||
| // Then, using g(x) for arctan(1/|x|)/pi: | ||
| // arctan(x)/pi = sign(x) * (1/2 - g(1/|x|)). | ||
| // | ||
| // Note that if 1/|x| still falls outside the | ||
| // g(x)'s primary range of accuracy (i.e., if 0.5 < 1/|x| <= 1), the rule | ||
| // from Case 2 must be applied recursively to 1/|x|. | ||
|  | ||
| LLVM_LIBC_FUNCTION(float16, atanpif16, (float16 x)) { | ||
| using FPBits = fputil::FPBits<float16>; | ||
|  | ||
| FPBits xbits(x); | ||
| bool is_neg = xbits.is_neg(); | ||
|  | ||
| auto signed_result = [is_neg](double r) -> float16 { | ||
| return fputil::cast<float16>(is_neg ? -r : r); | ||
| }; | ||
|  | ||
| if (LIBC_UNLIKELY(xbits.is_inf_or_nan())) { | ||
|         
                  hulxv marked this conversation as resolved.
              Show resolved
            Hide resolved | ||
| if (xbits.is_nan()) { | ||
| return x; | ||
| } | ||
|         
                  hulxv marked this conversation as resolved.
              Show resolved
            Hide resolved | ||
| // atanpi(±∞) = ±0.5 | ||
| return signed_result(0.5); | ||
| } | ||
|  | ||
| if (LIBC_UNLIKELY(xbits.is_zero())) { | ||
| return x; | ||
| } | ||
|  | ||
| double x_abs = fputil::cast<double>(xbits.abs().get_val()); | ||
|  | ||
| if (LIBC_UNLIKELY(x_abs == 1.0)) { | ||
| return signed_result(0.25); | ||
| } | ||
|         
                  hulxv marked this conversation as resolved.
              Outdated
          
            Show resolved
            Hide resolved | ||
|  | ||
| // polynomial coefficients for atan(x)/pi taylor series | ||
| // generated using sympy: series(atan(x)/pi, x, 0, 17) | ||
| constexpr double POLY_COEFFS[] = { | ||
| 0x1.45f306dc9c889p-2, // x^1: 1/pi | ||
| -0x1.b2995e7b7b60bp-4, // x^3: -1/(3*pi) | ||
| 0x1.04c26be3b06ccp-4, // x^5: 1/(5*pi) | ||
| -0x1.7483758e69c08p-5, // x^7: -1/(7*pi) | ||
| 0x1.21bb945252403p-5, // x^9: 1/(9*pi) | ||
| -0x1.da1bace3cc68ep-6, // x^11: -1/(11*pi) | ||
| 0x1.912b1c2336cf2p-6, // x^13: 1/(13*pi) | ||
| -0x1.5bade52f95e7p-6, // x^15: -1/(15*pi) | ||
| }; | ||
|         
                  hulxv marked this conversation as resolved.
              Outdated
          
            Show resolved
            Hide resolved | ||
|  | ||
| // evaluate atan(x)/pi using polynomial approximation, valid for |x| <= 0.5 | ||
| constexpr auto atanpi_eval = [](double x) -> double { | ||
| double xx = x * x; | ||
|         
                  hulxv marked this conversation as resolved.
              Outdated
          
            Show resolved
            Hide resolved | ||
| return x * fputil::polyeval(xx, POLY_COEFFS[0], POLY_COEFFS[1], | ||
| POLY_COEFFS[2], POLY_COEFFS[3], POLY_COEFFS[4], | ||
| POLY_COEFFS[5], POLY_COEFFS[6], POLY_COEFFS[7]); | ||
| }; | ||
|  | ||
| // Case 1: |x| <= 0.5 - Direct polynomial evaluation | ||
| if (LIBC_LIKELY(x_abs <= 0.5)) { | ||
| double result = atanpi_eval(x_abs); | ||
| return signed_result(result); | ||
| } | ||
|  | ||
| // case 2: 0.5 < |x| <= 1 - use double-angle reduction | ||
| // atan(x) = 2 * atan(x / (1 + sqrt(1 + x^2))) | ||
| // so atanpi(x) = 2 * atanpi(x') where x' = x / (1 + sqrt(1 + x^2)) | ||
| if (x_abs <= 1.0) { | ||
| double x2 = x_abs * x_abs; | ||
|         
                  hulxv marked this conversation as resolved.
              Outdated
          
            Show resolved
            Hide resolved | ||
| double sqrt_term = fputil::sqrt<double>(1.0 + x2); | ||
| double x_prime = x_abs / (1.0 + sqrt_term); | ||
| double result = 2.0 * atanpi_eval(x_prime); | ||
| return signed_result(result); | ||
| } | ||
|  | ||
| // case 3: |x| > 1 - use reciprocal transformation | ||
| // atan(x) = pi/2 - atan(1/x) for x > 0 | ||
| // so atanpi(x) = 1/2 - atanpi(1/x) | ||
| double x_recip = 1.0 / x_abs; | ||
| double result; | ||
|  | ||
| // if 1/|x| > 0.5, we need to apply Case 2 transformation to 1/|x| | ||
| if (x_recip > 0.5) { | ||
| double xx_recip = x_recip * x_recip; | ||
| double sqrt_term = fputil::sqrt<double>(1.0 + xx_recip); | ||
| double x_prime = x_recip / (1.0 + sqrt_term); | ||
| result = fputil::multiply_add(-2.0, atanpi_eval(x_prime), 0.5); | ||
| } else { | ||
| // direct evaluation since 1/|x| <= 0.5 | ||
| result = 0.5 - atanpi_eval(x_recip); | ||
| } | ||
|  | ||
| return signed_result(result); | ||
| } | ||
|  | ||
| } // namespace LIBC_NAMESPACE_DECL | ||
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| //===-- Exhaustive test for atanpif16 -------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|  | ||
| #include "src/math/atanpif16.h" | ||
| #include "test/UnitTest/FPMatcher.h" | ||
| #include "test/UnitTest/Test.h" | ||
| #include "utils/MPFRWrapper/MPFRUtils.h" | ||
|  | ||
| using LlvmLibcAtanpif16Test = LIBC_NAMESPACE::testing::FPTest<float16>; | ||
|  | ||
| namespace mpfr = LIBC_NAMESPACE::testing::mpfr; | ||
|  | ||
| // Range: [0, Inf] | ||
| static constexpr uint16_t POS_START = 0x0000U; | ||
| static constexpr uint16_t POS_STOP = 0x7c00U; | ||
|  | ||
| // Range: [-Inf, 0] | ||
| static constexpr uint16_t NEG_START = 0x8000U; | ||
| static constexpr uint16_t NEG_STOP = 0xfc00U; | ||
|  | ||
| TEST_F(LlvmLibcAtanpif16Test, PositiveRange) { | ||
| for (uint16_t v = POS_START; v <= POS_STOP; ++v) { | ||
| float16 x = FPBits(v).get_val(); | ||
| EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Atanpi, x, | ||
| LIBC_NAMESPACE::atanpif16(x), 0.5); | ||
| } | ||
| } | ||
|  | ||
| TEST_F(LlvmLibcAtanpif16Test, NegativeRange) { | ||
| for (uint16_t v = NEG_START; v <= NEG_STOP; ++v) { | ||
| float16 x = FPBits(v).get_val(); | ||
| EXPECT_MPFR_MATCH_ALL_ROUNDING(mpfr::Operation::Atanpi, x, | ||
| LIBC_NAMESPACE::atanpif16(x), 0.5); | ||
| } | ||
| } | ||
|  | 
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
              
              | Original file line number | Diff line number | Diff line change | 
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| //===-- Unittests for atanpif16 -------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|  | ||
| #include "src/errno/libc_errno.h" | ||
| #include "src/math/atanpif16.h" | ||
| #include "test/UnitTest/FPMatcher.h" | ||
|  | ||
| using LlvmLibcAtanpif16Test = LIBC_NAMESPACE::testing::FPTest<float16>; | ||
|  | ||
| TEST_F(LlvmLibcAtanpif16Test, SpecialNumbers) { | ||
| // zero | ||
| EXPECT_FP_EQ(zero, LIBC_NAMESPACE::atanpif16(zero)); | ||
| EXPECT_FP_EQ(neg_zero, LIBC_NAMESPACE::atanpif16(neg_zero)); | ||
|  | ||
| // NaN inputs | ||
| EXPECT_FP_EQ(FPBits::quiet_nan().get_val(), | ||
| LIBC_NAMESPACE::atanpif16(FPBits::quiet_nan().get_val())); | ||
|         
                  hulxv marked this conversation as resolved.
              Show resolved
            Hide resolved | ||
|  | ||
| EXPECT_FP_EQ(FPBits::quiet_nan().get_val(), | ||
| LIBC_NAMESPACE::atanpif16(FPBits::signaling_nan().get_val())); | ||
|         
                  hulxv marked this conversation as resolved.
              Outdated
          
            Show resolved
            Hide resolved | ||
|  | ||
| // infinity inputs -> should return +/-0.5 | ||
| EXPECT_FP_EQ(0.5f16, LIBC_NAMESPACE::atanpif16(inf)); | ||
| EXPECT_FP_EQ(-0.5f16, LIBC_NAMESPACE::atanpif16(neg_inf)); | ||
| } | ||
|  | ||
| TEST_F(LlvmLibcAtanpif16Test, SymmetryProperty) { | ||
| // Test that atanpi(-x) = -atanpi(x) | ||
| constexpr float16 TEST_VALS[] = {0.1f16, 0.25f16, 0.5f16, 0.75f16, | ||
|         
                  hulxv marked this conversation as resolved.
              Outdated
          
            Show resolved
            Hide resolved | ||
| 1.0f16, 1.5f16, 2.0f16, 5.0f16, | ||
| 10.0f16, 50.0f16, 100.0f16, 1000.0f16}; | ||
|  | ||
| for (float16 x : TEST_VALS) { | ||
| FPBits neg_x_bits(x); | ||
| neg_x_bits.set_sign(Sign::NEG); | ||
| float16 neg_x = neg_x_bits.get_val(); | ||
|  | ||
| float16 pos_result = LIBC_NAMESPACE::atanpif16(x); | ||
| float16 neg_result = LIBC_NAMESPACE::atanpif16(neg_x); | ||
|  | ||
| EXPECT_FP_EQ(pos_result, FPBits(neg_result).abs().get_val()); | ||
| } | ||
| } | ||
|  | ||
| TEST_F(LlvmLibcAtanpif16Test, MonotonicityProperty) { | ||
| // Test that atanpi is monotonically increasing | ||
| constexpr float16 TEST_VALS[] = {-1000.0f16, -100.0f16, -10.0f16, -2.0f16, | ||
| -1.0f16, -0.5f16, -0.1f16, 0.0f16, | ||
| 0.1f16, 0.5f16, 1.0f16, 2.0f16, | ||
| 10.0f16, 100.0f16, 1000.0f16}; | ||
|  | ||
| for (size_t i = 0; i < sizeof(TEST_VALS) / sizeof(TEST_VALS[0]) - 1; ++i) { | ||
|         
                  hulxv marked this conversation as resolved.
              Outdated
          
            Show resolved
            Hide resolved | ||
| float16 x1 = TEST_VALS[i]; | ||
| float16 x2 = TEST_VALS[i + 1]; | ||
| float16 result1 = LIBC_NAMESPACE::atanpif16(x1); | ||
| float16 result2 = LIBC_NAMESPACE::atanpif16(x2); | ||
|  | ||
| EXPECT_TRUE(result1 < result2); | ||
| } | ||
| } | ||
|  | ||
      
      Oops, something went wrong.
        
    
  
      
      Oops, something went wrong.
        
    
  
  Add this suggestion to a batch that can be applied as a single commit.
  This suggestion is invalid because no changes were made to the code.
  Suggestions cannot be applied while the pull request is closed.
  Suggestions cannot be applied while viewing a subset of changes.
  Only one suggestion per line can be applied in a batch.
  Add this suggestion to a batch that can be applied as a single commit.
  Applying suggestions on deleted lines is not supported.
  You must change the existing code in this line in order to create a valid suggestion.
  Outdated suggestions cannot be applied.
  This suggestion has been applied or marked resolved.
  Suggestions cannot be applied from pending reviews.
  Suggestions cannot be applied on multi-line comments.
  Suggestions cannot be applied while the pull request is queued to merge.
  Suggestion cannot be applied right now. Please check back later.
  
    
  
    
Uh oh!
There was an error while loading. Please reload this page.