Page 41 - Developer
P. 41

INNER PRodUcT // bRUcE dawsoN





          sin(float(pi)) is a very accurate   intrinsically safe because it is   as these times do not grow as the   point exceptions for its scope. By
          measure of the error in float(pi).  very likely that, even though your   game progresses, there will be   dropping these into key places
            With all that background in   GetGameTime() function returns a   no problems with bugs that only   you can validate the integrity of
          place, the two generic comparison   double, some junior programmer   occur after several days.  the code that you control, while
          routines I recommend are in Listing   will store the result in a float and   sidestepping issues in the code
          5 (relative and absolute) and   you’re back to having bugs that   exceptions  that you don’t control.
          Listing 6 (ULPs and absolute).  only occur after hours of gameplay.  » All code has bugs. That is the   The ideal strategy is to put a
            In both cases, if you know   Luckily, there is an easy   depressing reality of programming.   float-exception enabling object in the
          that you will not be dealing with   solution. The whole problem arises   In many cases the difference   start function of each thread, and
          numbers near zero, then you can   because float and double have   between shipping on time and   then disable exceptions as needed.
          use the simpler versions that omit   more precision near zero. All we   missing Christmas is a matter of   Pragmatic constraints might mean
          the maxDiff absolute epsilon.  have to do is not start our timer at   how quickly bugs can be found and   that you just enable float-exceptions
                                   zero. If we use a double, and if we   fixed. Since games contain huge   in your particle system, or just in
          FLoats For time anD
          Location                         Fixing rare or difficult-to-reproduce bugs is the most tedious
          » Fixing rare or difficult-to-reproduce   part of software development, so any design patterns that
          bugs is the most tedious part of    lead to such bugs should be avoided at all costs. In game
          software development, so any    development, there are a couple of patterns that lead to bugs
          design patterns that lead to such   that only occur after many hours of play, or in distant regions
          bugs should be avoided at all costs.   of maps, and if you don’t take steps to avoid these patterns you
          In game development, there are a           may have some long nights before certification.
          couple of patterns that lead to bugs
          that only occur after many hours of
          play, or in distant regions of maps,   start our timer at 4294967296.0   amounts of floating-point math, you   your AI. Baby steps are better than
          and if you don’t take steps to avoid   (2 to the 32nd power), then our   can improve your odds of finding   no steps at all. See Listing 7 for the
          these patterns you may have some   precision will be consistent until   quirky bugs if you enable floating-  classes I use.
          long nights before certification.  the timer reaches 8,589,934,592   point exceptions. Enabling floating-
            Floating-point numbers are   seconds—which won’t happen   point exceptions for divide-by-zero,   saving FLoats as text
          designed to have consistent   for more than a century. In   overflow, and illegal-operation is   » Text-based file formats can be
          relative precision across a wide   addition to ensuring consistent   like adding asserts before and after   terribly convenient because they are
          range of magnitudes. Or, to put it   precision, this technique   every floating-point operation. I’ve   human-readable and easily editable,
          another way, they are designed   guarantees that anybody trying   used this technique for 20 years and   but it is not obvious how to convert a
          to have much better absolute   to store GetGameTime() in a float   it continues to be useful. On a recent   float to text in a way that retains the
          precision near zero. If you use   will immediately hit precision   project that was not written to be   exact valuesufficient precision.
          float or double when this variable   problems, and the mistake will   float-exception clean, I was able to   Printing the exact value of a float
          precision is not desirable—  quickly be discovered. If you   enable float-exceptions in a few key   can require over 100 decimal digits.
          or when it might even be   prefer to return a 64-bit fixed-point   systems and then find an illegal   Luckily, printing the exact value of
          counterproductive—then you can   integer, then an extremely large   operation that was making particles   a float is rarely necessary. What
          end up with lots of exciting bugs.  number as the start point will   disappear, as well as some reading   is more useful is to print enough
            If you use a float to store   catch developers who store the   of uninitialized stack memory that   digits so that the original value can
          elapsed time in your game, that   game time in a float or an integer.  was triggering various forms of   be reconstructed when the text is
          means you have more precision   You’ll see similar problems   undefined behavior. It works.  converted back to a float. For this
          at the beginning of a game than at   occur with player positions and   The NaNs and infinities that are   purpose it is sufficient to print nine
          the end. When your game has been   world geometry. Storing player   created by exceptional situations can   digits of mantissa. Ninety-four
          running for 60 seconds, a float that   positions in a float means that   also cause performance problems,   percent of floats can round-trip to
          holds the elapsed time will have   you have much more precision   particularly on the x87 FPU—yet   text and back with just eight digits,
          .0038 milliseconds of precision.   near the origin, and it means   another reason to avoid them.  but all floats are guaranteed to
          Once your game has been running   that when you transmit player   The complicating factor is that   round-trip to text and back with nine
          for a day (86,400 seconds) that   positions across the network   not all code runs float-exception   digits. One possible way to do this
          same float only has 7.8 milliseconds   you are wasting precious bits   clean. Some libraries trigger illegal   is to use printf(“%1.8e”, f); which
          of precision. This is a big enough   on transmitting the exponent.   operations because they were   puts eight digits after the mantissa’s
          drop to make it quite likely that you   Using floats to store position is   carelessly written, and others may   decimal point. Perfect.
          will have timing precision bugs that   probably unavoidable, but when   make legitimate use of divide-by-  If you’re not sure that you trust
          will only show up after the game has   transmitting positions you should   zero semantics. Either way, any   your printf and scanf functions to
          been running for a long time.  consider using fixed-point.  practical way of enabling floating-  round-trip floats, you can instead
            The simple fix to the timing   It is fine to store time   point exceptions needs to account   easily write code that will iterate
          problem is to store time in a 64-bit   differences—the time between   for this reality.  through all of the floats, printing
          number—either a double or a   events—in a float, and that may   The simple technique is to   to text, scanning back to float, and
          64-bit integer (representing the   be necessary for compactly   define two C++ classes: one that   verifying that nothing is lost. On
          elapsed count of microseconds or   storing particle lifetimes and other   enables a set of floating-point   a modern computer, a complete
          nanoseconds). These techniques   attributes. As long as these times   exceptions for its scope, and   test takes less than 15 minutes.
          both work, but they are not   are relatively small, and as long   another that disables all floating-  There’s no point in wondering

                                                                                            www.gdmag.com  39
   36   37   38   39   40   41   42   43   44   45   46