When comparing the results of floating point operations on Hercules/VM and Windows, I discovered many differences. Most details of this difficult analysis and work are documented here:
Stanford Compiler Facebook page.
The biggest problem was that the output values were implicitly rounded on the PC (using the sprintf() function from ANSI C), but not always correctly. On Hercules/VM, there was no rounding at all.
For example: when writing the value 12.35 with only one decimal digit, Stanford Pascal on VM would always write 12.3, but Stanford Pascal on the PC would write 12.3 or 12.4, depending on the precision of the computed value (if there has been some arithmetic before the output operation, the value may be a little bit lower than "true" 12.35, so 12.3 is printed instead of 12.4, which would be correct).
To make the floating point output comparable, there is only one solution (which I know from my long experience with this topic, when working for a big European insurance company):
the output has to be rounded to the needed decimal precision,
but before the rounding a correction has to be made
that compensates the error introduced by the computations before.
This solution, BTW, will not work in every pathological case - a specialist on this topic once told me: "what you do is pretty good, but you can do what you want: I will always find a counter example where it will not work".
The "correction" in fact means that - depending on the platform - a value is added to the original value, that depends on the size on the original value; for example: if x is the original value, then the correction value is x * (16 ** (- 13)).
To do this, I implemented a new function in the Pascal runtime that does this kind of "corrective" rounding. This function is called ROUNDX, which means "round extended". It has a second parameter which tells the decimal position where the rounding has to take place; -2 for example means: at the 2nd decimal position. Values from 4 to -15 are accepted for the second parameter.
The ROUNDX function needs the FLOOR function as defined by the C runtime; so I added this function, too.
On Hercules/VM, ROUNDX is implemented in PASLIBX.PAS in Pascal (calling sequence generated by the compiler using CALLLIBRARYFUNC). FLOOR is a true CSP function which is implemented in PASMONN using ASSEMBLER (only a very small number of ASSEMBLER instructions). See the ROUNDX1 source code (from PASLIBX.PAS) below.
On Windows etc., roundx is a C function, and floor is already available, because it is a ANSI C function.
Because the "classical" ROUND function from Pascal worked differently on the both platforms, too, I changed its implementation, too. Now on both platforms, ROUND (x) is implemented as ROUNDX (x, 0), followed by TRUNC ... because ROUNDX gives a REAL result, but ROUND needs INTEGER. With this change, now ROUND works the same on all platforms (in most cases).
Note: I decided to do the corrective action only for ROUND and ROUNDX, but not for TRUNC and FLOOR.
|
Example program: the program didn't show 13 and -13 as result of ROUND before my changes:
|
Now the program produces the correct (and the same) result on both platforms:
|