daveb@ingres.com (When a problem comes along . . . you must whip it) (11/29/90)
Given this simplification: extern double D, foo(); foo( i ) int i; { double x; int changes = 0; do { x = foo( i ); if( x < D ) { changed++; D = x; } } while( !changed ); } is it reasonable for this to not terminate? We see a number of compilers that keep x in a register with extended precision, so that it has bits that are not in the global D. Thus, the comparison (x < D) fails, even after D is assigned the value of x. Yes, floating point in C is peculiar, but is it _this_ peculiar? thanks, -dB -- "If it were easy to understand, we wouldn't call it 'code'" David Brower: {amdahl, cpsc6a, mtxinu, sun}!rtech!daveb daveb@ingres.com
jeff@ingres.com (Jeff Anton) (11/29/90)
Dave ment to write: extern double D, foo(); bar( i ) int i; { double x; int changes = 0; do { x = foo( i ); if( x < D ) { changed++; D = x; } } while( !changed ); } The obvious compilation and recursion problems are clear with the original code. The issue is the legality of compilers extending the precision of variable when they are placed in registers. Jeff Anton
chris@mimsy.umd.edu (Chris Torek) (11/29/90)
In article <1990Nov28.220233.2630@ingres.Ingres.COM> daveb@ingres.com writes: >Given this simplification: > > extern double D, foo(); > > foo( i ) > int i; > { Type error, foo returns double and int. Because of the next problem, I am almost sure you meant `bar(i)': > double x; > int changes = 0; > do { > > x = foo( i ); Infinite recursion: to compute foo(i) we must first compute foo(i) before doing anything else. > if( x < D ) > { > changed++; > D = x; > } > > } while( !changed ); > } Repaired example: fn() { double x, eval(void); extern double D; extern void nop(void); for (D = x = eval();;) { nop(); /* does not change D */ if (x < D) D = x; else break; } } >is it reasonable for this to not terminate? I think so; I think that the reason you give here is not (quite) outlawed. >We see a number of compilers that keep x in a register with extended >precision, so that it has bits that are not in the global D. Thus, the >comparison (x < D) fails, even after D is assigned the value of x. > >Yes, floating point in C is peculiar, but is it _this_ peculiar? (Floating point in C is no more peculiar than floating point anywhere else. Or, more succinctly, floating point is peculiar everwhere.) -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 405 2750) Domain: chris@cs.umd.edu Path: uunet!mimsy!chris
jap@convex.cl.msu.edu (Joe Porkka) (11/29/90)
daveb@ingres.com (When a problem comes along . . . you must whip it) writes: >Given this simplification: > > extern double D, foo(); > > foo( i ) > int i; > { > double x; > int changes = 0; > do { > > x = foo( i ); Ooops, the recursion starts but but does not stop. You recurse BEFORE you do anything that could stop it, like an if.
gwyn@smoke.brl.mil (Doug Gwyn) (11/30/90)
In article <1990Nov28.220233.2630@ingres.Ingres.COM> daveb@hydra.Ingres.COM (When a problem comes along . . . you must whip it) writes: >is it reasonable for this to not terminate? The example you posted merely recurses "forever". I couldn't figure out a rewrite that would trigger the phenomenon you seemed to want to discuss.
gwyn@smoke.brl.mil (Doug Gwyn) (11/30/90)
In article <1990Nov29.021553.12522@ingres.Ingres.COM> jeff@ingres.com (Jeff Anton) writes: >The issue is the legality of compilers extending the precision of >variable when they are placed in registers. In many environments there is no choice; floating registers simply ARE wider than floating storage. The issue of exactly when an implementation is obliged to "scrape off" the extra precision is still open in X3J11, if I recall correctly. One might think that any cast or assignment should do this, but there are arguments why that isn't always desirable. At this point there is a C standard and it is "just" a matter of interpreting what requirements, if any, it imposes in this area. There should be an official interpretation ruling on this sometime..
stanley@phoenix.com (John Stanley) (11/30/90)
daveb@ingres.com (When a problem comes along . . . you must whip it) writes: > Given this simplification: > > extern double D, foo(); > > foo( i ) > int i; > { > double x; > int changes = 0; > do { > > x = foo( i ); > > if( x < D ) > { > changed++; > D = x; > } > > } while( !changed ); > } > > is it reasonable for this to not terminate? > Hmm. First thing foo does is invoke foo again. I would say this will not terminate until the stack overflows. Is that reasonable? If this problem were introduced by the simplification, then there is still the problem that foo never returns a value. Whatever happens to show up in x will be whatever was left in the registers. Is that going to be less than D? Who knows? > We see a number of compilers that keep x in a register with extended > precision, so that it has bits that are not in the global D. Thus, the > comparison (x < D) fails, even after D is assigned the value of x. > Ah. Floating comparisons. This is a problem that was well known (at least to me) in the Sun workstations (for one example). The 68881 FPU has an 80 bit register. This will rarely equal anything that has passed through the 64 bit double. Sun had a flag on the compiler to force floating ops to use only 64 bits from the FPU. I don't remember what it is. > Yes, floating point in C is peculiar, but is it _this_ peculiar? This is not C, it is hardware. Yes, that peculiar. <> "If winning is not important, then why keep score?" -- Turtle Head <> "Eaten any good books lately?" -- Q <> "Sanity check!" "Sorry, we can't accept it, it's from out of state." - me