{ $Id$ This file is part of the Free Pascal run time library. Copyright (c) 1997 by Michael Van Canneyt, member of the Free Pascal development team See the file COPYING.FPC, included in this distribution, for details about the copyright. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. **********************************************************************} type { See symdefh.inc tfloattyp } treal_type = (rt_s32real,rt_s64real,rt_s80real,rt_c64bit,rt_f16bit,rt_f32bit); { corresponding to single double extended fixed comp for i386 } const { do not use real constants else you get rouding errors } i10 : longint = 10; i2 : longint = 2; i1 : longint = 1; { we can use this conditional if the Inf const is defined in processor specific code PM } {$ifdef FPC_HAS_INFINITY_CONST} {$define FPC_INFINITY_FOR_REAL2STR} {$else not FPC_HAS_INFINITY_CONST} { To avoid problems with infinity just issue it in byte representation to be endianness independant PM } {$ifndef FPC_INFINITY_FOR_REAL2STR} {$ifdef SUPPORT_EXTENDED} { extended is not IEEE so its processor specific so I only allow it for i386 PM } {$ifdef i386} {$define FPC_INFINITY_FOR_REAL2STR} InfArray : {extended} array[0..9] of byte = ($0,$0,$0,$0,$0,$0,$0,$80,$ff,$7f); {$endif i386} {$endif SUPPORT_EXTENDED} {$endif not FPC_INFINITY_FOR_REAL2STR} {$ifndef FPC_INFINITY_FOR_REAL2STR} {$ifdef SUPPORT_DOUBLE} {$define FPC_INFINITY_FOR_REAL2STR} InfArray : {double} array[0..9] of byte = ($0,$0,$0,$0,$0,$0,$f0,$7f); {$endif SUPPORT_DOUBLE} {$endif not FPC_INFINITY_FOR_REAL2STR} {$ifndef FPC_INFINITY_FOR_REAL2STR} {$ifdef SUPPORT_SINGLE} {$define FPC_INFINITY_FOR_REAL2STR} InfArray : {single} array[0..3] of byte = ($0,$0,$80,$7f); {$endif SUPPORT_SINGLE} {$endif not FPC_INFINITY_FOR_REAL2STR} {$ifndef FPC_INFINITY_FOR_REAL2STR} {$warning don't know Infinity values } {$endif not FPC_INFINITY_FOR_REAL2STR} {$endif not FPC_HAS_INFINITY_CONST} Procedure str_real (len,f : longint; d : ValReal; real_type :treal_type; var s : string); { These numbers are for the double type... At the moment these are mapped onto a double but this may change in the future ! } var maxlen : longint; { Maximal length of string for float } minlen : longint; { Minimal length of string for float } explen : longint; { Length of exponent, including E and sign. Must be strictly larger than 2 } const maxexp = 1e+35; { Maximum value for decimal expressions } minexp = 1e-35; { Minimum value for decimal expressions } zero = '0000000000000000000000000000000000000000'; var correct : longint; { Power correction } currprec : longint; il,il2,roundcorr : Valreal; temp : string; power : string[10]; sign : boolean; i : integer; dot : byte; currp : pchar; begin case real_type of rt_s32real : begin maxlen:=16; minlen:=8; explen:=4; end; rt_s64real : begin maxlen:=23; minlen:=9; explen:=5; end; rt_s80real : begin maxlen:=26; minlen:=10; explen:=6; end; rt_c64bit : begin maxlen:=22; minlen:=9; { according to TP (was 5) (FK) } explen:=6; end; rt_f16bit : begin maxlen:=16; minlen:=8; explen:=4; end; rt_f32bit : begin maxlen:=16; minlen:=8; explen:=4; end; end; { check parameters } { default value for length is -32767 } if len=-32767 then len:=maxlen; { determine sign. before precision, needs 2 less calls to abs() } sign:=d<0; { the creates a cannot determine which overloaded function to call if d is extended !!! we should prefer real_to_real on real_to_longint !! corrected in compiler } { d:=abs(d); this converts d to double so we loose precision } { for the same reason I converted d:=frac(d) to d:=d-int(d); (PM) } if sign then d:=-d; {$ifdef FPC_INFINITY_FOR_REAL2STR} {$ifndef FPC_HAS_INFINITY_CONST} if d=ValReal(InfArray) then {$else FPC_HAS_INFINITY_CONST} if d=Inf then {$endif FPC_HAS_INFINITY_CONST} begin if sign then s:='-Inf' else s:='Inf'; exit; end; {$endif FPC_INFINITY_FOR_REAL2STR} { determine precision : maximal precision is : } currprec:=maxlen-explen-3; { this is also the maximal number of decimals !!} if f>currprec then f:=currprec; { when doing a fixed-point, we need less characters.} if (f<0) or ( (d<>0) and ((d>maxexp) or (d=0) and (len0) and (len=i10 then begin il:=i1; il2:=i10; repeat il:=il2; il2:=il*i10; inc(correct); until (d0) then begin while d<1 do begin d:=d*i10; dec(correct); end; end; { RoundOff } roundcorr:=extended(i1)/extended(i2); if f<0 then for i:=1 to currprec do roundcorr:=roundcorr/i10 else begin if correct+f<0 then begin for i:=1 to abs(correct+f) do roundcorr:=roundcorr*i10; end else begin for i:=1 to correct+f do roundcorr:=roundcorr/i10; end; end; d:=d+roundcorr; { 0.99 + 0.05 > 1.0 ! Fix this by dividing the results >=10 first (PV) } while (d>=10.0) do begin d:=d/i10; inc(correct); end; { Now we have a standard expression : sign d *10^correct where 1maxexp) then begin insert ('.',temp,3); str(abs(correct),power); if length(power)=0 then begin if length(temp)0 then temp[0]:=chr(pos('.',temp)+f) else temp[0]:=chr(pos('.',temp)-1); end; if length(temp)