bits.cpp 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. /*
  2. * src/bits.cc
  3. *
  4. * This work was supported by the Director, Office of Science, Division
  5. * of Mathematical, Information, and Computational Sciences of the
  6. * U.S. Department of Energy under contract number DE-AC03-76SF00098.
  7. *
  8. * Copyright (c) 2000-2001
  9. *
  10. * Defines various routines to get / set bits of a IEEE floating point
  11. * number. This used by the library for debugging purposes.
  12. */
  13. #include <iostream>
  14. #include <iomanip>
  15. #include <cmath>
  16. #include <climits>
  17. #include "config.h"
  18. #include <qd/inline.h>
  19. #include <qd/bits.h>
  20. #ifdef HAVE_IEEEFP_H
  21. #include <ieeefp.h>
  22. #endif
  23. using std::setw;
  24. int get_double_expn(double x) {
  25. if (x == 0.0)
  26. return INT_MIN;
  27. if (QD_ISINF(x) || QD_ISNAN(x))
  28. return INT_MAX;
  29. double y = std::abs(x);
  30. int i = 0;
  31. if (y < 1.0) {
  32. while (y < 1.0) {
  33. y *= 2.0;
  34. i++;
  35. }
  36. return -i;
  37. } else if (y >= 2.0) {
  38. while (y >= 2.0) {
  39. y *= 0.5;
  40. i++;
  41. }
  42. return i;
  43. }
  44. return 0;
  45. }
  46. void print_double_info(std::ostream &os, double x) {
  47. std::streamsize old_prec = os.precision(19);
  48. std::ios_base::fmtflags old_flags = os.flags();
  49. os << std::scientific;
  50. os << setw(27) << x << ' ';
  51. if (QD_ISNAN(x) || QD_ISINF(x) || (x == 0.0)) {
  52. os << " ";
  53. } else {
  54. x = std::abs(x);
  55. int expn = get_double_expn(x);
  56. double d = std::ldexp(1.0, expn);
  57. os << setw(5) << expn << " ";
  58. for (int i = 0; i < 53; i++) {
  59. if (x >= d) {
  60. x -= d;
  61. os << '1';
  62. } else
  63. os << '0';
  64. d *= 0.5;
  65. }
  66. if (x != 0.0) {
  67. // should not happen
  68. os << " +trailing stuff";
  69. }
  70. }
  71. os.precision(old_prec);
  72. os.flags(old_flags);
  73. }