Advertisement
Guest User

Untitled

a guest
Jun 27th, 2017
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.36 KB | None | 0 0
  1. /* ibm2ieee - Converts a number from IBM 370 single precision floating
  2.  point format to IEEE 754 single precision format. For normalized
  3. numbers, the IBM format has greater range but less precision than the
  4. IEEE format. Numbers within the overlapping range are converted
  5. exactly. Numbers which are too large are converted to IEEE Infinity
  6. with the correct sign. Numbers which are too small are converted to
  7. IEEE denormalized numbers with a potential loss of precision (including
  8. complete loss of precision which results in zero with the correct
  9. sign). When precision is lost, rounding is toward zero (because it's
  10. fast and easy -- if someone really wants round to nearest it shouldn't
  11. be TOO difficult). */
  12.  
  13. /*
  14.  * https://bytes.com/topic/c/answers/221981-c-code-converting-ibm-370-floating-point-ieee-754-a
  15.  */
  16.  
  17. // [[Rcpp::export]]
  18. void ibm2ieee(void *to, const void *from, int len)
  19. {
  20.   unsigned fr; /* fraction */
  21.   int exp; /* exponent */
  22.   int sgn; /* sign */
  23.  
  24.   for (; len-- > 0; to = (char *)to + 4, from = (char *)from + 4) {
  25.     /* split into sign, exponent, and fraction */
  26.     /* eliminate conversion -- expect little endian */
  27.     fr = *(long *)from; /* pick up value */
  28.     sgn = fr >> 31; /* save sign */
  29.     fr <<= 1; /* shift sign out */
  30.     exp = fr >> 25; /* save exponent */
  31.     fr <<= 7; /* shift exponent out */
  32.    
  33.     if (fr == 0) { /* short-circuit for zero */
  34.     exp = 0;
  35.       goto done;
  36.     }
  37.    
  38.     /* adjust exponent from base 16 offset 64 radix point before first digit
  39.     to base 2 offset 127 radix point after first digit */
  40.     /* (exp - 64) * 4 + 127 - 1 == exp * 4 - 256 + 126 == (exp << 2) - 130 */
  41.     exp = (exp << 2) - 130;
  42.    
  43.     /* (re)normalize */
  44.     while (fr < 0x80000000) { /* 3 times max for normalized input */
  45.     --exp;
  46.       fr <<= 1;
  47.     }
  48.    
  49.     if (exp <= 0) { /* underflow */
  50.     if (exp < -24) /* complete underflow - return properly signed zero */
  51.     fr = 0;
  52.     else /* partial underflow - return denormalized number */
  53.     fr >>= -exp;
  54.     exp = 0;
  55.     } else if (exp >= 255) { /* overflow - return infinity */
  56.     fr = 0;
  57.       exp = 255;
  58.     } else { /* just a plain old number - remove the assumed high bit */
  59.     fr <<= 1;
  60.     }
  61.    
  62.     done:
  63.       /* put the pieces back together and return it */
  64.       *(unsigned *)to = (fr >> 9) | (exp << 23) | (sgn << 31);
  65.      
  66.   }
  67. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement