Boost C++ Libraries: Ticket #6095: boost::icl::is_empty fails for certain open intervals https://svn.boost.org/trac10/ticket/6095 <p> While playing around with intervals over <code>int</code> with <code>INT_MAX</code> and <code>INT_MIN</code> bounds, I encountered some assertion failures in the library. After a little debugging the problem boiled down to the following test: </p> <pre class="wiki"> BOOST_AUTO_TEST_CASE(isEmptyTest) { typedef int Value; typedef boost::icl::interval&lt;Value&gt; Interval; typedef std::numeric_limits&lt;Value&gt; Limits; Value const max(Limits::max()); BOOST_CHECK(!is_empty(Interval::open(max - 2, max))); BOOST_CHECK( is_empty(Interval::open(max - 1, max))); BOOST_CHECK( is_empty(Interval::open(max, max))); } </pre><p> The last check fails due to an integer overflow in the implementation of <code>is_empty</code> where the lower bound gets incremented. </p> <p> I was able to fix this problem for <code>is_empty</code> but there are many places in the ICL where <code>domain_next</code> or <code>domain_prior</code> is used and there might be more problems lurking there. </p> <p> My motivation for these experiments was to get a properly total interval map, i.e. one where the iterators start at <code>INT_MIN</code> and end at <code>INT_MAX</code>. To get this, I 'primed' the empty map with a closed interval ranging over the complete domain value range. But then the problems started. </p> <p> So at least for me these overflow problems are not just of academical interest. </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/6095 Trac 1.4.3 Marvin Sielenkemper <m.sielenkemper@…> Fri, 04 Nov 2011 14:29:10 GMT attachment set https://svn.boost.org/trac10/ticket/6095 https://svn.boost.org/trac10/ticket/6095 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">interval.hpp.diff</span> </li> </ul> <p> patch to check for overflow in is_empty </p> Ticket Joachim Faulhaber Sun, 06 Nov 2011 16:53:21 GMT <link>https://svn.boost.org/trac10/ticket/6095#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6095#comment:1</guid> <description> <p> Hi Marvin, </p> <p> thank you for your report and the attached patch. I agree that the behavior of <code>icl::intervals</code> at open borders and for limited domain types is kind of nasty. Nevertheless after examining your information I am not convinced that we can speak of a bug here and that a code change is needed. </p> <p> In your test case you propose that </p> <pre class="wiki"> BOOST_CHECK( is_empty(Interval::open(max, max))); </pre><p> is supposed to succeed. But an open interval <code>Interval::open(max, x)</code> has an open lower bound of <code>max</code>, which means that values of its domain_type do not exist that can be elements of the interval. My interpretation of intervals of this kind is that they are ill formed rather than empty. So the user has to take care via program logic that these types of intervals are not constructed in the same way she has to take care that <code>++i</code> is not called if <code>i == numeric_limits&lt;int&gt;::max()</code> already. </p> <p> Best regards, Joachim </p> </description> <category>Ticket</category> </item> <item> <author>Marvin Sielenkemper <m.sielenkemper@…></author> <pubDate>Mon, 07 Nov 2011 08:21:30 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/6095#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6095#comment:2</guid> <description> <p> Hi Joachim, </p> <p> as a mathematician I have to disagree: what distinguishes the interval <code>Interval::open(max, max)</code> from <code>Interval::open(0, 0)</code>? For both there exist no elements, that is the point of being empty. Even intervals like <code>Interval::closed(17, 4)</code> are allowed and deemed empty! </p> <p> As a programmer I might be able to accept the responsibility to avoid such cases, but only if I were able to do so. I encountered the problem not while putting open intervals into the container but closed ones. And for those borders like <code>min</code> and <code>max</code> certainly make sense. </p> <p> What I was trying to do was </p> <pre class="wiki"> BOOST_AUTO_TEST_CASE(totalRangeTest) { typedef int Value; typedef boost::icl::interval&lt;Value&gt; Interval; typedef std::numeric_limits&lt;Value&gt; Limits; typedef boost::icl::interval_map&lt;Value, int, boost::icl::total_enricher&gt; Container; Value const min(Limits::min()); Value const max(Limits::max()); boost::icl::interval_map&lt;Value, int, boost::icl::total_enricher&gt; intervals; intervals += std::make_pair(Interval::closed(min, max), 0); intervals += std::make_pair(Interval::right_open(0, 10), 3); BOOST_CHECK_EQUAL(intervals.iterative_size(), 3); } </pre><p> and this fails <code>BOOST_ASSERT(this-&gt;_map.find(inter_val) == this-&gt;_map.end());</code> in <code>interval_base_map.hpp</code>, line 530 while trying to calculate the new third element of the container (<code>Interval::closed(10, max)</code>) when inserting the second interval. </p> <p> Drilling down on that, I found <code>is_empty</code> and its problematic behaviour. </p> <p> Thank you for your response! </p> <p> Best regards,<br /> Marvin </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Joachim Faulhaber</dc:creator> <pubDate>Mon, 07 Nov 2011 22:26:42 GMT</pubDate> <title>status, milestone changed; keywords set https://svn.boost.org/trac10/ticket/6095#comment:3 https://svn.boost.org/trac10/ticket/6095#comment:3 <ul> <li><strong>keywords</strong> icl open interval integer overflow added </li> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">assigned</span> </li> <li><strong>milestone</strong> <span class="trac-field-old">To Be Determined</span> → <span class="trac-field-new">Boost 1.48.0</span> </li> </ul> <p> Hi Marvin, </p> <p> I hope you forgive me my temporal {arrog|ignor}ance ;) Your use case shows, that the user can hardly avoid hitting the overflow trap of open intervals that are computed internally in the library in your test case. Also your fix is a nifty one. So thanks again for the report. I will apply your fix and put you on the credits list :) Send in more use cases if you find more bugs related to the <code>[min,max]</code>-preinitialized usage. </p> <p> Cheers,<br /> Joachim </p> Ticket Marvin Sielenkemper <m.sielenkemper@…> Tue, 08 Nov 2011 08:12:12 GMT <link>https://svn.boost.org/trac10/ticket/6095#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6095#comment:4</guid> <description> <p> Hi Joachim, </p> <p> no problem :) </p> <p> But I would like to propose a maybe even more nifty fix:<br /> An open interval <code>]a, b[</code> is empty if <code>b &lt;= a || b &lt;= a + 1</code>. </p> <p> This does not only avoid the second increment, it even avoids the first one in many cases due to the short circuit <code>||</code>-operator and does <em>never</em> run into the overflow case:<br /> If the first check fails, we know that <code>a &lt; b</code> and hence that there is at least one element to increment to without overflowing. </p> <p> So this should even work for bound types that are less forgiving than <code>int</code> when hitting their bounds, (e.g. throw exceptions). </p> <p> Best regards,<br /> Marvin </p> </description> <category>Ticket</category> </item> <item> <author>Marvin Sielenkemper <m.sielenkemper@…></author> <pubDate>Tue, 08 Nov 2011 08:13:44 GMT</pubDate> <title>attachment set https://svn.boost.org/trac10/ticket/6095 https://svn.boost.org/trac10/ticket/6095 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">interval.hpp.2.diff</span> </li> </ul> <table class="wiki"> <tr>b &lt;= a <td> b &lt;= a + 1 fix </td></tr></table> Ticket Joachim Faulhaber Tue, 08 Nov 2011 18:14:49 GMT <link>https://svn.boost.org/trac10/ticket/6095#comment:5 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6095#comment:5</guid> <description> <p> Hi Marvin, </p> <p> yes, this is nice and simple. I changed the code accordingly. </p> <p> Thanx again,<br /> Joachim </p> </description> <category>Ticket</category> </item> <item> <dc:creator>anonymous</dc:creator> <pubDate>Sat, 12 Nov 2011 00:53:38 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/6095#comment:6 https://svn.boost.org/trac10/ticket/6095#comment:6 <ul> <li><strong>status</strong> <span class="trac-field-old">assigned</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">fixed</span> </li> </ul> Ticket anonymous Fri, 03 Feb 2012 07:11:10 GMT type, component changed https://svn.boost.org/trac10/ticket/6095#comment:7 https://svn.boost.org/trac10/ticket/6095#comment:7 <ul> <li><strong>type</strong> <span class="trac-field-old">Bugs</span> → <span class="trac-field-new">Patches</span> </li> <li><strong>component</strong> <span class="trac-field-old">ICL</span> → <span class="trac-field-new">Building Boost</span> </li> </ul> Ticket Joachim Faulhaber Sat, 04 Feb 2012 17:32:23 GMT type, component changed https://svn.boost.org/trac10/ticket/6095#comment:8 https://svn.boost.org/trac10/ticket/6095#comment:8 <ul> <li><strong>type</strong> <span class="trac-field-old">Patches</span> → <span class="trac-field-new">Bugs</span> </li> <li><strong>component</strong> <span class="trac-field-old">Building Boost</span> → <span class="trac-field-new">ICL</span> </li> </ul> Ticket