Sunday, January 28, 2018

A squished bug...

A squished bug...  Of the software variety, that is.  My Sisyphus table software had a bug in it that was driving me crazy.  At apparently random times while the software was running, it would generate insane tracks for the table.  I call them “insane” because they didn't resemble in any way what my software commands told it to do.

I spent hours tracking it down to the point where in one function I could add or subtract a line of code and the problem would disappear or reappear.  The thing is, that line of code did essentially nothing – and even worse, adding it caused results before the added line of code to change.  This makes no sense unless one of two things were true: (a) the compiler had a bug, or (b) I didn't really understand what I was looking at.

One of my golden rules of debugging is never assume you have a compiler bug, unless you have proved to yourself at least 15 different ways that it couldn't possibly be something else.  I hadn't done that, so I kept plugging away.

The function I was having the oddball results in computes a transformed position – it applies an offset in Cartesian coordinates, and a rotation in polar coordinates.  After some very careful observation, I noted that when it worked properly, the input angle was about 2E-15 ... very close to zero, but not quite.  When it was working incorrectly, it was exactly zero.  This function called another function that computes an angle from a delta x, delta y pair; that function looked like this:


Spot the problem?  I didn't, at least not right away.  It's in the last line of that function, with the call to Math.signum().  My intent there was to multiply pi by either 1 or -1 ... but Math.signum() can also return zero, if the input is exactly zero.  Bingo!  The fix was simple: I wrote my own “sign()” function that returns only +1 or -1 and changed the function as below:


Presto!  Problem gone.

And it was not a compiler bug.  :)