|
From: Ethan M. <merritt@u.washington.edu> - 2008-05-16 21:53:04
|
On Friday 16 May 2008 12:10, Lutz Maibaum wrote:
> I encountered some issues when trying to use the mouse zoom on data sets
> plotted on logarithmic axes. I have attached a sample data file. When I
> start a new gnuplot session, and plot the data using
>
> set log x; set log y; plot "test.dat" u 1:2 w lp
>
> and then try to zoom into the top right corner of the plot, there is a good
> chance that I get an error message along the lines of
>
> gnuplot> set xr[2645923.77833:105299864.051];
> set yr[525542494246:2.96579249916e+13]; set x2r[ 6.42110: 8.02058];
> set y2r[11.3442: 12.9336]
> ^
> integer overflow; change to floating point
>
> I observed this in both the X11 and the wxt terminals, using gnuplot 4.2.3
> on a linux box. Can anyone else reproduce this behavior?
No, I can't reproduce it. But I can see what is wrong from the output you gave.
The zoom function reads off (x1,y1) and (x2,y2) coords from the mouse and
constructs the appropriate "set [xy]range" commands as a string which is fed
back to the command line interpreter. In your case the lower bound on y
is too large to represent as an integer. This would normally be OK because
it is written using a floating point format
mouse.c line 662: sprintf(s, "set xr[%.12g:%.12g]; set yr[%.12g:%.12g]"
but since there is nothing after the decimal point, the %g format writes
it as a 12 digit integer. Such an integer is too large to read in. It would
work if there were a trailing decimal point, but there isn't one.
Simpler demonstation of the problem:
gnuplot> t = 525542494246
gnuplot> print t
2147483647
gnuplot> t = 525542494246.
gnuplot> print t
525542494246.0
Your machine issues the message you see
"integer overflow; change to floating point".
based on the test in scanner.c: get_num()
lval = atol(str);
if ((token[t_num].l_val.v.int_val = lval) != lval)
But this test assumes appears to assume some odd non-POSIX behavior,
and/or an odd compiler. I would expect the compiler to optimize away
the test if ((A=B) != B)
The only exception would be for A = NaN, but that can't happen for
a positive integer. My linux machine behaves as documented by the spec
for atol(). On overflow it returns MAX_LONG, which is a legal value,
and the test for ((A=MAX_LONG) != MAX_LONG) can never trigger even
if it hasn't been optimize away.
Anyhow....
Can anyone think of a down-side to simply storing the number as a complex double
in such a case? Does it even need to be treated as an int_error() rather than
a simple warning? In a case like yours, even the warning is gratuitous.
IOW, how about the following patch:
--- gnuplot/src/scanner.c 2007-08-27 01:05:18.000000000 -0700
+++ gnuplot-cvs/src/scanner.c 2008-05-16 14:37:34.000000000 -0700
@@ -278,13 +278,16 @@ get_num(char str[])
while (isdigit((unsigned char) str[++count]));
}
if (token[t_num].l_val.type == INTGR) {
- lval = atol(str);
- if ((token[t_num].l_val.v.int_val = lval) != lval)
- int_error(t_num, "integer overflow; change to floating point");
+ token[t_num].l_val.v.int_val = atol(str);
+ if (token[t_num].l_val.v.int_val < INT_MAX)
+ return(count);
+ int_warn(t_num, "integer overflow; changing to floating point");
+ token[t_num].l_val.type = CMPLX;
+ /* fall through */
}
+
+ token[t_num].l_val.v.cmplx_val.imag = 0.0;
+ token[t_num].l_val.v.cmplx_val.real = atof(str);
- } else {
- token[t_num].l_val.v.cmplx_val.imag = 0.0;
- token[t_num].l_val.v.cmplx_val.real = atof(str);
return (count);
}
--
Ethan A Merritt
|