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 14 #include <iostream> 15 #include <iomanip> 16 #include <cmath> 17 #include <climits> 18 19 #include "config.h" 20 #include <qd/inline.h> 21 #include <qd/bits.h> 22 23 #ifdef HAVE_IEEEFP_H 24 #include <ieeefp.h> 25 #endif 26 27 using std::setw; 28 get_double_expn(double x)29int get_double_expn(double x) { 30 if (x == 0.0) 31 return INT_MIN; 32 if (QD_ISINF(x) || QD_ISNAN(x)) 33 return INT_MAX; 34 35 double y = std::abs(x); 36 int i = 0; 37 if (y < 1.0) { 38 while (y < 1.0) { 39 y *= 2.0; 40 i++; 41 } 42 return -i; 43 } else if (y >= 2.0) { 44 while (y >= 2.0) { 45 y *= 0.5; 46 i++; 47 } 48 return i; 49 } 50 return 0; 51 } 52 print_double_info(std::ostream & os,double x)53void print_double_info(std::ostream &os, double x) { 54 std::streamsize old_prec = os.precision(19); 55 std::ios_base::fmtflags old_flags = os.flags(); 56 os << std::scientific; 57 58 os << setw(27) << x << ' '; 59 if (QD_ISNAN(x) || QD_ISINF(x) || (x == 0.0)) { 60 os << " "; 61 } else { 62 63 x = std::abs(x); 64 int expn = get_double_expn(x); 65 double d = std::ldexp(1.0, expn); 66 os << setw(5) << expn << " "; 67 for (int i = 0; i < 53; i++) { 68 if (x >= d) { 69 x -= d; 70 os << '1'; 71 } else 72 os << '0'; 73 d *= 0.5; 74 } 75 76 if (x != 0.0) { 77 // should not happen 78 os << " +trailing stuff"; 79 } 80 } 81 82 os.precision(old_prec); 83 os.flags(old_flags); 84 } 85 86