bugGNU Octave - Bugs: bug #48350, plot error calculating yticks on...

 
 

bug #48350: plot error calculating yticks on large constant plus small delta

Submitter:  None
Submitted:  Thu 30 Jun 2016 09:04:49 AM UTC
   
 
Category:  Plotting Severity:  4 - Important
Priority:  5 - Normal Item Group:  Regression
Status:  Fixed Assigned to:  None
Originator Name:  Robert Jenssen Originator Email:  -email is unavailable-
Open/Closed:  * Closed Release:  * dev
Operating System:  * GNU/Linux Fixed Release:  None
Planned Release:  None
* Mandatory Fields

Add a New Comment Rich Markup
   

Jump to the original submission

Wed 24 Aug 2016 01:46:25 PM UTC, comment #7: 

The other calculations all used type double to represent values so I changed i1 and i2 to double as well to work around this regression.  See this cset (http://hg.savannah.gnu.org/hgweb/octave/rev/59d66abc27d0).

Fixed, closing report.

Rik <rik5>
Group administrator
Sat 23 Jul 2016 06:46:14 AM UTC, comment #6: 

This works for me:


diff -r 6c94c7bd55e7 libinterp/corefcn/graphics.cc
--- a/libinterp/corefcn/graphics.cc        Fri Jul 22 17:09:38 2016 -0700
+++ b/libinterp/corefcn/graphics.cc        Sat Jul 23 16:17:07 2016 +1000
@@ -6849,8 +6849,8 @@
   else
     tick_sep = calc_tick_sep (lo, hi);

-  int i1 = static_cast<int> (std::floor (lo / tick_sep));
-  int i2 = static_cast<int> (std::ceil (hi / tick_sep));
+  int i1 = static_cast<int64_t> (std::floor (lo / tick_sep));
+  int i2 = static_cast<int64_t> (std::ceil (hi / tick_sep));

   if (limmode_is_auto)
     {


Robert Jenssen <morgawr>
Fri 01 Jul 2016 05:26:35 PM UTC, comment #5: 

Note that


>> h = plot (15 + (5e-11 .* [1:70]'))


(as opposed to 5e-10) doesn't select a very good range for y axis.

Dan Sebald <sebald>
Fri 01 Jul 2016 04:55:13 PM UTC, comment #4: 

Wait, actually the long long type did work.  I forgot to change the explicit cast from <int> to <long long>.  Here's what I see:


>> h = plot (15 + (5e-10 .* [1:70]'))
lo: 0  hi: 1
tick_sep: 0.2
i1=0, i2=5
lo: 0  hi: 1
tick_sep: 0.2
i1=0, i2=5
lo: 0  hi: 1
tick_sep: 0.2
i1=0, i2=5
lo: 0  hi: 1
tick_sep: 0.2
i1=0, i2=5
lo: 0  hi: 1
tick_sep: 0.2
i1=0, i2=5
lo: 0  hi: 70
tick_sep: 10
i1=0, i2=7
lo: 0  hi: 70
tick_sep: 10
i1=0, i2=7
lo: 15  hi: 15
tick_sep: 5e-09
i1=3000000000, i2=3000000007
lo: 15  hi: 15
tick_sep: 5e-09
i1=3000000000, i2=3000000007
h = -6.5041


So the attached patch works.  Again, it seems like there should be a better approach that subtracts out the mean or "median integerized value", if you follow what I'm saying.  I.e., so that i1 and i2 become 0 and 7.  Part of the reason I say this is that the y-axis labels become meaningless--they all say "15".  In gnuplot, something like:


gnuplot> set xrange [15.0000000005000000413701854995:15.0000000349999993431993061677]
gnuplot> plot x


has y axis labels:

15.00000004
15.00000003
15.00000003
15.00000002
15.00000002
15.00000001
15.00000001
15.00000000

That's a little improvement, but still it seems one should be able to write this as 15+##e-8 if you follow.

Anyway, the attached patch works, and I'm inclined to be content with it because of how time-consuming it is to compile the project when the graphics.cc file is touched.

PS: I can guess why the out-of-memory error message of the original bug.  In the code is

  Matrix tmp_ticks (1, i2-i1+1);

when the i2 and i1 are bogus, it is probably trying to create some huge matrix.

(file #37655)

Dan Sebald <sebald>
Fri 01 Jul 2016 08:49:23 AM UTC, comment #3: 

I followed this one through the code.  This is the failing line:


    handles(i) = __go_line__ (p, data_args{:}, other_args{:});


(I put some debug lines in _line_.m and got a plot but there is no y-axis tics or labels.)  _go_line_ is internal, in the file graphics.cc as follows:


DEFUN (__go_line__, args, ,
       doc: /* -*- texinfo -*-
@deftypefn {} {} __go_line__ (@var{parent})
Undocumented internal function.
@end deftypefn */)
{
  GO_BODY (line);
}


And GO_BODY is


#define GO_BODY(TYPE) \
  gh_manager::auto_lock guard; \
 \
  if (args.length () == 0) \
    print_usage (); \
 \
  return octave_value (make_graphics_object (#TYPE, false, args)); \


which takes us to


static octave_value
make_graphics_object (const std::string& go_name,
                      bool integer_figure_handle,
                      const octave_value_list& args)
{


My best guess is that internally something is going wrong with the line construction or plotting and the return value of _go_line_ is invalid such that Octave thinks it is trying to index something (what should be a returned handle) it doesn't know about.  E.g., there is no "ans = -2.1370" or something like it even though my plot is occurring.

The construction of the line and its properties seems pretty straightforward.  There is a go.initialize() though, and this function gets called (I placed the fprintf() calls within):


Matrix
line::properties::compute_ylim (void) const
{
  Matrix m (1, 4);

  m(0) = ydata.min_val ();
fprintf(stderr, "min_val: %30lg\n", ydata.min_val ());
  m(1) = ydata.max_val ();
fprintf(stderr, "max_val: %30lg\n", ydata.max_val ());
  m(2) = ydata.min_pos ();
fprintf(stderr, "min_pos: %30lg\n", ydata.min_pos ());
  m(3) = ydata.max_neg ();
fprintf(stderr, "max_neg: %30lg\n", ydata.max_neg ());

  return m;
}


Here is what I'm seeing (snipping out the garbage):


>> h = plot ( (5e-10 .* [1:70]'))
min_val: 5.0000000000000003114079572889e-10
max_val: 3.50000000000000023866508541606e-08
min_pos: 5.0000000000000003114079572889e-10
max_neg: -inf
[snip]
>> h = plot (15 + (5e-10 .* [1:70]'))
min_val: 15.0000000005000000413701854995
max_val: 15.0000000349999993431993061677
min_pos: 15.0000000005000000413701854995
max_neg: -inf


That seems OK, nothing is being lost in the data (e.g., there is no double conversion to float or int or anything).
-verbatim-

Maybe it is this routine:


void
axes::properties::calc_ticks_and_lims (array_property& lims,
                                       array_property& ticks,
                                       array_property& mticks,
                                       bool limmode_is_auto, bool is_logscale)
{


YES, I think that is where the problem lies.  I can say that this is not correct:


fprintf(stderr, "tick_sep: %lg\n", tick_sep);
  int i1 = static_cast<int> (std::floor (lo / tick_sep));
  int i2 = static_cast<int> (std::ceil (hi / tick_sep));
fprintf(stderr, "i1=%d, i2=%d\n", i1, i2);


The result I see is:


>> h = plot (15 + (5e-10 .* [1:70]'))
[snip]
min_val: 15.0000000005000000413701854995
max_val: 15.0000000349999993431993061677
min_pos: 15.0000000005000000413701854995
max_neg: -inf
tick_sep: 5e-09
i1=-2147483648, i2=-2147483648


Because the tick_sep turns out to be so small, the division is putting that double value outside the range of an int and the value is wrapping to negative numbers.

I changed the type of i1 and i2 to "long long", but that didn't fix the problem.  I suppose it is the double arithmetic that is saturating.  But I'm not sure that is the way to fix this anyway.  Probably the right thing to do is to subtract the mean value from the data somehow before doing the range integerization.  (Takes quite a while to compile though, so I've had enough for now.)

Dan Sebald <sebald>
Thu 30 Jun 2016 04:59:44 PM UTC, comment #2: 

Confirmed, the following works in Octave 4.0.2 but not on the default branch


>> plot (15 + (5e-10 .* [1:70]'))
error: out of memory or dimension too large for Octave's index type
error: called from
    __line__ at line 120 column 16
    line at line 56 column 8
    __plt__>__plt2vv__ at line 502 column 10
    __plt__>__plt2__ at line 248 column 14
    __plt__>__plt1__ at line 207 column 10
    __plt__ at line 119 column 17
    plot at line 222 column 10



Mike Miller <mtmiller>
Group Member
Thu 30 Jun 2016 10:57:23 AM UTC, comment #1: 

The problem seems to be in function axes::properties::calc_ticks_and_lims()
at graphics.cc:6857:

  int i1 = static_cast<int> (std::floor (lo / tick_sep));
  int i2 = static_cast<int> (std::ceil (hi / tick_sep));


The debugger shows:

(gdb) p lo
$39 = 14.999999985000001
(gdb) p hi
$40 = 15.000000010000001
(gdb) p tick_sep
$41 = 5.0000000000000001e-09
(gdb) p i1
$42 = -2147483648
(gdb) p i2
$43 = -2147483648


Doing "plot(T-15)" gives sensible results.

Robert Jenssen <morgawr>
Thu 30 Jun 2016 09:04:49 AM UTC, original submission:  

I built a debug version of the development sources (see the attached output from _octave_config_info_) and ran the test_plot.m script that is also attached. Results:


$ /usr/local/dbg-octave/bin/octave-cli
GNU Octave, version 4.1.0+
Copyright (C) 2015 John W. Eaton and others.
This is free software; see the source code for copying conditions.
There is ABSOLUTELY NO WARRANTY; not even for MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  For details, type 'warranty'.

Octave was configured for "x86_64-pc-linux-gnu".

Additional information about Octave is available at http://www.octave.org.

Please contribute if you find this software useful.
For more information, visit http://www.octave.org/get-involved.html

Read http://www.octave.org/bugs.html to learn how to submit bug reports.
For information about changes from previous versions, type 'news'.

octave:1> test_plot
XOpenIM() failed
ans =

   71    1

ans =    1.50000000091998e+01
ans =    1.49999999852670e+01
kits =
{
  [1,1] = fltk
  [1,2] = gnuplot
}
ans = fltk
out of memory or dimension too large for Octave's index type
Called __line__ at line 120
Called line at line 56
Called __plt__>__plt2vv__ at line 502
Called __plt__>__plt2__ at line 248
Called __plt__>__plt1__ at line 207
Called __plt__ at line 119
Called plot at line 222
Called test_plot at line 82
ans = gnuplot
out of memory or dimension too large for Octave's index type
Called __line__ at line 120
Called line at line 56
Called __plt__>__plt2vv__ at line 502
Called __plt__>__plt2__ at line 248
Called __plt__>__plt1__ at line 207
Called __plt__ at line 119
Called plot at line 222
Called test_plot at line 82
octave:2>


Anonymous

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

Attached Files
file #37631:  octave_config_info.txt added by None (28KiB - text/plain - Script causes plot failure with fltk and gnuplot toolkits)
file #37632:  test_plot.m added by None (2KiB - text/x-objcsrc - Script causes plot failure with fltk and gnuplot toolkits)

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by rik5 (Posted a comment)
  • -email is unavailable- added by sebald (Posted a comment)
  • -email is unavailable- added by mtmiller (Posted a comment)
  • -email is unavailable- added by morgawr (Posted a comment)
  • -email is unavailable- added by None (Submitted the item)
  •  

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

    Only group members can vote.

     

    Follow 9 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2016-08-24 rik5 StatusConfirmed Fixed
        Open/ClosedOpen Closed
    2016-07-01 sebald Attached File- Added octave-longlong_tick_vars-bug48350-djs2016jul01.patch, #37655
    2016-06-30 mtmiller Summaryplot fails plot error calculating yticks on large constant plus small delta
    2016-06-30 mtmiller StatusNone Confirmed
        Summaryplot fails on development build plot fails
    2016-06-30 mtmiller Severity3 - Normal 4 - Important
    2016-06-30 None Attached File- Added octave_config_info.txt, #37631
        Attached File- Added test_plot.m, #37632

    Back to the top

    Powered by Savane 3.13-02a9.
    Corresponding source code