/*----------------------------------------------------------------------------- * * cvtibmf.c : IBM float/double <-> IEEE float/double conversion * *+++ * * Copyright (c) Software AG 1996,1998. All rights reserved. * *--- * * License: * * "According to the DCOM Porting Agreement Software AG grants to Microsoft * an irrevocable, unlimited, royalty free license to use and market the * enclosed piece of software code in source and object format for * the purposes of Microsoft. 17-April-1998." * *----------------------------------------------------------------------------*/ #include #include #include #include "winerror.h" /* * Convert floating point numbers from IBM/370 to IEEE representation or vice versa. * * Synopsis: * * void cvt_ibm_f_to_ieee_single(ULONG *ulFP); * void cvt_ibm_d_to_ieee_double(ULONG *ulFP); * void cvt_ieee_single_to_ibm_f(ULONG *ulFP); * void cvt_ieee_double_to_ibm_d(ULONG *ulFP); * * Note: * * Overflow/Underflow during conversion results in RpcRaiseException(RPC_S_FP_OVERFLOW/ * RPC_S_FP_UNDERFLOW). * */ /* ******************************************************************************* * * Floating point representations: * * ------------------------ * IBM/370 single precision * ------------------------ * * xxxx.xxxx xxxx.xxxx xxxx.xxxx xxxx.xxxx * s|-exp--| |--------fraction-----------| * (7) (24) * * value = (-1)**s * 16**(e - 64) * .f range = 5.4E-79 ... 7.2E+75 * * ******************************************************************************* * * --------------------- * IEEE single precision * --------------------- * * xxxx.xxxx xxxx.xxxx xxxx.xxxx xxxx.xxxx * s|--exp---||-------fraction-----------| * (8) (23) * * value = (-1)**s * 2**(e - 127) * 1.f range = 1.2E-38 ... 3.4E+38 * * ******************************************************************************* * * ------------------------ * IBM/370 double precision * ------------------------ * * xxxx.xxxx xxxx.xxxx xxxx.xxxx xxxx.xxxx yyyy.yyyy yyyy.yyyy yyyy.yyyy yyyy.yyyy * s|-exp--| |-------------------------------fraction----------------------------| * (7) (56) * * value = (-1)**s * 16**(e - 64) * .f range = 5.4E-79 ... 7.2E+75 * * ******************************************************************************* * * --------------------- * IEEE double precision * --------------------- * * xxxx.xxxx xxxx.xxxx xxxx.xxxx xxxx.xxxx yyyy.yyyy yyyy.yyyy yyyy.yyyy yyyy.yyyy * s|--exponent-| |-------------------------fraction-----------------------------| * (11) (52) * * value = (-1)**s * 2**(e - 1023) * 1.f range = 2.2E-308 ... 1.8+308 * * *******************************************************************************/ #if 1 /* We assume little endian for NT, this does not work: NDR_LOCAL_ENDIAN == NDR_LITTLE_ENDIAN */ # define HI 1 /* index of high order LONG */ # define LO 0 /* index of low order LONG */ #else # define HI 0 /* index of high order LONG */ # define LO 1 /* index of low order LONG */ #endif static float floatMin = FLT_MIN; static float floatMax = FLT_MAX; #define SIGN(src) (src[HI] & 0x80000000) /* Convert IBM/370 "float" to IEEE "single" */ void cvt_ibm_f_to_ieee_single ( ULONG *ulFP ) { ULONG ulFraction ; LONG lExponent ; /* in this special case we just keep the sign */ if ( ( *ulFP & 0x7fffffff ) == 0 ) { return ; } /* fetch the exponent (excess-64 notation) and fraction */ lExponent = ( (*ulFP & 0x7f000000) >> 24) - 64 ; ulFraction = *ulFP & 0x00ffffff ; /* convert from "16**exponent" to "2**exponent" */ if ( lExponent >= 0 ) lExponent <<= 2 ; else lExponent = -((-lExponent) << 2) ; /* convert exponent for 24 bit fraction to 23 bit fraction */ lExponent -= 1; /* normalize fraction */ if ( ulFraction ) { while ( (ulFraction & 0x00800000) == 0 ) { ulFraction <<= 1 ; lExponent -= 1 ; } } /* remove the implied '1' preceeding the binary point */ ulFraction &= 0x007fffff ; /* convert exponent to excess-127 notation and store the number if the exponent is not out of range */ if ( (lExponent += 127) >= 255 ) *ulFP = SIGN(ulFP) | *((ULONG *)&floatMax) ; /* floating overflow */ else if ( lExponent <= 0 ) *ulFP = SIGN(ulFP) | *((ULONG *)&floatMin) ; /* floating underflow */ else *ulFP = SIGN(ulFP) | (lExponent << 23) | ulFraction ; } /* Convert IBM/370 "double" to IEEE "double" */ void cvt_ibm_d_to_ieee_double ( ULONG* ulFP ) { ULONG ulFraction[2] ; LONG lExponent ; /* in this special case we just keep the sign */ if ( (ulFP[HI] & 0x7fffffff) == 0 ) { return ; } /* fetch the exponent (removing excess 64) and fraction */ lExponent = ( (ulFP[HI] & 0x7f000000) >> 24 ) - 64 ; ulFraction[HI] = ulFP[HI] & 0x00ffffff ; ulFraction[LO] = ulFP[LO] ; /* convert from "16**exponent" to "2**exponent" */ if ( lExponent >= 0 ) lExponent <<= 2 ; else lExponent = -((-lExponent) << 2); /* normalize the fraction (to 57 bits) */ if ( ulFraction[HI] ) { while ((ulFraction[HI] & 0x01000000) == 0) { ulFraction[HI] = ( ulFraction[HI] << 1 ) | ( ulFraction[LO] >> 31 ) ; ulFraction[LO] = ulFraction[LO] << 1 ; lExponent -= 1 ; } } /* convert 57 bit fraction to 53 bit fraction and remove the implied '1' preceeding the binary point */ ulFraction[LO] = ( ulFraction[LO] >> 4 ) | ( ulFraction[HI] << 28 ) ; ulFraction[HI] = ( ulFraction[HI] >> 4 ) & 0x000fffff ; /* convert exponent to excess-1023 notation and store the number if the exponent is not out of range */ if ( (lExponent += 1023) >= 2047 ) RpcRaiseException ( RPC_S_FP_OVERFLOW ) ; /* should never happen */ else if ( lExponent <= 0 ) RpcRaiseException ( RPC_S_FP_UNDERFLOW ) ; /* should never happen */ else { ulFP[HI] = SIGN(ulFP) | (lExponent << 20) | ulFraction[HI] ; ulFP[LO] = ulFraction[LO] ; } } /* The following is not used in Windows NT */ #if 0 /* Convert IEEE "single" to IBM/370 "float" */ void cvt_ieee_single_to_ibm_f ( ULONG* ulFP ) { ULONG ulFraction ; LONG lExponent ; /* in this special case we just keep the sign */ if ( (*ulFP & 0x7fffffff) == 0 ) { return ; } lExponent = ((*ulFP & 0x7f800000) >> 23) - 127 ; ulFraction = *ulFP & 0x007fffff ; /* convert 23 bit fraction to 24 bit fraction */ ulFraction <<= 1 ; /* restore the implied '1' which preceeded the IEEE binary point */ ulFraction |= 0x01000000 ; /* convert from "2**exponent" to "16**exponent" (fraction is not normalized) */ if ( lExponent >= 0 ) { ulFraction <<= (lExponent & 3) ; lExponent >>= 2 ; } else { ulFraction >>= ((-lExponent) & 3) ; lExponent = -((-lExponent) >> 2) ; } /* reduce fraction to 24 bits or less */ if ( ulFraction & 0x0f000000 ) { ulFraction >>= 4 ; lExponent += 1 ; } /* convert exponent to excess-64 notation and store the number if the exponent is not out of range */ if ( (lExponent += 64) > 127 ) RpcRaiseException ( RPC_S_FP_OVERFLOW ) ; /* should never happen */ else if ( lExponent < 0 ) RpcRaiseException ( RPC_S_FP_UNDERFLOW ) ; /* should never happen */ else *ulFP = SIGN(ulFP) | (lExponent << 24) | ulFraction ; } /* Convert IEEE "double" to IBM/370 "double" */ void cvt_ieee_double_to_ibm_d ( ULONG* ulFP ) { ULONG ulFraction[2] ; LONG lExponent ; LONG shift ; /* in this special case we just keep the sign and the low word */ if ( (ulFP[HI] & 0x7fffffff) == 0 ) { return ; } /* fetch the exponent (excess-1023 notation) and fraction */ lExponent = ((ulFP[HI] & 0x7ff00000) >> 20) - 1023 ; ulFraction[HI] = ulFP[HI] & 0x000fffff ; ulFraction[LO] = ulFP[LO] ; /* convert 52 bit fraction to 56 bit fraction and restore the '1' which preceeds the IEEE binary point*/ ulFraction[HI] = ( ulFraction[HI] << 4 ) | ( ulFraction[LO] >> 28 ) | 0x01000000 ; ulFraction[LO] = ulFraction[LO] << 4 ; /* convert from "2**exponent" to "16**exponent" (fraction is not normalized) */ if ( lExponent >= 0 ) { shift = lExponent & 3 ; ulFraction[HI] = ( ulFraction[HI] << shift ) | ( ulFraction[LO] >> (32 - shift) ) ; ulFraction[LO] = ulFraction[LO] << shift ; lExponent >>= 2 ; } else { shift = (-lExponent) & 3 ; ulFraction[LO] = ( ulFraction[LO] >> shift ) | ( ulFraction[HI] << (32 - shift) ) ; ulFraction[HI] = ( ulFraction[HI] >> shift ) ; lExponent = -((-lExponent) >> 2) ; } /* reduce fraction to 56 bits or less */ if ( ulFraction[HI] & 0x0f000000 ) { ulFraction[LO] = ( ulFraction[LO] >> 4 ) | ( ulFraction[HI] << 28 ) ; ulFraction[HI] = ( ulFraction[HI] >> 4 ) ; lExponent += 1 ; } /* convert exponent to excess-64 notation and store the number */ if ( (lExponent += 64) > 127 ) { /* we store the highest IBM float but we keep the sign ! */ ulFP[HI] = SIGN(ulFP) | 0x7FFFFFFF ; ulFP[LO] = 0xFFFFFFFF ; } else if ( lExponent < 0 ) { /* we store 0 but we keep the sign ! */ ulFP[HI] = SIGN(ulFP) ; ulFP[LO] = 0 ; } else { ulFP[HI] = SIGN(ulFP) | (lExponent << 24) | ulFraction[HI] ; ulFP[LO] = ulFraction[LO] ; } } #endif