Skip to main content
gamedev.net
🔒 Locked

Division by zero detection

Started by RogalDorn Jan 9, 2004 at 11:15 AM 39 replies 3.5k views
Original Post
RogalDorn
RogalDorn
Hello, we are working on a new Doom3 like Engine (graphicslike) and came to a problem. Our physics and our render engine are executing thousands of mathematical operations per frame. Now I realized that due to some special vertex constellations some operations perform a division by zero *coughs*. Thus our performance lowers dramatically to less than 10%. I would like to know if there is an easy way to detect divisions by zero similar to the way you can track memory leaks are reported with Visual Studio. I do not want to put an if in front of each divsion we do to check that there won''t be a divsion by zero. Thanks a lot in advance Greetings Jan
Rick Scott
Rick Scott
Instead of an "if" you can use a ?: operator.

total = x==0 ? 0 : y/x;

But you probably wanted to hear something like this:

"On modern processors, the CPU/FPU can automatically insert the value 0 if it encounters a 0 in the denominator."

I don''t know if that is true, and I doubt it, so you will probably be stuck using the if/?: thing.
Narcist
Narcist
under debug, enable fp exceptions so you can catch any divide by zeros..

try and fix the input at as high a level as possibly
CWizard
CWizard
quote:
Original post by Rick Scott
Instead of an "if" you can use a ?: operator.
That''s just another way of doing the same thing, just as bad for the instruction pipeline.
blizzard999
blizzard999
quote:

RogalDorn:
Now I realized that due to some special vertex constellations some operations perform a division by zero *coughs*. Thus our performance lowers dramatically to less than 10%.

I would like to know if there is an easy way to detect divisions by zero similar to the way you can track memory leaks are reported with Visual Studio.



You should catch exceptions raised by division by zero in debug version (in release mode you can substitute the #defines you use to throw exceptions with NOP ).

Divisions by zero are bugs! You should never ignore them! But division by zero is only a specific case...you should also pay attention to divisions that involves ''little'' number in denominator.

In practice in your code every time you use ''/'' you should ask yourself: "what happen if..."

Division by zero should raise an exception under MSVC (debug mode)(but I''m not sure now if it''s raised also for float/double).

quote:

I do not want to put an if in front of each divsion we do to check that there won''t be a divsion by zero.



This is not a problem because a float/double op is MORE expensive...dont start to optimize now
VenDrake
VenDrake
Assuming you''re using a PC and MSDev etc...
Lookup setjmp() in the MSDN. It includes an example of detecting and handling floating point division by zero.

Let me know if you can''t find it.





-----------
VenDrake

"My stupid jar is full. I can''t talk to you anymore."
-------------VenDrakeTo understand recursion, you must first understand recursion.
blizzard999
blizzard999
Microsoft says
"setjmp and longjmp do not support C++ object semantics. In C++ programs, use the C++ exception-handling mechanism."


capn_midnight
capn_midnight
you could write your own number class, with an overloaded division operator that checks for divide by zero. I mean, that''s what I''d do. You could name it "Float", then do a global replace of float to Float.
blizzard999
blizzard999
quote:
Original post by capn_midnight
you could write your own number class, with an overloaded division operator that checks for divide by zero. I mean, that''s what I''d do. You could name it "Float", then do a global replace of float to Float.


Probably an elegant solution(like java) ...but too slow for these kind of app and your Float arrays are not guaranteed to be compatible with float arrays (useful when dealing with 3D API). And of course this class should implement every kind of conversion floats have by default (int to float, char to float, float to double,...).
In my opinion is simpler to handle division by zero where they are used or where they are called...and there are not so many divisions around!



RenderTarget
RenderTarget
You''ll just have to ensure by logic or checks. HEED THESE WORDS: Exception handling is much much mucn slower than a conditional. Like said above, div by 0 is a bug, pure and simple. It should never be allowed. Mathematically, it''s undefined. So you should never rely on it.

You could create a class Float : public float that overloads the ''/'' and checks for zero, but that would just be silly. Just stabilize your math and make checks where you can''t.

I like pie.
[sub]My spoon is too big.[/sub]
RogalDorn
RogalDorn
Hello you all,
first of all thanks a lot to you all for fast replying .
I really appreciate it.

I do not accept divsions by zero. As some of you said a division by zero is undefined and thereby has to be handled as a bug in the application.
When I divide by zero the division returns a value like this 1.#ND.

My problem is that I have a huge map with lots of polygons and a character walking through it and other things. When calculating physics and other stuff sometimes two vertices have such a stupid relation to each others that you end up by a division by zero.

Stupid example: you divide by the dot product which can be zero if the vertices have the same coordinates or lie opposite to each others.

First of all I wanted to know an easy way to track divisions by zero because I want to know IF there are any other operations at the moment which divide by zero and thereby slow down the performance (and act illegaly because div by zero is illegal).

Then I come to the point of preventing divisions by zero.

You all gave me a few good hints where to start on this.
Thanks again
and if you have any other ideas please post them here.
Have a nice weekend
Greetings
Jan
RogalDorn
RogalDorn
Hello again,
I need to add something that I forgot to mention.
Due to the fact that a division by zero is a serious bug I want the program to terminate. Weirdly I can divide by zero as often as I want without the programm to automatically terminate.

Is there a way to change this behaviour? Or do I really have to write an interrupt handler that catches the (Int 0) division by zero interrupt?

Thanks in advance
Greetings
Jan
msn12b
msn12b
quote:
Original post by RogalDorn
Hello again,
I need to add something that I forgot to mention.
Due to the fact that a division by zero is a serious bug I want the program to terminate. Weirdly I can divide by zero as often as I want without the programm to automatically terminate.

Is there a way to change this behaviour? Or do I really have to write an interrupt handler that catches the (Int 0) division by zero interrupt?

Thanks in advance
Greetings
Jan


Look at _controlfp, _control87, _clearfp, _clear87, _fpreset, and Structured Exception Handling. There are also some SSE exception intrinsics you''ll want to look at in sse.h if you compile for P3 or above.

You''ll want to either setup a SEH block in main or some other suitable high level control function and handle EXCEPTION_FLT_* and STATUS_FLOAT_MULTIPLE_FAULTS and STATUS_FLOAT_MULTIPLE_TRAPS for SSE.

MSN

angryzenmaster @ livejournal
blizzard999
blizzard999
It''s common to use exceptions to handle bugs and report the lines where they are located (when the stack space is rewinded you can output somewhere the points where your bug was generated).
Exceptions are slow? Yes but you use them only in debug version...as I said in release mode you can remove them by redefine your ASSERT macros with NOP.

However I think that you should avoid divisions by zero with conditionals...in fact you can run in division by zero or little number after a lot of operations that creates ''singularities'' that you cannot predict.


jonbell
jonbell
If you can write an engine similar to Doom3 then surely you have the skill to get your data correct so that a div by zero never occurs.
NatasDM
NatasDM
quote:
Original post by RogalDorn
I do not want to put an if in front of each divsion we do to check that there won''t be a divsion by zero.


Well, being a Math Tutor, I have an alternative suggestion. Without seeing your "equation" I can''t be certain, but would it at all be possible to eliminate the division?

I''m referring to limits and Taylor (McClaurin) Polynomials. Limits themselves would only account for the special case of division by zero (ergo the derivative function). Taylor Polynomials however would be able to aproximate the calculation without division of variables (just constants).

From what I understand, multiplication is faster than division anyways.

Also, what''s your website?
RogalDorn
RogalDorn
Hi,
thanks again for yer answers.
Maybe I did not made my question clear enough. Normally a programm terminates as soon as it divides by zero. I wonder why this does not happen in the release version of VC++ 6.0 compiled applications.

The _controlfp and _control87 can change the behaviour so that my application terminates in debug mode.

Another thing: divisions by zero are BUGS in my point of view.
They happen because we are in development status.
I want to get rid of divisions by zero and do not want to use exception handling cuz it causes immense overhead.
I dunno why Microsft Windows does no longer terminate applications that divide by zero.

@NatasDM
We are a team of motivated software developers coding this engine in our freetime (that's around 60hours each per week). We do not have a website yet but hope to get into the game business soon.

Greetings
Jan



[edited by - RogalDorn on January 11, 2004 6:53:19 AM]
Soulkeeper
Soulkeeper
From what it looks like you are doing floating point math.

A divide by zero with floats/doubles default to setting the value of the result to 1.#ND

I believe this is how it''s always worked, not sure though. Though like somebody pointed out above, you can change the behavior.

I just wanted to point out that it''s never terminated the program (at least, I don''t believe it has)
I'm learning, just like the best of us...Ok, now assume a spherical cow... :)
overflowed
overflowed
I''m gonna hope that if you''re doing dot products and working with dot products and vectors/points that you''re using a dot() function (or something similiar) and a struct/class for the points.

If so, copy your dot() function to dotSafe() and have it check it''s result. If it''s 0, change the result to 0.001 (or there-abouts, depending on how big your numbers are, decimal point resolution, etc etc). This will ensure you don''t have an error. For a nice touch you could also have it give an error (write to a file, popup, etc) whenever a 0 result is detected.

Just a few thoughts.
blizzard999
blizzard999
quote:
Original post by overflowed
...
If so, copy your dot() function to dotSafe() and have it check it''s result. If it''s 0, change the result to 0.001 (or there-abouts, depending on how big your numbers are, decimal point resolution, etc etc). This will ensure you don''t have an error.
...



A dot product MUST returns zero if the vectors have zero len or they are orthogonal...you cannot change this rule!

-------------------

To RogalDorn: your problem is not only div by zero but also division by little numbers. Note that a zero can derive after a lot of computing (''numeric erasing'' if this is the right english term). Simply add a conditional where you must check the result; for example if you have to invert a matrix check that its determinant is not little
if(Abs(x)>YOUR_FLOAT_LITTLE_NUMBER)...

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.