Bug 4948 – std.algorithm.sort asserts unexpectedly with certain comparators

Status
RESOLVED
Resolution
WORKSFORME
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
x86
OS
Windows
Creation time
2010-09-26T14:10:00Z
Last change time
2012-06-10T06:20:24Z
Assigned to
andrei
Creator
peter.alexander.au

Comments

Comment #0 by peter.alexander.au — 2010-09-26T14:10:13Z
The following code asserts unexpectedly when compiled with DMD 2.048 using no flags. void main() { alias Tuple!(int, "x", int, "y") V; V[] vs = [V(3, 4), V(6, 8)]; float arg(V v) { return atan2(cast(float)v.y, cast(float)v.x); } bool order(V a, V b) { return arg(a) < arg(b); } sort!order(vs); } core.exception.AssertError@C:\D\dmd2\windows\bin\..\..\src\phobos\std\array.d(356): Attempting to fetch the front of an empty array It does not assert when the arg(V) function is replaced to be something more simple, and only asserts when vs has particular values. I suspect this has something to do with floating point inaccuracies with atan2, but haven't looked deep enough into the issue.
Comment #1 by braddr — 2011-02-06T15:40:52Z
Mass migration of bugs marked as x86-64 to just x86. The platform run on isn't what's relevant, it's if the app is a 32 or 64 bit app.
Comment #2 by lovelydear — 2012-04-22T08:40:00Z
Note that replacing float arg(V v) { return atan2(cast(float)v.y , cast(float)v.x); } with float arg(V v) { return (cast(float)v.y * cast(float)v.x); } or float arg(V v) { return (cast(float)v.y / cast(float)v.x); } is enough to make the bug disappear...
Comment #3 by andrei — 2012-04-22T09:42:49Z
Works for me on 2.059. I'll also note that arg(v[0]) == arg(v[1]).
Comment #4 by lovelydear — 2012-04-22T10:00:38Z
I'm sorry but I'm reopening the case: there is no reason for the sort to fail if two elements are equal. A sort that fails in this case is broken. Besides, as I've said before, it works with a multiplication or a division, even with equals elements. It only fails with the atan2 function. import std.stdio; import std.typecons, std.algorithm, std.math; void main() { alias Tuple!(int, "x", int, "y") V; V[] vs = [V(6, 8), V(1, 2), V(6, 8), V(5,6)]; float arg(V v) { return (cast(float)v.y * cast(float)v.x); } bool order(V a, V b) { return arg(a) < arg(b); } writeln(sort!order(vs)); }
Comment #5 by andrei — 2012-04-22T10:43:11Z
I meant to say it works for me with no assert no nothing. For the last example the output is: Tuple!(int,"x",int,"y")(1, 2), Tuple!(int,"x",int,"y")(5, 6), Tuple!(int,"x",int,"y")(6, 8), Tuple!(int,"x",int,"y")(6, 8)]
Comment #6 by andrei — 2012-04-22T10:49:24Z
Rats. That's the output with the multiplication. Using atan2 the output is: [Tuple!(int,"x",int,"y")(5, 6), Tuple!(int,"x",int,"y")(6, 8), Tuple!(int,"x",int,"y")(6, 8), Tuple!(int,"x",int,"y")(1, 2)] That's on OSX Lion/64 bit.