Xref: utzoo comp.lang.smalltalk:3049 comp.object:3655 Newsgroups: comp.lang.smalltalk,comp.object Path: utzoo!utgpu!cunews!bnrgate!bqnes74!news From: CWatts@BNR.CA (Carl Watts) Subject: Re: Integer / Float arithmetic in ST80 (Some benchmarks) Message-ID: <1991Jun5.185120.8104@bqnes74.bnr.ca> Sender: news@bqnes74.bnr.ca Organization: Bell Northern Research Date: Wed, 5 Jun 91 18:51:20 GMT In regards to the "Re: Integer / Float arithmetic in ST80 (Some benchmarks)" message I posted a while ago, "Ed Klimas" sent me a response through normal mail. Because the message and my response are of general userfulness to Smalltalkers, I'll post my answer here (hope you don't mind Ed?) You said in your message "I also don't see how the execution is limited to 1250 times, an interval of 1 to 2499 IS presented to the block under all of the SMalltalks that I tested." If you execute the following in Smalltalk-80 v2.5 (or earlier probably) (it won't execute at all in Smalltalk-80 v4.0): | c | c := 0. 1 to: 2499 by: 1 do: [:a | a := (a*a) sqrt ln exp arcTan tan + 1. c := c + 1] you will see that the final value of "c" is 1251 NOT 2500. This shows the loop only executed half the number of times it was intended to. I'm not sure also that readers of the above code would realize (as my friend Joe May didn't) that: a := (a*a) sqrt ln exp arcTan tan + 1 is the same as (given precise arithmetic): a := a + 1 This is important because it is easier to see the problem with: 1 to: 2499 by: 1 do: [:a | a := a + 1] since you don't get thrown off by the trig functions. The Smalltalk-80 v2.5 compiler compiles the to:by:do: message inline. This message doesn't actually get sent, instead the code for it is compiled right into the method that uses it. The comment for the method Integer>to:by:do: mentions this. This would be fine if it weren't for the fact that a certain optimization is done by the compiler when it does this. This optimization has a bug in it in that it allows assignment to the blocks local variables ("a" in your case) to have an effect on the next invocation of the block. This means your "a := ... + 1" DOES IN FACT increment "a" for the next invocation of the loop. But the to:by:do:'s job is also to increment the parameter to the block each time through the loop. So because of this inline bug, the "a" gets incremented TWICE through the loop. This is why it only executes 1250 times instead of 2500 times. Anway, even in other Smalltalk's which don't have this bug, the Savage Test code you used is still improperly formed. In these Smalltalk's the "by: 1" part, the "a:=" part, and the "+1" part of the loop shouldn't be there. The "by: 1" is unnecessary, the "a :=" is meaningless (or illegal), and the "+1" is improper since the reason you are using to:by:do: is because it increments the parameter to the block. The other code you gave (if you want to answer the final value of "a") is also wrong: | a | 1 to: 2499 by: 1 do: [:a| a:= (a*a) sqrt ln exp arcTan tan +1] ^a In a properly functioning Smalltalk this either: a) wouldn't execute at all because its illegal to assign to a parameter to a block or: b) would answer "nil" since the "a" inside the loop is a different "a" from the one outside the loop. In some Smalltalk's this expression would happen to work ONLY because of TWO known "bugs" in the these Smalltalks. The first is the aforementioned bug in the Compiler's inlineing of the to:by:do: statement. The second bug is the fact that some Smalltalk's (like older Smalltalk-80's) used method temp vars for block temp vars. In any properly functioning Smalltalk, that expression would never work right. You definitely want: | a | a := 1. 2499 timesRepeat: [a := (a*a) sqrt ln exp arcTan tan + 1] I found it very interesting that you reported that Smalltalk/V answered the precise answer "2500" for the final value of "a" with the code you gave above. This shows that either Smalltalk/V is using incredibly precise trig arithmetic OR that you got the answer "2500" only because of the aforementioned bugs in the Smalltalk implementation. Only because of these bugs could your expression happen to have given you the right answer. I suspect if you redo your benchmark test using my version of this Savage Benchmark, you will find: a) Smalltalk/V does not have incredibly precise trig arithmetic, it was just a bizarre coincidence that bugs in your expression made use of bugs in the Smalltalk to give you the impression that it did. b) The times you gave for Smalltalk-80 v2.5 were off by about 50% because the loop only executed half the expected number of times. Please get back to us about Smalltalk/V's precision. I would be very interested to find out how Smalltalk/V fares in precision to Smalltalk-80 for a properly formulated expression of this benchmark.