prob_distr_mpfr_ref.c 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. /* Copyright 2012-2019, The Tor Project, Inc
  2. * See LICENSE for licensing information */
  3. /** prob_distr_mpfr_ref.c
  4. *
  5. * Example reference file for GNU MPFR vectors tested in test_prob_distr.c .
  6. * Code by Riastradh.
  7. */
  8. #include <complex.h>
  9. #include <float.h>
  10. #include <math.h>
  11. #include <stdio.h>
  12. /* Must come after <stdio.h> so we get mpfr_printf. */
  13. #include <mpfr.h>
  14. /* gcc -o mpfr prob_distr_mpfr_ref.c -lmpfr -lm */
  15. /* Computes logit(p) for p = .49999 */
  16. int
  17. main(void)
  18. {
  19. mpfr_t p, q, r;
  20. mpfr_init(p);
  21. mpfr_set_prec(p, 200);
  22. mpfr_init(q);
  23. mpfr_set_prec(q, 200);
  24. mpfr_init(r);
  25. mpfr_set_prec(r, 200);
  26. mpfr_set_d(p, .49999, MPFR_RNDN);
  27. mpfr_set_d(q, 1, MPFR_RNDN);
  28. /* r := q - p = 1 - p */
  29. mpfr_sub(r, q, p, MPFR_RNDN);
  30. /* q := p/r = p/(1 - p) */
  31. mpfr_div(q, p, r, MPFR_RNDN);
  32. /* r := log(q) = log(p/(1 - p)) */
  33. mpfr_log(r, q, MPFR_RNDN);
  34. mpfr_printf("mpfr 200-bit\t%.128Rg\n", r);
  35. /*
  36. * Print a double approximation to logit three different ways. All
  37. * three agree bit for bit on the libms I tried, with the nextafter
  38. * adjustment (which is well within the 10 eps relative error bound
  39. * advertised). Apparently I must have used the Goldberg expression
  40. * for what I wrote down in the test case.
  41. */
  42. printf("mpfr 53-bit\t%.17g\n", nextafter(mpfr_get_d(r, MPFR_RNDN), 0), 0);
  43. volatile double p0 = .49999;
  44. printf("log1p\t\t%.17g\n", nextafter(-log1p((1 - 2*p0)/p0), 0));
  45. volatile double x = (1 - 2*p0)/p0;
  46. volatile double xp1 = x + 1;
  47. printf("Goldberg\t%.17g\n", -x*log(xp1)/(xp1 - 1));
  48. /*
  49. * Print a bad approximation, using the naive expression, to see a
  50. * lot of wrong digits, far beyond the 10 eps relative error attained
  51. * by -log1p((1 - 2*p)/p).
  52. */
  53. printf("naive\t\t%.17g\n", log(p0/(1 - p0)));
  54. fflush(stdout);
  55. return ferror(stdout);
  56. }