b=907986 avoid under and overflow in Normalize() r=padenot
authorKarl Tomlinson <karlt+@karlt.net>
Wed, 04 Sep 2013 21:20:58 +1200
changeset 158465 084b01d1b6b381c82606e3a4f7b9e4ef2548aa4a
parent 158464 845d86b48e8525e792bae94b7e8b63493dcfa80f
child 158466 86c9a90d8408b9c364bf1eebc9aadfddf0dcb7c9
push id2961
push userlsblakk@mozilla.com
push dateMon, 28 Oct 2013 21:59:28 +0000
treeherdermozilla-beta@73ef4f13486f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspadenot
bugs907986
milestone26.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
b=907986 avoid under and overflow in Normalize() r=padenot
content/media/webaudio/ThreeDPoint.h
--- a/content/media/webaudio/ThreeDPoint.h
+++ b/content/media/webaudio/ThreeDPoint.h
@@ -3,16 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef ThreeDPoint_h_
 #define ThreeDPoint_h_
 
 #include <cmath>
+#include <algorithm>
 
 namespace mozilla {
 
 namespace dom {
 
 struct ThreeDPoint {
   ThreeDPoint()
     : x(0.)
@@ -29,16 +30,22 @@ struct ThreeDPoint {
 
   double Magnitude() const
   {
     return sqrt(x * x + y * y + z * z);
   }
 
   void Normalize()
   {
+    // Normalize with the maximum norm first to avoid overflow and underflow.
+    double invMax = 1 / MaxNorm();
+    x *= invMax;
+    y *= invMax;
+    z *= invMax;
+
     double invDistance = 1 / Magnitude();
     x *= invDistance;
     y *= invDistance;
     z *= invDistance;
   }
 
   ThreeDPoint CrossProduct(const ThreeDPoint& rhs) const
   {
@@ -57,16 +64,22 @@ struct ThreeDPoint {
     return sqrt(hypot(rhs.x, x) + hypot(rhs.y, y) + hypot(rhs.z, z));
   }
 
   bool IsZero() const
   {
     return x == 0 && y == 0 && z == 0;
   }
   double x, y, z;
+
+private:
+  double MaxNorm() const
+  {
+    return std::max(fabs(x), std::max(fabs(y), fabs(z)));
+  }
 };
 
 ThreeDPoint operator-(const ThreeDPoint& lhs, const ThreeDPoint& rhs);
 ThreeDPoint operator*(const ThreeDPoint& lhs, const ThreeDPoint& rhs);
 ThreeDPoint operator*(const ThreeDPoint& lhs, const double rhs);
 bool operator==(const ThreeDPoint& lhs, const ThreeDPoint& rhs);
 
 }