Page 2 of 3

Re: Division on Zero

Posted: Thu Oct 07, 2010 5:06 am
by ShiftZ
One more... no, not div by zero. Got invalid floating point operation on cpSpaceHash.c: 230 while trying to add a new shape in scene:

static inline int
floor_int(cpFloat f)
{
int i = (int)f;
...

it caused by uninitialized values of shape->bb.
Initialization has been commented for some reason cpShape.c:65
// cpShapeCacheBB(shape);

shape may have huge bb size and filll whole hash space, also may lead to very long loop casescpSpaceHash:245.

Re: Division on Zero

Posted: Thu Oct 07, 2010 8:34 am
by slembcke
This should be fixed in trunk as of a couple weeks ago. I had intended to move it so that the bounding box wouldn't be calculated until the shape was actually added to the space. (This was causing some other bug) It seems I missed a couple of cases though.

Re: Division on Zero

Posted: Wed Apr 06, 2011 9:28 am
by ShiftZ
Anyone know how to trap floating point exception on iPhone.
I had no success. All i can do is just check if floating point exception flag is raised, but it's usless without exact raising location.

Re: Division on Zero

Posted: Fri Sep 23, 2011 7:39 am
by ShiftZ
slembcke
Hi, again constanly catching floating point exception.

cpPolyShape.c:
cpPolyShapeSegmentQuery(cpPolyShape *poly, cpVect a, cpVect b, cpSegmentQueryInfo *info)

Code: Select all

cpFloat an = cpvdot(a, n);
if(axes[i].d > an) continue;
		
cpFloat bn = cpvdot(b, n);
cpFloat t = (axes[i].d - an)/(bn - an);
If vector a and b enough distant from center (0, 0) and pretty close to each other, then quite likely bn and an would be equal due to lack of float precision. For example :
a.x -132.42502 float
a.y -91.492790 float

b.x -134.37552 float
b.y -90.621086 float

n.x 0.40801811 float
n.y 0.91297394 float

gives equal bn an and division by zero as result. Note that a and b are pretty common values, it's not an exotic case. More distant values gives div by zero more often. I think there should be a way to avoid such inconsistence.

Re: Division on Zero

Posted: Fri Sep 23, 2011 9:53 am
by ShiftZ
slembcke
Well, anyway, it is missing extra condition check

Code: Select all

 if (an == bn) continue; 
in case if ab segment is parallel to polygon edge.


The only thing that i cannot understand is that:

Code: Select all

if(axes[i].d > an) continue;
What does it mean? Why it is working?

Re: Division on Zero

Posted: Fri Sep 23, 2011 9:55 am
by slembcke
Hmm. That's sort of nasty. I'll have to rearrange some of those ops to use the available precision better. It's hitting that surface very nearly parallel to it's surface causing the dot products to be nearly equal even when the line segment size is not particularly small.

Re: Division on Zero

Posted: Fri Sep 23, 2011 10:05 am
by slembcke

Code: Select all

if(axes[i].d > an) continue;
That checks if the starting point of the segment query is already behind that particular axis. Queries aren't checked against the interior of shapes, so it needs to reject those cases.

Re: Division on Zero

Posted: Fri Sep 23, 2011 10:05 am
by ShiftZ
slembcke wrote:Hmm. That's sort of nasty. I'll have to rearrange some of those ops to use the available precision better.
You can localize calculation of t, but actually there is no need to do that since very close an and bn unlikly hit the poly edge. All you need to fix it is just to add extra condition check:

Code: Select all

cpFloat an = cpvdot(a, n);
if(axes[i].d > an) continue;
      
cpFloat bn = cpvdot(b, n);
if (an == bn) continue; // Parallel surfaces or very close to parallel
cpFloat t = (axes[i].d - an)/(bn - an);
However this wont fix a rare case of distant segment close to parallel, but still crossing the edge. It wont hit and this will be a bug. To fix it you'll have to calculate t relative one of the poly vertex. Something link:
float an = (a - v) dot n;
float bn = (b - v) dot n;
float t = an / (bn - an);

Re: Division on Zero

Posted: Tue Feb 14, 2012 4:22 am
by ShiftZ
Hey, another division by zero here

Code: Select all

cpBB.h:
static inline cpFloat cpBBSegmentQuery(cpBB bb, cpVect a, cpVect b)
{
	cpFloat idx = 1.0f/(b.x - a.x);
	cpFloat tx1 = (bb.l == a.x ? -INFINITY : (bb.l - a.x)*idx);
	cpFloat tx2 = (bb.r == a.x ?  INFINITY : (bb.r - a.x)*idx);
	cpFloat txmin = cpfmin(tx1, tx2);
	cpFloat txmax = cpfmax(tx1, tx2);
	
	cpFloat idy = 1.0f/(b.y - a.y);
	cpFloat ty1 = (bb.b == a.y ? -INFINITY : (bb.b - a.y)*idy);
	cpFloat ty2 = (bb.t == a.y ?  INFINITY : (bb.t - a.y)*idy);
	cpFloat tymin = cpfmin(ty1, ty2);
	cpFloat tymax = cpfmax(ty1, ty2);
1.0f/(b.x - a.x) and 1.0f/(b.y - a.y);

Re: Division on Zero

Posted: Tue Feb 14, 2012 9:21 am
by slembcke
Yes, those were intended to produce infinity for horizontal or vertical lines.