Contributor: J.P. RITCHEY {=========================================================================== Date: 10-09-93 (23:23) From: J.P. Ritchey Subj: MSBIN to IEEE --------------------------------------------------------------------------- GE> Does anyone have any code for Converting MSBIN format GE> numbers into IEEE? } {$A-,B-,D-,E+,F-,I-,L-,N+,O-,R-,S-,V-} unit BFLOAT; (* MicroSoft Binary Float to IEEE format Conversion Copyright (c) 1989 J.P. Ritchey Version 1.0 This software is released to the public domain. Though tested, there could be some errors. Any reports of bugs discovered would be appreciated. Send reports to Pat Ritchey Compuserve ID 72537,2420 *) interface type bfloat4 = record { M'Soft single precision } mantissa : array[5..7] of byte; exponent : byte; end; Bfloat8 = record { M'Soft double precision } mantissa : array[1..7] of byte; exponent : byte; end; Function Bfloat4toExtended(d : bfloat4) : extended; Function Bfloat8toExtended(d : Bfloat8): extended; { These routines will convert a MicroSoft Binary Floating point number to IEEE extended format. The extended is large enough to store any M'Soft single or double number, so no over/underflow problems are encountered. The Mantissa of an extended is large enough to hold a BFloatx mantissa, so no truncation is required. The result can be returned to TP single and double variables and TP will handle the conversion. Note that Over/Underflow can occur with these types. } Function HexExt(ep:extended) : string; { A routine to return the hex representation of an IEEE extended variable Left in from debugging, you may find it useful } Function ExtendedtoBfloat4(ep : extended; var b : bfloat4) : boolean; Function ExtendedtoBfloat8(ep : extended; var b : Bfloat8) : boolean; { These routines are the reverse of the above, that is they convert TP extended => M'Soft format. You can use TP singles and doubles as the first parameter and TP will do the conversion to extended for you. The Function result returns True if the conversion was succesful, and False if not (because of overflow). Since an extended can have an exponent that will not fit in the M'Soft format Over/Underflow is handled in the following manner: Overflow: Set the Bfloatx to 0 and return a False result. Underflow: Set the BFloatx to 0 and return a True Result. No rounding is done on the mantissa. It is simply truncated to fit. } Function BFloat4toReal(b:bfloat4) : Real; Function BFloat8toReal(b:bfloat8) : Real; { These routines will convert a MicroSoft Binary Floating point number to Turbo real format. The real is large enough to store any M'Soft single or double Exponent, so no over/underflow problems are encountered. The Mantissa of an real is large enough to hold a BFloat4 mantissa, so no truncation is required. The BFloat8 mantissa is truncated (from 7 bytes to 5 bytes) } Function RealtoBFloat4(rp: real; var b:bfloat4) : Boolean; Function RealtoBFloat8(rp : real; var b:bfloat8) : Boolean; { These routines do the reverse of the above. No Over/Underflow can occur, but truncation of the mantissa can occur when converting Real to Bfloat4 (5 bytes to 3 bytes). The function always returns True, and is structured this way to function similar to the IEEE formats } implementation type IEEEExtended = record Case integer of 0 : (Mantissa : array[0..7] of byte; Exponent : word); 1 : (e : extended); end; TurboReal = record Case integer of 0 : (Exponent : byte; Mantissa : array[3..7] of byte); 1 : (r : real); end; Function HexExt(ep:extended) : string; var e : IEEEExtended absolute ep; i : integer; s : string; Function Hex(b:byte) : string; const hc : array[0..15] of char = '0123456789ABCDEF'; begin Hex := hc[b shr 4]+hc[b and 15]; end; begin s := hex(hi(e.exponent))+hex(lo(e.exponent))+' '; for i := 7 downto 0 do s := s+hex(e.mantissa[i]); HexExt := s; end; Function NullMantissa(e : IEEEextended) : boolean; var i : integer; begin NullMantissa := False; for i := 0 to 7 do if e.mantissa[i] <> 0 then exit; NullMantissa := true; end; Procedure ShiftLeftMantissa(var e); { A routine to shift the 8 byte mantissa left one bit } inline( {0101} $F8/ { CLC } {0102} $5F/ { POP DI } {0103} $07/ { POP ES } {0104} $B9/$04/$00/ { MOV CX,0004 } {0107} $26/$D1/$15/ { RCL Word Ptr ES:[DI],1 } {010A} $47/ { INC DI } {010B} $47/ { INC DI } {010C} $E2/$F9 { LOOP 0107 } ); Procedure Normalize(var e : IEEEextended); { Normalize takes an extended and insures that the "i" bit is set to 1 since M'Soft assumes a 1 is there. An extended has a value of 0.0 if the mantissa is zero, so the first check. The exponent also has to be kept from wrapping from 0 to $FFFF so the "if e.exponent = 0" check. If it gets this small for the routines that call it, there would be underflow and 0 would be returned. } var exp : word; begin exp := e.exponent and $7FFF; { mask out sign } if NullMantissa(e) then begin E.exponent := 0; exit end; while e.mantissa[7] < 128 do begin ShiftLeftMantissa(e); dec(exp); if exp = 0 then exit; end; e.exponent := (e.exponent and $8000) or exp; { restore sign } end; Function Bfloat8toExtended(d : Bfloat8) : extended; var i : integer; e : IEEEExtended; begin fillchar(e,sizeof(e),0); Bfloat8toExtended := 0.0; if d.exponent = 0 then exit; { if the bfloat exponent is 0 the mantissa is ignored and the value reurned is 0.0 } e.exponent := d.exponent - 129 + 16383; { bfloat is biased by 129, extended by 16383 This creates the correct exponent } if d.mantissa[7] > 127 then { if the sign bit in bfloat is 1 then set the sign bit in the extended } e.exponent := e.exponent or $8000; move(d.Mantissa[1],e.mantissa[1],6); e.mantissa[7] := $80 or (d.mantissa[7] and $7F); { bfloat assumes 1.fffffff, so supply it for extended } Bfloat8toExtended := e.e; end; Function Bfloat4toExtended(d : bfloat4) : extended; var i : integer; e : IEEEExtended; begin fillchar(e,sizeof(e),0); Bfloat4toExtended := 0.0; if d.exponent = 0 then exit; e.exponent := integer(d.exponent - 129) + 16383; if d.mantissa[7] > 127 then e.exponent := e.exponent or $8000; move(d.Mantissa[5],e.mantissa[5],2); e.mantissa[7] := $80 or (d.mantissa[7] and $7F); Bfloat4toExtended := e.e; end; Function ExtendedtoBfloat8(ep : extended; var b : Bfloat8) : boolean; var e : IEEEextended absolute ep; exp : integer; sign : byte; begin FillChar(b,Sizeof(b),0); ExtendedtoBfloat8 := true; { assume success } Normalize(e); if e.exponent = 0 then exit; sign := byte(e.exponent > 32767) shl 7; exp := (e.exponent and $7FFF) - 16383 + 129; if exp < 0 then exp := 0; { underflow } if exp > 255 then { overflow } begin ExtendedtoBfloat8 := false; exit; end; b.exponent := exp; move(e.mantissa[1],b.mantissa[1],7); b.mantissa[7] := (b.mantissa[7] and $7F) or sign; end; Function ExtendedtoBfloat4(ep : extended; var b : Bfloat4) : boolean; var e : IEEEextended absolute ep; exp : integer; sign : byte; begin FillChar(b,Sizeof(b),0); ExtendedtoBfloat4 := true; { assume success } Normalize(e); if e.exponent = 0 then exit; sign := byte(e.exponent > 32767) shl 7; exp := (e.exponent and $7FFF) - 16383 + 129; if exp < 0 then exp := 0; { underflow } if exp > 255 then { overflow } begin ExtendedtoBfloat4 := false; exit; end; b.exponent := exp; move(e.mantissa[5],b.mantissa[5],3); b.mantissa[7] := (b.mantissa[7] and $7F) or sign; end; Function BFloat4toReal(b:bfloat4) : Real; var r : TurboReal; begin fillchar(r,sizeof(r),0); r.exponent := b.exponent; move(b.mantissa[5],r.mantissa[5],3); Bfloat4toReal := r.r; end; Function BFloat8toReal(b:bfloat8) : Real; var r : TurboReal; begin fillchar(r,sizeof(r),0); r.exponent := b.exponent; move(b.mantissa[3],r.mantissa[3],5); Bfloat8toReal := r.r; end; Function RealtoBFloat4(rp: real; var b:bfloat4) : Boolean; var r : TurboReal absolute rp; begin fillchar(b,sizeof(b),0); b.exponent := r.exponent; move(r.mantissa[5],b.mantissa[5],3); RealtoBfloat4 := true; end; Function RealtoBFloat8(rp : real; var b:bfloat8) : Boolean; var r : TurboReal absolute rp; begin fillchar(b,sizeof(b),0); b.exponent := r.exponent; move(r.mantissa[3],b.mantissa[3],5); RealtoBfloat8 := true; end; end.