raph@tigger.planet.bt.co.uk (Raphael Mankin) (07/28/89)
MSC 'make' has a completely different logic from Unix 'make'. The differences, though, are not something to go into here. MSC implements a strange logic in multiplication. If you do something like int i, j; long l; ... l = i*j; MSC will compute i*j as 32 bits, discard the upper 16 bits and then sign extend the 16 bits back to 32 bits. If you want to avoid the loss of precision you have to use a cast to force a 32 by 32 multiplication. e.g. l = i * (long)j; What do other compilers do in the way of preserving or losing arithmetic precision?. I a Coral 66 compiler that I wrote some 17 years ago I went to great lengths to preserve arithmetic precision, including transforming things like a/b/c/d/e into a/(b*c*d*e) and re-ordering factors so as to do division as late as possible.
exspes@gdr.bath.ac.uk (P E Smee) (08/09/89)
In article <527@tigger.planet.bt.co.uk> raph@tigger.planet.bt.co.uk (Raphael Mankin) writes: > >I a Coral 66 compiler that I wrote some 17 years ago I went to great >lengths to preserve arithmetic precision, including transforming >things like > a/b/c/d/e >into > a/(b*c*d*e) >and re-ordering factors so as to do division as late as possible. A bad move, I'd have said. It is not difficult to think of cases where 'a/b/c/d/e' would give a sensible answer, while 'a/(b*c*d*e)' will overflow computing the denominator '(b*c*d*e)' and so give nonsense. Further, the person writing that might have set up condition (or fault, or signal, take your pick) handlers to catch the hardware conditions that might result from the repeated division (at a higher level invisible to the compiler) based on knowledge of likely values/errors. The reordering changes the sorts of faults which are likely to occur. (Having both written and used compilers myself) I'd suggest that it is generally a bad idea for a compiler to 'rewrite' expressions unless the rewrite is both mathematically identical in an ideal world, and pragmatically identical given the range of numbers the machine can express, and the sorts of faults which will occur with any set of input values. (Although, being paranoid, I'd also suggest that the person writing a/b/c/d/e should inject lots of ()s to indicate that the ordering is really desired. I tend to parenthesize everything :-) Goes without saying that I strongly feel that languages should honor any order-of- evaluation requirements which the programmer specifies using parens.
gwyn@smoke.BRL.MIL (Doug Gwyn) (08/10/89)
In article <527@tigger.planet.bt.co.uk> raph@tigger.planet.bt.co.uk (Raphael Mankin) writes: > int i, j; > long l; > l = i*j; >MSC will compute i*j as 32 bits, discard the upper 16 bits and then sign >extend the 16 bits back to 32 bits. That's acceptable behavior. If the operands were unsigned, discarding of the high bits would even be required behavior. Dealing with, or better yet avoiding, arithmetic overflow is tricky to do right. C explicitly does not constrain the implementation's behavior in such a case, partly because any simple rule would not be universally appropriate.
davidsen@sungod.crd.ge.com (ody) (08/11/89)
In article <1989Aug9.094742.20000@gdt.bath.ac.uk> exspes@gdr.bath.ac.uk (P E Smee) writes: | A bad move, I'd have said. It is not difficult to think of cases where | 'a/b/c/d/e' would give a sensible answer, while 'a/(b*c*d*e)' will | overflow computing the denominator '(b*c*d*e)' and so give nonsense. Could you give us an example? Looking at the conditions it sure looks as though even by avoiding the overflow you would be doing the equivalent operations and would get an underflow on one of the divides. I was also able to come up with values which give zero significant digits without getting a trap. I can come up with a few cases where the order of operations was important (ie big # times fraction times big # doesn't overflow, big # time big # does, before the fraction). That's a diferent problem, since order is needed for either multiplication or division. I assume that when you said "sensible answer" you meant "correct to some useful number of digits" rathar than "avoids hardware errors." bill davidsen (davidsen@crdos1.crd.GE.COM) {uunet | philabs}!crdgw1!crdos1!davidsen "Stupidity, like virtue, is its own reward" -me
scjones@sdrc.UUCP (Larry Jones) (08/13/89)
In article <1631@crdgw1.crd.ge.com>, davidsen@sungod.crd.ge.com (ody) writes: > In article <1989Aug9.094742.20000@gdt.bath.ac.uk> exspes@gdr.bath.ac.uk (P E Smee) writes: > > | A bad move, I'd have said. It is not difficult to think of cases where > | 'a/b/c/d/e' would give a sensible answer, while 'a/(b*c*d*e)' will > | overflow computing the denominator '(b*c*d*e)' and so give nonsense. > > Could you give us an example? Looking at the conditions it sure looks > as though even by avoiding the overflow you would be doing the > equivalent operations and would get an underflow on one of the divides. For simplicity, lets consider just a/b/c vs. a/(b*c). If a and b are equal and very large (like DBL_MAX, for example) and c is some small integral value (like 2.0), then a/b/c is a quite reasonable, representable value (0.5), but a/(b*c) causes an overflow (since 2.0 * DBL_MAX is not representable). ---- Larry Jones UUCP: uunet!sdrc!scjones SDRC scjones@SDRC.UU.NET 2000 Eastman Dr. BIX: ltl Milford, OH 45150-2789 AT&T: (513) 576-2070 "I have plenty of good sense. I just choose to ignore it." -Calvin