gsl_ieee-utils__make_rep.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /* ieee-utils/make_rep.c
  2. *
  3. * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 Brian Gough
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 3 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. * General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18. */
  19. #include "gsl__config.h"
  20. #include "gsl_ieee_utils.h"
  21. #include "gsl_ieee-utils__endian.c"
  22. #include "gsl_ieee-utils__standardize.c"
  23. static void sprint_nybble(int i, char *s) ;
  24. static void sprint_byte(int i, char *s) ;
  25. static int determine_ieee_type (int non_zero, int exponent, int max_exponent);
  26. /* For the IEEE float format the bits are found from the following
  27. masks,
  28. sign = 0x80000000
  29. exponent = 0x7f800000
  30. mantisssa = 0x007fffff
  31. For the IEEE double format the masks are,
  32. sign = 0x8000000000000000
  33. exponent = 0x7ff0000000000000
  34. mantissa = 0x000fffffffffffff
  35. */
  36. void
  37. gsl_ieee_float_to_rep (const float * x, gsl_ieee_float_rep * r)
  38. {
  39. int e, non_zero;
  40. union {
  41. float f;
  42. struct {
  43. unsigned char byte[4] ;
  44. } ieee ;
  45. } u;
  46. u.f = *x ;
  47. if (little_endian_p())
  48. make_float_bigendian(&(u.f)) ;
  49. /* note that r->sign is signed, u.ieee.byte is unsigned */
  50. if (u.ieee.byte[3]>>7)
  51. {
  52. r->sign = 1 ;
  53. }
  54. else
  55. {
  56. r->sign = 0 ;
  57. }
  58. e = (u.ieee.byte[3] & 0x7f) << 1 | (u.ieee.byte[2] & 0x80)>>7 ;
  59. r->exponent = e - 127 ;
  60. sprint_byte((u.ieee.byte[2] & 0x7f) << 1,r->mantissa) ;
  61. sprint_byte(u.ieee.byte[1],r->mantissa + 7) ;
  62. sprint_byte(u.ieee.byte[0],r->mantissa + 15) ;
  63. r->mantissa[23] = '\0' ;
  64. non_zero = u.ieee.byte[0] || u.ieee.byte[1] || (u.ieee.byte[2] & 0x7f);
  65. r->type = determine_ieee_type (non_zero, e, 255) ;
  66. }
  67. void
  68. gsl_ieee_double_to_rep (const double * x, gsl_ieee_double_rep * r)
  69. {
  70. int e, non_zero;
  71. union
  72. {
  73. double d;
  74. struct {
  75. unsigned char byte[8];
  76. } ieee ;
  77. } u;
  78. u.d= *x ;
  79. if (little_endian_p())
  80. make_double_bigendian(&(u.d)) ;
  81. /* note that r->sign is signed, u.ieee.byte is unsigned */
  82. if (u.ieee.byte[7]>>7)
  83. {
  84. r->sign = 1 ;
  85. }
  86. else
  87. {
  88. r->sign = 0 ;
  89. }
  90. e =(u.ieee.byte[7] & 0x7f)<<4 ^ (u.ieee.byte[6] & 0xf0)>>4 ;
  91. r->exponent = e - 1023 ;
  92. sprint_nybble(u.ieee.byte[6],r->mantissa) ;
  93. sprint_byte(u.ieee.byte[5],r->mantissa + 4) ;
  94. sprint_byte(u.ieee.byte[4],r->mantissa + 12) ;
  95. sprint_byte(u.ieee.byte[3],r->mantissa + 20) ;
  96. sprint_byte(u.ieee.byte[2],r->mantissa + 28) ;
  97. sprint_byte(u.ieee.byte[1],r->mantissa + 36) ;
  98. sprint_byte(u.ieee.byte[0],r->mantissa + 44) ;
  99. r->mantissa[52] = '\0' ;
  100. non_zero = (u.ieee.byte[0] || u.ieee.byte[1] || u.ieee.byte[2]
  101. || u.ieee.byte[3] || u.ieee.byte[4] || u.ieee.byte[5]
  102. || (u.ieee.byte[6] & 0x0f)) ;
  103. r->type = determine_ieee_type (non_zero, e, 2047) ;
  104. }
  105. /* A table of character representations of nybbles */
  106. static char nybble[16][5]={ /* include space for the \0 */
  107. "0000", "0001", "0010", "0011",
  108. "0100", "0101", "0110", "0111",
  109. "1000", "1001", "1010", "1011",
  110. "1100", "1101", "1110", "1111"
  111. } ;
  112. static void
  113. sprint_nybble(int i, char *s)
  114. {
  115. char *c ;
  116. c=nybble[i & 0x0f ];
  117. *s=c[0] ; *(s+1)=c[1] ; *(s+2)=c[2] ; *(s+3)=c[3] ;
  118. }
  119. static void
  120. sprint_byte(int i, char *s)
  121. {
  122. char *c ;
  123. c=nybble[(i & 0xf0)>>4];
  124. *s=c[0] ; *(s+1)=c[1] ; *(s+2)=c[2] ; *(s+3)=c[3] ;
  125. c=nybble[i & 0x0f];
  126. *(s+4)=c[0] ; *(s+5)=c[1] ; *(s+6)=c[2] ; *(s+7)=c[3] ;
  127. }
  128. static int
  129. determine_ieee_type (int non_zero, int exponent, int max_exponent)
  130. {
  131. if (exponent == max_exponent)
  132. {
  133. if (non_zero)
  134. {
  135. return GSL_IEEE_TYPE_NAN ;
  136. }
  137. else
  138. {
  139. return GSL_IEEE_TYPE_INF ;
  140. }
  141. }
  142. else if (exponent == 0)
  143. {
  144. if (non_zero)
  145. {
  146. return GSL_IEEE_TYPE_DENORMAL ;
  147. }
  148. else
  149. {
  150. return GSL_IEEE_TYPE_ZERO ;
  151. }
  152. }
  153. else
  154. {
  155. return GSL_IEEE_TYPE_NORMAL ;
  156. }
  157. }