Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

317 lines
9.4 KiB

  1. /*-----------------------------------------------------------------------------
  2. *
  3. * cvtibmf.c : IBM float/double <-> IEEE float/double conversion
  4. *
  5. *+++
  6. *
  7. * Copyright (c) Software AG 1996,1998. All rights reserved.
  8. *
  9. *---
  10. *
  11. * License:
  12. *
  13. * "According to the DCOM Porting Agreement Software AG grants to Microsoft
  14. * an irrevocable, unlimited, royalty free license to use and market the
  15. * enclosed piece of software code in source and object format for
  16. * the purposes of Microsoft. 17-April-1998."
  17. *
  18. *----------------------------------------------------------------------------*/
  19. #include <float.h>
  20. #include <rpc.h>
  21. #include <rpcndr.h>
  22. #include "winerror.h"
  23. /*
  24. * Convert floating point numbers from IBM/370 to IEEE representation or vice versa.
  25. *
  26. * Synopsis:
  27. *
  28. * void cvt_ibm_f_to_ieee_single(ULONG *ulFP);
  29. * void cvt_ibm_d_to_ieee_double(ULONG *ulFP);
  30. * void cvt_ieee_single_to_ibm_f(ULONG *ulFP);
  31. * void cvt_ieee_double_to_ibm_d(ULONG *ulFP);
  32. *
  33. * Note:
  34. *
  35. * Overflow/Underflow during conversion results in RpcRaiseException(RPC_S_FP_OVERFLOW/
  36. * RPC_S_FP_UNDERFLOW).
  37. *
  38. */
  39. /* *******************************************************************************
  40. *
  41. * Floating point representations:
  42. *
  43. * ------------------------
  44. * IBM/370 single precision
  45. * ------------------------
  46. *
  47. * xxxx.xxxx xxxx.xxxx xxxx.xxxx xxxx.xxxx
  48. * s|-exp--| |--------fraction-----------|
  49. * (7) (24)
  50. *
  51. * value = (-1)**s * 16**(e - 64) * .f range = 5.4E-79 ... 7.2E+75
  52. *
  53. * *******************************************************************************
  54. *
  55. * ---------------------
  56. * IEEE single precision
  57. * ---------------------
  58. *
  59. * xxxx.xxxx xxxx.xxxx xxxx.xxxx xxxx.xxxx
  60. * s|--exp---||-------fraction-----------|
  61. * (8) (23)
  62. *
  63. * value = (-1)**s * 2**(e - 127) * 1.f range = 1.2E-38 ... 3.4E+38
  64. *
  65. * *******************************************************************************
  66. *
  67. * ------------------------
  68. * IBM/370 double precision
  69. * ------------------------
  70. *
  71. * xxxx.xxxx xxxx.xxxx xxxx.xxxx xxxx.xxxx yyyy.yyyy yyyy.yyyy yyyy.yyyy yyyy.yyyy
  72. * s|-exp--| |-------------------------------fraction----------------------------|
  73. * (7) (56)
  74. *
  75. * value = (-1)**s * 16**(e - 64) * .f range = 5.4E-79 ... 7.2E+75
  76. *
  77. * *******************************************************************************
  78. *
  79. * ---------------------
  80. * IEEE double precision
  81. * ---------------------
  82. *
  83. * xxxx.xxxx xxxx.xxxx xxxx.xxxx xxxx.xxxx yyyy.yyyy yyyy.yyyy yyyy.yyyy yyyy.yyyy
  84. * s|--exponent-| |-------------------------fraction-----------------------------|
  85. * (11) (52)
  86. *
  87. * value = (-1)**s * 2**(e - 1023) * 1.f range = 2.2E-308 ... 1.8+308
  88. *
  89. * *******************************************************************************/
  90. #if 1 /* We assume little endian for NT, this does not work: NDR_LOCAL_ENDIAN == NDR_LITTLE_ENDIAN */
  91. # define HI 1 /* index of high order LONG */
  92. # define LO 0 /* index of low order LONG */
  93. #else
  94. # define HI 0 /* index of high order LONG */
  95. # define LO 1 /* index of low order LONG */
  96. #endif
  97. static float floatMin = FLT_MIN;
  98. static float floatMax = FLT_MAX;
  99. #define SIGN(src) (src[HI] & 0x80000000)
  100. /* Convert IBM/370 "float" to IEEE "single" */
  101. void cvt_ibm_f_to_ieee_single ( ULONG *ulFP )
  102. {
  103. ULONG ulFraction ;
  104. LONG lExponent ;
  105. /* in this special case we just keep the sign */
  106. if ( ( *ulFP & 0x7fffffff ) == 0 )
  107. {
  108. return ;
  109. }
  110. /* fetch the exponent (excess-64 notation) and fraction */
  111. lExponent = ( (*ulFP & 0x7f000000) >> 24) - 64 ;
  112. ulFraction = *ulFP & 0x00ffffff ;
  113. /* convert from "16**exponent" to "2**exponent" */
  114. if ( lExponent >= 0 ) lExponent <<= 2 ;
  115. else lExponent = -((-lExponent) << 2) ;
  116. /* convert exponent for 24 bit fraction to 23 bit fraction */
  117. lExponent -= 1;
  118. /* normalize fraction */
  119. if ( ulFraction )
  120. {
  121. while ( (ulFraction & 0x00800000) == 0 )
  122. {
  123. ulFraction <<= 1 ;
  124. lExponent -= 1 ;
  125. }
  126. }
  127. /* remove the implied '1' preceeding the binary point */
  128. ulFraction &= 0x007fffff ;
  129. /* convert exponent to excess-127 notation and store the number if the exponent is not out of range */
  130. if ( (lExponent += 127) >= 255 )
  131. *ulFP = SIGN(ulFP) | *((ULONG *)&floatMax) ; /* floating overflow */
  132. else if ( lExponent <= 0 )
  133. *ulFP = SIGN(ulFP) | *((ULONG *)&floatMin) ; /* floating underflow */
  134. else
  135. *ulFP = SIGN(ulFP) | (lExponent << 23) | ulFraction ;
  136. }
  137. /* Convert IBM/370 "double" to IEEE "double" */
  138. void cvt_ibm_d_to_ieee_double ( ULONG* ulFP )
  139. {
  140. ULONG ulFraction[2] ;
  141. LONG lExponent ;
  142. /* in this special case we just keep the sign */
  143. if ( (ulFP[HI] & 0x7fffffff) == 0 )
  144. {
  145. return ;
  146. }
  147. /* fetch the exponent (removing excess 64) and fraction */
  148. lExponent = ( (ulFP[HI] & 0x7f000000) >> 24 ) - 64 ;
  149. ulFraction[HI] = ulFP[HI] & 0x00ffffff ;
  150. ulFraction[LO] = ulFP[LO] ;
  151. /* convert from "16**exponent" to "2**exponent" */
  152. if ( lExponent >= 0 ) lExponent <<= 2 ;
  153. else lExponent = -((-lExponent) << 2);
  154. /* normalize the fraction (to 57 bits) */
  155. if ( ulFraction[HI] )
  156. {
  157. while ((ulFraction[HI] & 0x01000000) == 0)
  158. {
  159. ulFraction[HI] = ( ulFraction[HI] << 1 ) | ( ulFraction[LO] >> 31 ) ;
  160. ulFraction[LO] = ulFraction[LO] << 1 ;
  161. lExponent -= 1 ;
  162. }
  163. }
  164. /* convert 57 bit fraction to 53 bit fraction and remove the implied '1' preceeding the binary point */
  165. ulFraction[LO] = ( ulFraction[LO] >> 4 ) | ( ulFraction[HI] << 28 ) ;
  166. ulFraction[HI] = ( ulFraction[HI] >> 4 ) & 0x000fffff ;
  167. /* convert exponent to excess-1023 notation and store the number if the exponent is not out of range */
  168. if ( (lExponent += 1023) >= 2047 )
  169. RpcRaiseException ( RPC_S_FP_OVERFLOW ) ; /* should never happen */
  170. else if ( lExponent <= 0 )
  171. RpcRaiseException ( RPC_S_FP_UNDERFLOW ) ; /* should never happen */
  172. else
  173. {
  174. ulFP[HI] = SIGN(ulFP) | (lExponent << 20) | ulFraction[HI] ;
  175. ulFP[LO] = ulFraction[LO] ;
  176. }
  177. }
  178. /* The following is not used in Windows NT */
  179. #if 0
  180. /* Convert IEEE "single" to IBM/370 "float" */
  181. void cvt_ieee_single_to_ibm_f ( ULONG* ulFP )
  182. {
  183. ULONG ulFraction ;
  184. LONG lExponent ;
  185. /* in this special case we just keep the sign */
  186. if ( (*ulFP & 0x7fffffff) == 0 )
  187. {
  188. return ;
  189. }
  190. lExponent = ((*ulFP & 0x7f800000) >> 23) - 127 ;
  191. ulFraction = *ulFP & 0x007fffff ;
  192. /* convert 23 bit fraction to 24 bit fraction */
  193. ulFraction <<= 1 ;
  194. /* restore the implied '1' which preceeded the IEEE binary point */
  195. ulFraction |= 0x01000000 ;
  196. /* convert from "2**exponent" to "16**exponent" (fraction is not normalized) */
  197. if ( lExponent >= 0 )
  198. {
  199. ulFraction <<= (lExponent & 3) ;
  200. lExponent >>= 2 ;
  201. }
  202. else
  203. {
  204. ulFraction >>= ((-lExponent) & 3) ;
  205. lExponent = -((-lExponent) >> 2) ;
  206. }
  207. /* reduce fraction to 24 bits or less */
  208. if ( ulFraction & 0x0f000000 )
  209. {
  210. ulFraction >>= 4 ;
  211. lExponent += 1 ;
  212. }
  213. /* convert exponent to excess-64 notation and store the number if the exponent is not out of range */
  214. if ( (lExponent += 64) > 127 )
  215. RpcRaiseException ( RPC_S_FP_OVERFLOW ) ; /* should never happen */
  216. else if ( lExponent < 0 )
  217. RpcRaiseException ( RPC_S_FP_UNDERFLOW ) ; /* should never happen */
  218. else
  219. *ulFP = SIGN(ulFP) | (lExponent << 24) | ulFraction ;
  220. }
  221. /* Convert IEEE "double" to IBM/370 "double" */
  222. void cvt_ieee_double_to_ibm_d ( ULONG* ulFP )
  223. {
  224. ULONG ulFraction[2] ;
  225. LONG lExponent ;
  226. LONG shift ;
  227. /* in this special case we just keep the sign and the low word */
  228. if ( (ulFP[HI] & 0x7fffffff) == 0 )
  229. {
  230. return ;
  231. }
  232. /* fetch the exponent (excess-1023 notation) and fraction */
  233. lExponent = ((ulFP[HI] & 0x7ff00000) >> 20) - 1023 ;
  234. ulFraction[HI] = ulFP[HI] & 0x000fffff ;
  235. ulFraction[LO] = ulFP[LO] ;
  236. /* convert 52 bit fraction to 56 bit fraction and restore the '1' which preceeds the IEEE binary point*/
  237. ulFraction[HI] = ( ulFraction[HI] << 4 ) | ( ulFraction[LO] >> 28 ) | 0x01000000 ;
  238. ulFraction[LO] = ulFraction[LO] << 4 ;
  239. /* convert from "2**exponent" to "16**exponent" (fraction is not normalized) */
  240. if ( lExponent >= 0 )
  241. {
  242. shift = lExponent & 3 ;
  243. ulFraction[HI] = ( ulFraction[HI] << shift ) | ( ulFraction[LO] >> (32 - shift) ) ;
  244. ulFraction[LO] = ulFraction[LO] << shift ;
  245. lExponent >>= 2 ;
  246. }
  247. else
  248. {
  249. shift = (-lExponent) & 3 ;
  250. ulFraction[LO] = ( ulFraction[LO] >> shift ) | ( ulFraction[HI] << (32 - shift) ) ;
  251. ulFraction[HI] = ( ulFraction[HI] >> shift ) ;
  252. lExponent = -((-lExponent) >> 2) ;
  253. }
  254. /* reduce fraction to 56 bits or less */
  255. if ( ulFraction[HI] & 0x0f000000 )
  256. {
  257. ulFraction[LO] = ( ulFraction[LO] >> 4 ) | ( ulFraction[HI] << 28 ) ;
  258. ulFraction[HI] = ( ulFraction[HI] >> 4 ) ;
  259. lExponent += 1 ;
  260. }
  261. /* convert exponent to excess-64 notation and store the number */
  262. if ( (lExponent += 64) > 127 )
  263. { /* we store the highest IBM float but we keep the sign ! */
  264. ulFP[HI] = SIGN(ulFP) | 0x7FFFFFFF ;
  265. ulFP[LO] = 0xFFFFFFFF ;
  266. }
  267. else if ( lExponent < 0 )
  268. { /* we store 0 but we keep the sign ! */
  269. ulFP[HI] = SIGN(ulFP) ;
  270. ulFP[LO] = 0 ;
  271. }
  272. else
  273. {
  274. ulFP[HI] = SIGN(ulFP) | (lExponent << 24) | ulFraction[HI] ;
  275. ulFP[LO] = ulFraction[LO] ;
  276. }
  277. }
  278. #endif