weixin_40001924
weixin_40001924
2020-11-24 15:08

C11 compilation

This PR fixes compilation with gcc with -std=c11 option. Tested on Ubuntu 16.10.

该提问来源于开源项目:OSGeo/PROJ

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

7条回答

  • weixin_39709979 weixin_39709979 5月前

    As you can imagine, changing the definition of mathematical constants for a coordinate system projection library is a BIG DEAL.

    Can you provide more background on why these changes are needed and what the actual errors are with -std=c11

    点赞 评论 复制链接分享
  • weixin_39861955 weixin_39861955 5月前

    Yes, it's a big deal. But!!!, I was sorry to see that the last digits given for the value of M_PI were wrong. Probably the old and new constants become the same double precision value. This should be checked.

    点赞 评论 复制链接分享
  • weixin_39825854 weixin_39825854 5月前

    Here's the commit where I took the PI out and converted to using M_PI: 3043b2f7fcf4471983c8d4472b17ccf9df1710c8

    This consequently made it so that some compilers were using more precise compiler defaults for M_PI. These lines were removed:

    C
    -#define HALFPI     1.5707963267948966
    -#define FORTPI     0.78539816339744833
    -#define PI     3.14159265358979323846
    

    Here's the commit that added M_PI back in for ANSI mode compilation: 196a1bb848dbd8f080d8ad6769f478c17c96d409

    The lines added:

    C
    #ifndef M_PI
    #define M_PI            3.14159265358979310
    #define M_PI_2          1.57079632679489660
    #define M_PI_4          0.78539816339744828
    #endif
    

    This is what is in my math.h on my Ubuntu Linux machine gcc 4.8.4, which are identical to the values submitted in this PR.

    C
    # define M_PI           3.14159265358979323846  /* pi */
    # define M_PI_2         1.57079632679489661923  /* pi/2 */
    # define M_PI_4         0.78539816339744830962  /* pi/4 */
    

    These could cause some problem for testing between platforms. Good catch. (Yuck.)

    点赞 评论 复制链接分享
  • weixin_40001924 weixin_40001924 5月前

    When compiling with strict C option (-ansi, -std=c11,...) mathematical constants are not defined. This is partially addressed in the current code for M_PI, M_PI_2, M_PI_4 but M_2_PI and M_SQRT2 are missing.

    In addition, the constants were not defined with enough accuracy. Mathematical constants are usually defined with at least 20 digits precision so they can be assigned to long double without losing any accuracy. I also noticed the existing constants had some wrong digits. This could potentially cause some regression.

    点赞 评论 复制链接分享
  • weixin_40001924 weixin_40001924 5月前

    Both versions of M_PI give the same value when assigned to a double, on MacOS Sierra with clang Apple LLVM version 8.0.0 (clang-800.0.42.1). So the change should not introduce any regression.

    Here is the test code:

    include

    define M_PI_OLD 3.14159265358979310

    define M_PI_NEW 3.14159265358979323846

    double old_pi = M_PI_OLD; double new_pi = M_PI_NEW; long double old_pi_ld = M_PI_OLD; long double new_pi_ld = M_PI_NEW; int main() { printf("Old: %.24f\n", old_pi); printf("New: %.24f\n", new_pi); printf("Old ld: %.24Lf\n", old_pi_ld); printf("New ld: %.24Lf\n", new_pi_ld); return 0; }

    However, the long double variable didn't show the increased accuracy.

    点赞 评论 复制链接分享
  • weixin_39854440 weixin_39854440 5月前

    It seems to be me who introduced the bad pi definition. I did a little digging around to find out where I got the value from. I think I must have written a small program and printed out the value of M_PI. At first that sounds a bit off, but this small program confirms my suspecion:

    C
    #include <stdio.h>
    #include <math.h>
    
    int main() {
        double pi1 = 3.14159265358979310;
        double pi2 = 3.14159265358979323846;
    
        printf("%1.20f\n", pi1);
        printf("%1.20f\n", pi2);
        printf("%1.20f\n", M_PI);
    
        return 0;
    }
    </math.h></stdio.h>

    The results are

    
    C:\dev\misc>gcc float_test.c -o float_test.exe && float_test.exe
    3.14159265358979310000
    3.14159265358979310000
    3.14159265358979310000
    

    So I guess that's the closest we can get to true pi with double precision floating point represention. At least on my computer, but I expect similar results on other systems as well. It also agrees with results above.

    I am in favour of changing the constants in the source code to the proper PI values, even though it probably wont change anything.

    点赞 评论 复制链接分享
  • weixin_39861955 weixin_39861955 5月前

    Agreed. By the way, a good way to detect small discrepancies in the value of pi is to print out its sine. With IEEE double precision you should exact(pi) - rounded(pi) = 1.22e-16.

    点赞 评论 复制链接分享

相关推荐