[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Math bug



I tried to use the LongStr procedures RealToFloat and RealToEnd, but
got only "0.00000" as result.  Needless to say, zero wasn't the
input.  The first GetExponent in RealToFloat gives a wrong value due
to a broken log resp. ln calculation for iX86.  Maybe an little/big
endian problem?  

The following little program gives the output 
On iX86:
REAL    : r=1.110000e+02  ln(10)=2.302585e+00  log(111,10)=2.045323e+00
LONGREAL: l=1.110000e+02  ln(10)=-7.060941e+02  log(111,10)=9.970032e-01
On HP-PA or SPARC:
REAL    : r=1.110000e+02  ln(10)=2.302585e+00  log(111, 10)=2.045323e+00  
LONGREAL: l=1.110000e+02  ln(10)=2.302585e+00  log(111, 10)=2.045323e+00  


MODULE LT;

IMPORT
  Unix, CharClass, LongMath, RealMath;

VAR
  i: LONGINT; r: REAL; l: LONGREAL;

PROCEDURE Ln;
  VAR
    nl: ARRAY 3 OF CHAR;
    i: LONGINT;
  BEGIN
    nl := "X"; nl[0] := CharClass.eol; i := Unix.printf("%s", nl)
  END Ln;

BEGIN
  r := 111;
  i := Unix.printf("REAL    : r=%e  ", r);
  i := Unix.printf("ln(10)=%e  ", LONG (RealMath.ln (10)));
  i := Unix.printf("log(111, 10)=%e  ", LONG (RealMath.log (111, 10)));
  Ln;
  
  l := 111;
  i := Unix.printf("LONGREAL: l=%e  ", l);
  i := Unix.printf("ln(10)=%e  ", LongMath.ln (10));
  i := Unix.printf("log(111, 10)=%e  ", LongMath.log (111, 10));
  Ln
END LT.

------------------------------------------------------------------------

Other stuff:

IntConv, IntStr, LongConv, LongStr, RealConv, RealStr You have to
redeclare (export) the type ConvResult _and_ the constants
strAllRight, strOutOfRange, strWrongFormat, and strEmpty to allow the
use of the conversion module without having to import ConvTypes.


IntStr.IntStr
>  (* truncate output if necessary *)
>  IF LEN(str)>e THEN COPY(b, str) 
>  ELSE Str.Extract(b, 0, SHORT(LEN(str))-1, str) 
>  END
No need to use Extract, COPY will truncate the value if `str' isn't
large enough to hold `b'.


IntConv, LongConv, OakIn, and RealConv import CharInfo.  Has to be
replaced by CharClass resp. Ascii.


LowReal, LowLong:
>CONST large*=      MAX(REAL)/100;
The value is defined as "large: -- The largest value of the
corresponding real number type."  In my opinion this means that
`large' equals MAX(REAL) resp. MAX(LONGREAL).

>CONST small*=      1/large;
Definition: "small: -- The smallest positive value of the
corresponding real number type, represented to maximal precision."  So
this definition of `small' is definitely wrong.

>CONST rounds*=     TRUE;
Setting either one of them to TRUE is more than optimistic.  Are you
really saying that all function in the Math libs compute results
closest to the mathematical result?

>CONST gUnderflow*= TRUE;
Sure about that?


I think you should now how OOC handles REAL constants internally: The
front-end and the optimizers operate exclusively on LONGREAL constant
values (ie, all REAL constants are mapped to LONGREAL internally).
Truncation happens not until the constant value is assigned to a REAL
variable.  For this reason all REAL constants should be written down
with LONGREAL precision if they take part in any constant folding or
if they are passed to LONGREAL variable.  This avoids unnecassary
truncation. 


The describing comments of some procedure headers aren't very helpful.
Example: IntConv.FormatInt or the constants in LowReal&co.  I'd
appreciate if you'd extend/add those comments to fully describe the
procedure's behaviour and results.  You could take the file
ISOExtract.txt as a starting point.  And I'd be grateful if you could
format the comments to a line length of 80 characters.  This improves
readability and avoids truncated lines on displays that have a screen
width of 80 chars.


-- mva