[tracing] Move math utilities from base into their own subdirectory (attempt 2)

Reattempting after the last CL missed updating some references to tr.b.Range.

Script to rename imports:

function names {
  echo bbox2
  echo math
  echo quad
  echo rect
  echo running_statistics
  echo statistics
  echo piecewise_linear_function
  echo range
  echo range_utils
  echo sorted_array_utils
}

function update_exports {
  local path=$1
  sed -i '' "s!tr.exportTo('tr.b'!tr.exportTo('tr.b.math'!g" $path
}

function from_last_return {
  local path=$1
  local line=$(cat $path | grep return -nr | tail -1 | cut -d: -f2)
  awk "NR >= $line" $path
}

function get_exports {
  local path=$1
  from_last_return $path | grep "^    " | sed 's/,//g' | sed 's/    //g'
}

function update_imports {
  local path=$1
  get_exports $path | while read export; do
  find tracing dashboard -type f | grep 'html$' | xargs sed -i '' "s!tr.b.$export\([^A-Za-z]\)!tr.b.math.$export\1!g"
  done
}

files=$(find tracing dashboard -type f | grep 'html$')
gypifiles=$(find tracing dashboard -type f | grep 'gypi$')

names | while read name; do
  sed -i '' "s!tracing/base/$name.html!tracing/base/math/$name.html!g" $files
  sed -i '' "s!tracing/base/$name.html!tracing/base/math/$name.html!g" $gypifiles
  update_exports tracing/tracing/base/math/$name.html
  update_imports tracing/tracing/base/math/$name.html
done

BUG=catapult:#3425

Review-Url: https://codereview.chromium.org/2771723003
diff --git a/trace_processor/experimental/mappers/scheduling/map_input_blockers.html b/trace_processor/experimental/mappers/scheduling/map_input_blockers.html
index 34b16a3..50ff386 100644
--- a/trace_processor/experimental/mappers/scheduling/map_input_blockers.html
+++ b/trace_processor/experimental/mappers/scheduling/map_input_blockers.html
@@ -6,7 +6,7 @@
 -->
 
 <link rel="import" href="/perf_insights/mre/function_handle.html">
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
 
 <script>
@@ -45,13 +45,13 @@
         // Now we can derive the queueing interval from the flow event.
         var flowEvent = event.inFlowEvents[0];
         var queueRange =
-            tr.b.Range.fromExplicitRange(flowEvent.start, event.start);
+            tr.b.math.Range.fromExplicitRange(flowEvent.start, event.start);
 
         // Find all events that intersect the queueing interval and compute how
         // much they contributed to it.
         for (var intersectingEvent of mainThread.getDescendantEvents()) {
           var eventRange =
-              tr.b.Range.fromExplicitRange(intersectingEvent.start,
+              tr.b.math.Range.fromExplicitRange(intersectingEvent.start,
                   intersectingEvent.start + intersectingEvent.duration);
           var intersection = queueRange.findIntersection(eventRange);
           if (intersection.isEmpty || intersection.duration === 0)
diff --git a/trace_processor/experimental/mappers/scheduling/map_wake_ups.html b/trace_processor/experimental/mappers/scheduling/map_wake_ups.html
index d8b3701..b8e3ced 100644
--- a/trace_processor/experimental/mappers/scheduling/map_wake_ups.html
+++ b/trace_processor/experimental/mappers/scheduling/map_wake_ups.html
@@ -6,7 +6,7 @@
 -->
 
 <link rel="import" href="/perf_insights/mre/function_handle.html">
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 
 <script>
 'use strict';
diff --git a/trace_processor/experimental/mappers/slice_cost.html b/trace_processor/experimental/mappers/slice_cost.html
index d1f1ff8..b741363 100644
--- a/trace_processor/experimental/mappers/slice_cost.html
+++ b/trace_processor/experimental/mappers/slice_cost.html
@@ -98,7 +98,7 @@
     function generateDomainCosts(slice) {
       // V8.Execute events may generate several sliceCostInfo, based on the
       // origin of the JS being executed.
-      var range = new tr.b.Range();
+      var range = new tr.b.math.Range();
       slice.addBoundsToRange(range);
       var filtered = range.filterArray(
           slice.parentContainer.samples,
diff --git a/trace_processor/experimental/mappers/trace_stats.html b/trace_processor/experimental/mappers/trace_stats.html
index a8e48a0..d86c760 100644
--- a/trace_processor/experimental/mappers/trace_stats.html
+++ b/trace_processor/experimental/mappers/trace_stats.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/base/unit.html">
 <link rel="import" href="/tracing/mre/function_handle.html">
 <link rel="import" href="/tracing/value/histogram.html">
@@ -23,7 +23,7 @@
     var lastTime = 0;
     var categories = {};
 
-    var seconds_counts = {};
+    var secondsCounts = {};
     for (var event of model.getDescendantEvents()) {
       eventCount += 1;
       if (event.start < firstTime)
@@ -39,17 +39,17 @@
       categories[event.category]++;
 
       var second = Math.round(event.start / 1000);
-      if (seconds_counts[second] === undefined)
-        seconds_counts[second] = 0;
+      if (secondsCounts[second] === undefined)
+        secondsCounts[second] = 0;
 
-      seconds_counts[second]++;
+      secondsCounts[second]++;
     }
 
     var histogram = new tr.v.Histogram(
         tr.b.Unit.byName.count, COUNT_BOUNDARIES);
 
-    for (var second in seconds_counts)
-      histogram.add(seconds_counts[second]);
+    for (var second in secondsCounts)
+      histogram.add(secondsCounts[second]);
 
     var stats = {
       totalEvents: eventCount,
@@ -66,7 +66,7 @@
 
   tr.mre.FunctionRegistry.register(traceStatsFunction);
 
-  //Exporting for tests.
+  // Exporting for tests.
   return {
     traceStatsFunctionForTest: traceStatsFunction
   };
diff --git a/trace_processor/experimental/mappers/v8_map_function.html b/trace_processor/experimental/mappers/v8_map_function.html
index 371cd86..4dba993 100644
--- a/trace_processor/experimental/mappers/v8_map_function.html
+++ b/trace_processor/experimental/mappers/v8_map_function.html
@@ -150,7 +150,7 @@
       if (slice.title === 'V8.Execute') {
         // V8.Execute events may generate several sliceCostInfo, based on the
         // origin of the JS being executed.
-        var range = new tr.b.Range();
+        var range = new tr.b.math.Range();
         slice.addBoundsToRange(range);
         var filtered = range.filterArray(
             slice.parentContainer.samples,
diff --git a/tracing/trace_viewer.gypi b/tracing/trace_viewer.gypi
index b4398cf..477b201 100644
--- a/tracing/trace_viewer.gypi
+++ b/tracing/trace_viewer.gypi
@@ -32,7 +32,6 @@
       '../third_party/polymer/components/polymer/polymer.html',
       'tracing/base/base.html',
       'tracing/base/base64.html',
-      'tracing/base/bbox2.html',
       'tracing/base/category_util.html',
       'tracing/base/color.html',
       'tracing/base/color_scheme.html',
@@ -46,20 +45,21 @@
       'tracing/base/guid.html',
       'tracing/base/interval_tree.html',
       'tracing/base/iteration_helpers.html',
-      'tracing/base/math.html',
+      'tracing/base/math/bbox2.html',
+      'tracing/base/math/math.html',
+      'tracing/base/math/piecewise_linear_function.html',
+      'tracing/base/math/quad.html',
+      'tracing/base/math/range.html',
+      'tracing/base/math/range_utils.html',
+      'tracing/base/math/rect.html',
+      'tracing/base/math/running_statistics.html',
+      'tracing/base/math/sorted_array_utils.html',
+      'tracing/base/math/statistics.html',
       'tracing/base/multi_dimensional_view.html',
-      'tracing/base/piecewise_linear_function.html',
-      'tracing/base/quad.html',
       'tracing/base/raf.html',
-      'tracing/base/range.html',
-      'tracing/base/range_utils.html',
-      'tracing/base/rect.html',
-      'tracing/base/running_statistics.html',
       'tracing/base/scalar.html',
       'tracing/base/settings.html',
       'tracing/base/sinebow_color_generator.html',
-      'tracing/base/sorted_array_utils.html',
-      'tracing/base/statistics.html',
       'tracing/base/task.html',
       'tracing/base/time_display_modes.html',
       'tracing/base/timing.html',
diff --git a/tracing/tracing/base/assert_utils.html b/tracing/tracing/base/assert_utils.html
index 642792e..1f0a997 100644
--- a/tracing/tracing/base/assert_utils.html
+++ b/tracing/tracing/base/assert_utils.html
@@ -16,7 +16,7 @@
 tr.exportTo('tr.b', function() {
   /**
    * Throws if the range |actual| is not equal to the range |expected| (using
-   * tr.b.Range.equals).
+   * tr.b.math.Range.equals).
    */
   function assertRangeEquals(actual, expected) {
     assert(actual.equals(expected),
diff --git a/tracing/tracing/base/bbox2.html b/tracing/tracing/base/math/bbox2.html
similarity index 94%
rename from tracing/tracing/base/bbox2.html
rename to tracing/tracing/base/math/bbox2.html
index 25e07d4..b7520cb 100644
--- a/tracing/tracing/base/bbox2.html
+++ b/tracing/tracing/base/math/bbox2.html
@@ -5,8 +5,8 @@
 found in the LICENSE file.
 -->
 <link rel="import" href="/tracing/base/base.html">
-<link rel="import" href="/tracing/base/math.html">
-<link rel="import" href="/tracing/base/rect.html">
+<link rel="import" href="/tracing/base/math/math.html">
+<link rel="import" href="/tracing/base/math/rect.html">
 
 <script>
 'use strict';
@@ -14,7 +14,7 @@
 /**
  * @fileoverview 2D bounding box computations.
  */
-tr.exportTo('tr.b', function() {
+tr.exportTo('tr.b.math', function() {
   /**
    * Tracks a 2D bounding box.
    * @constructor
@@ -141,7 +141,7 @@
     },
 
     asRect: function() {
-      return tr.b.Rect.fromXYWH(
+      return tr.b.math.Rect.fromXYWH(
           this.min_[0],
           this.min_[1],
           this.max_[0] - this.min_[0],
diff --git a/tracing/tracing/base/bbox2_test.html b/tracing/tracing/base/math/bbox2_test.html
similarity index 90%
rename from tracing/tracing/base/bbox2_test.html
rename to tracing/tracing/base/math/bbox2_test.html
index 156c25e..1bb77e0 100644
--- a/tracing/tracing/base/bbox2_test.html
+++ b/tracing/tracing/base/math/bbox2_test.html
@@ -4,7 +4,7 @@
 Use of this source code is governed by a BSD-style license that can be
 found in the LICENSE file.
 -->
-<link rel="import" href="/tracing/base/bbox2.html">
+<link rel="import" href="/tracing/base/math/bbox2.html">
 <script>
 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
@@ -14,7 +14,7 @@
 
 tr.b.unittest.testSuite(function() {
   test('addVec2', function() {
-    var bbox = new tr.b.BBox2();
+    var bbox = new tr.b.math.BBox2();
     var x = vec2.create();
     vec2.set(x, 10, 10);
     bbox.addVec2(x);
diff --git a/tracing/tracing/base/math.html b/tracing/tracing/base/math/math.html
similarity index 98%
rename from tracing/tracing/base/math.html
rename to tracing/tracing/base/math/math.html
index 0a71cb1..e0658a41 100644
--- a/tracing/tracing/base/math.html
+++ b/tracing/tracing/base/math/math.html
@@ -30,7 +30,7 @@
 <script>
 'use strict';
 
-tr.exportTo('tr.b', function() {
+tr.exportTo('tr.b.math', function() {
   var PREFERRED_NUMBER_SERIES_MULTIPLIERS = [1, 2, 5, 10];
 
   /* Returns true when x and y are within delta of each other. */
@@ -215,7 +215,7 @@
     var absMin = Math.abs(min);
     // The conservative guess is the largest power of 10 less than
     // or equal to |absMin|.
-    var conservativeGuess = tr.b.lesserPower(absMin);
+    var conservativeGuess = tr.b.math.lesserPower(absMin);
     var minPreferedNumber = undefined;
     for (var multiplier of PREFERRED_NUMBER_SERIES_MULTIPLIERS) {
       var tightenedGuess = conservativeGuess * multiplier;
diff --git a/tracing/tracing/base/math/math_test.html b/tracing/tracing/base/math/math_test.html
new file mode 100644
index 0000000..81c2a1c
--- /dev/null
+++ b/tracing/tracing/base/math/math_test.html
@@ -0,0 +1,150 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/math/math.html">
+
+<script>
+'use strict';
+
+tr.b.unittest.testSuite(function() {
+  test('erf', function() {
+    assert.closeTo(-1, tr.b.math.erf(-1e10), 1e-6);
+    assert.closeTo(-0.8427, tr.b.math.erf(-1), 1e-6);
+    assert.closeTo(-0.5205, tr.b.math.erf(-0.5), 1e-6);
+    assert.closeTo(0, tr.b.math.erf(0), 1e-6);
+    assert.closeTo(0.5205, tr.b.math.erf(0.5), 1e-6);
+    assert.closeTo(0.8427, tr.b.math.erf(1), 1e-6);
+    assert.closeTo(1, tr.b.math.erf(1e10), 1e-6);
+  });
+
+  test('clamping', function() {
+    assert.equal(tr.b.math.clamp(2, 1, 3), 2);
+    assert.equal(tr.b.math.clamp(1, 1, 3), 1);
+    assert.equal(tr.b.math.clamp(0, 1, 3), 1);
+    assert.equal(tr.b.math.clamp(3, 1, 3), 3);
+    assert.equal(tr.b.math.clamp(4, 1, 3), 3);
+  });
+
+  test('interpolatePiecewiseFunction', function() {
+    var points = [[0, 0], [0.1, 0.5], [1, 1]];
+    assert.equal(0, vec2.interpolatePiecewiseFunction(points, -1));
+    assert.equal(0, vec2.interpolatePiecewiseFunction(points, 0));
+    assert.equal(0.25, vec2.interpolatePiecewiseFunction(points, 0.05));
+    assert.equal(0.5, vec2.interpolatePiecewiseFunction(points, 0.1));
+    assert.equal(0.75, vec2.interpolatePiecewiseFunction(points, 0.55));
+    assert.equal(1, vec2.interpolatePiecewiseFunction(points, 1));
+    assert.equal(1, vec2.interpolatePiecewiseFunction(points, 2));
+  });
+
+  test('powers', function() {
+    assert.strictEqual(0.01, tr.b.math.lesserPower(0.05));
+    assert.strictEqual(0.1, tr.b.math.greaterPower(0.05));
+    assert.strictEqual(0.1, tr.b.math.lesserPower(0.5));
+    assert.strictEqual(1, tr.b.math.greaterPower(0.5));
+    assert.strictEqual(1, tr.b.math.lesserPower(5));
+    assert.strictEqual(10, tr.b.math.greaterPower(5));
+    assert.strictEqual(10, tr.b.math.lesserPower(50));
+    assert.strictEqual(100, tr.b.math.greaterPower(50));
+
+    assert.strictEqual(0, tr.b.math.lesserPower(0));
+    assert.strictEqual(0, tr.b.math.greaterPower(0));
+    assert.isTrue(isNaN(tr.b.math.lesserPower(-1)));
+    assert.isTrue(isNaN(tr.b.math.greaterPower(-1)));
+
+    assert.strictEqual(0.25, tr.b.math.lesserPower(0.3, 2));
+    assert.strictEqual(0.5, tr.b.math.greaterPower(0.3, 2));
+    assert.strictEqual(0.5, tr.b.math.lesserPower(0.8, 2));
+    assert.strictEqual(1, tr.b.math.greaterPower(0.8, 2));
+    assert.strictEqual(1, tr.b.math.lesserPower(1.5, 2));
+    assert.strictEqual(2, tr.b.math.greaterPower(1.5, 2));
+    assert.strictEqual(2, tr.b.math.lesserPower(3, 2));
+    assert.strictEqual(4, tr.b.math.greaterPower(3, 2));
+    assert.strictEqual(4, tr.b.math.lesserPower(5, 2));
+    assert.strictEqual(8, tr.b.math.greaterPower(5, 2));
+
+    assert.strictEqual(0, tr.b.math.lesserPower(0, 2));
+    assert.strictEqual(0, tr.b.math.greaterPower(0, 2));
+    assert.isTrue(isNaN(tr.b.math.lesserPower(-1, 2)));
+    assert.isTrue(isNaN(tr.b.math.greaterPower(-1, 2)));
+  });
+
+  test('lesserWholeNumber', function() {
+    // Use powers of 2 less than 10 to prevent float rounding errors from
+    // breaking Math.floor().
+    for (const i of [1, 2, 4, 8]) {
+      assert.strictEqual(-i, tr.b.math.lesserWholeNumber(-i));
+      assert.strictEqual(-i * 10, tr.b.math.lesserWholeNumber(-i * 10));
+      assert.strictEqual(-i / 10, tr.b.math.lesserWholeNumber(-i / 10));
+      assert.strictEqual(-i * 100, tr.b.math.lesserWholeNumber(-i * 100));
+      assert.strictEqual(-i / 100, tr.b.math.lesserWholeNumber(-i / 100));
+
+      assert.strictEqual(i, tr.b.math.lesserWholeNumber(i));
+      assert.strictEqual(i * 10, tr.b.math.lesserWholeNumber(i * 10));
+      assert.strictEqual(i / 10, tr.b.math.lesserWholeNumber(i / 10));
+      assert.strictEqual(i * 100, tr.b.math.lesserWholeNumber(i * 100));
+      assert.strictEqual(i / 100, tr.b.math.lesserWholeNumber(i / 100));
+
+      const x = i * 1.01;
+      assert.strictEqual(-i, tr.b.math.lesserWholeNumber(-x));
+      assert.strictEqual(-i * 10, tr.b.math.lesserWholeNumber(-x * 10));
+      assert.strictEqual(-i / 10, tr.b.math.lesserWholeNumber(-x / 10));
+      assert.strictEqual(-i * 100, tr.b.math.lesserWholeNumber(-x * 100));
+      assert.strictEqual(-i / 100, tr.b.math.lesserWholeNumber(-x / 100));
+
+      assert.strictEqual(i, tr.b.math.lesserWholeNumber(x));
+      assert.strictEqual(i * 10, tr.b.math.lesserWholeNumber(x * 10));
+      assert.strictEqual(i / 10, tr.b.math.lesserWholeNumber(x / 10));
+      assert.strictEqual(i * 100, tr.b.math.lesserWholeNumber(x * 100));
+      assert.strictEqual(i / 100, tr.b.math.lesserWholeNumber(x / 100));
+    }
+  });
+
+  test('greaterWholeNumber', function() {
+    // Use powers of 2 great than 10 to prevent float rounding errors from
+    // breaking Math.floor().
+    for (const i of [1, 2, 4, 8]) {
+      assert.strictEqual(-i, tr.b.math.greaterWholeNumber(-i));
+      assert.strictEqual(-i * 10, tr.b.math.greaterWholeNumber(-i * 10));
+      assert.strictEqual(-i / 10, tr.b.math.greaterWholeNumber(-i / 10));
+      assert.strictEqual(-i * 100, tr.b.math.greaterWholeNumber(-i * 100));
+      assert.strictEqual(-i / 100, tr.b.math.greaterWholeNumber(-i / 100));
+
+      assert.strictEqual(i, tr.b.math.greaterWholeNumber(i));
+      assert.strictEqual(i * 10, tr.b.math.greaterWholeNumber(i * 10));
+      assert.strictEqual(i / 10, tr.b.math.greaterWholeNumber(i / 10));
+      assert.strictEqual(i * 100, tr.b.math.greaterWholeNumber(i * 100));
+      assert.strictEqual(i / 100, tr.b.math.greaterWholeNumber(i / 100));
+
+      const x = i * 0.99;
+      assert.strictEqual(-i, tr.b.math.greaterWholeNumber(-x));
+      assert.strictEqual(-i * 10, tr.b.math.greaterWholeNumber(-x * 10));
+      assert.strictEqual(-i / 10, tr.b.math.greaterWholeNumber(-x / 10));
+      assert.strictEqual(-i * 100, tr.b.math.greaterWholeNumber(-x * 100));
+      assert.strictEqual(-i / 100, tr.b.math.greaterWholeNumber(-x / 100));
+
+      assert.strictEqual(i, tr.b.math.greaterWholeNumber(x));
+      assert.strictEqual(i * 10, tr.b.math.greaterWholeNumber(x * 10));
+      assert.strictEqual(i / 10, tr.b.math.greaterWholeNumber(x / 10));
+      assert.strictEqual(i * 100, tr.b.math.greaterWholeNumber(x * 100));
+      assert.strictEqual(i / 100, tr.b.math.greaterWholeNumber(x / 100));
+    }
+  });
+
+  test('preferedNumberLargerThanMin', function() {
+    assert.strictEqual(tr.b.math.preferredNumberLargerThanMin(0), 0);
+    assert.strictEqual(tr.b.math.preferredNumberLargerThanMin(1), 1);
+    assert.strictEqual(tr.b.math.preferredNumberLargerThanMin(2), 2);
+    assert.strictEqual(tr.b.math.preferredNumberLargerThanMin(3), 5);
+    assert.strictEqual(tr.b.math.preferredNumberLargerThanMin(7), 10);
+    assert.strictEqual(tr.b.math.preferredNumberLargerThanMin(0.03), 0.05);
+    assert.strictEqual(tr.b.math.preferredNumberLargerThanMin(-1), -1);
+    assert.strictEqual(tr.b.math.preferredNumberLargerThanMin(237538), 500000);
+    assert.strictEqual(tr.b.math.preferredNumberLargerThanMin(46.13246), 50);
+    assert.strictEqual(tr.b.math.preferredNumberLargerThanMin(-823.34561),
+        -1000);
+  });
+});
+</script>
diff --git a/tracing/tracing/base/piecewise_linear_function.html b/tracing/tracing/base/math/piecewise_linear_function.html
similarity index 98%
rename from tracing/tracing/base/piecewise_linear_function.html
rename to tracing/tracing/base/math/piecewise_linear_function.html
index f4cab6f..b97b781 100644
--- a/tracing/tracing/base/piecewise_linear_function.html
+++ b/tracing/tracing/base/math/piecewise_linear_function.html
@@ -10,7 +10,7 @@
 <script>
 'use strict';
 
-tr.exportTo('tr.b', function() {
+tr.exportTo('tr.b.math', function() {
   var PERCENTILE_PRECISION = 1e-7;
   /**
    * A function that consists of linear pieces.
diff --git a/tracing/tracing/base/piecewise_linear_function_test.html b/tracing/tracing/base/math/piecewise_linear_function_test.html
similarity index 82%
rename from tracing/tracing/base/piecewise_linear_function_test.html
rename to tracing/tracing/base/math/piecewise_linear_function_test.html
index 7b36d7d..c83fe11 100644
--- a/tracing/tracing/base/piecewise_linear_function_test.html
+++ b/tracing/tracing/base/math/piecewise_linear_function_test.html
@@ -5,14 +5,14 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/piecewise_linear_function.html">
+<link rel="import" href="/tracing/base/math/piecewise_linear_function.html">
 
 <script>
 'use strict';
 
 tr.b.unittest.testSuite(function() {
   test('PiecewiseLinearFunctionEmpty', function() {
-    var f = new tr.b.PiecewiseLinearFunction();
+    var f = new tr.b.math.PiecewiseLinearFunction();
     assert.strictEqual(f.max, -Infinity);
     assert.strictEqual(f.min, Infinity);
     assert.strictEqual(f.average, 0);
@@ -20,7 +20,7 @@
   });
 
   test('PiecewiseLinearFunction', function() {
-    var f = new tr.b.PiecewiseLinearFunction();
+    var f = new tr.b.math.PiecewiseLinearFunction();
     f.push(0, 0.0, 10, 1.0);
     f.push(10, 1.0, 20, 0.0);
     f.push(20, 0.0, 30, 0.0);
diff --git a/tracing/tracing/base/quad.html b/tracing/tracing/base/math/quad.html
similarity index 97%
rename from tracing/tracing/base/quad.html
rename to tracing/tracing/base/math/quad.html
index 2ba997e..5ead839 100644
--- a/tracing/tracing/base/quad.html
+++ b/tracing/tracing/base/math/quad.html
@@ -5,11 +5,11 @@
 found in the LICENSE file.
 -->
 <link rel="import" href="/tracing/base/base.html">
-<link rel="import" href="/tracing/base/math.html">
+<link rel="import" href="/tracing/base/math/math.html">
 <script>
 'use strict';
 
-tr.exportTo('tr.b', function() {
+tr.exportTo('tr.b.math', function() {
   var tmpVec2s = [];
   for (var i = 0; i < 8; i++)
     tmpVec2s[i] = vec2.create();
@@ -97,7 +97,7 @@
       var x1 = Math.max(this.p1[0], this.p2[0], this.p3[0], this.p4[0]);
       var y1 = Math.max(this.p1[1], this.p2[1], this.p3[1], this.p4[1]);
 
-      return new tr.b.Rect.fromXYWH(x0, y0, x1 - x0, y1 - y0);
+      return new tr.b.math.Rect.fromXYWH(x0, y0, x1 - x0, y1 - y0);
     },
 
     clone: function() {
diff --git a/tracing/tracing/base/math/quad_test.html b/tracing/tracing/base/math/quad_test.html
new file mode 100644
index 0000000..8549137
--- /dev/null
+++ b/tracing/tracing/base/math/quad_test.html
@@ -0,0 +1,130 @@
+<!DOCTYPE html>
+<!--
+Copyright (c) 2014 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+<link rel="import" href="/tracing/base/math/quad.html">
+<link rel="import" href="/tracing/base/math/rect.html">
+<script>
+'use strict';
+
+function assertQuadEquals(a, b, opt_message) {
+  var ok = true;
+  ok &= a.p1[0] === b.p1[0] && a.p1[1] === b.p1[1];
+  ok &= a.p2[0] === b.p2[0] && a.p2[1] === b.p2[1];
+  ok &= a.p3[0] === b.p3[0] && a.p3[1] === b.p3[1];
+  ok &= a.p4[0] === b.p4[0] && a.p4[1] === b.p4[1];
+  if (ok)
+    return;
+  var message = opt_message || 'Expected "' + a.toString() +
+      '", got "' + b.toString() + '"';
+  assert.fail(a, b, message);
+}
+
+tr.b.unittest.testSuite(function() {
+  test('pointInTri', function() {
+    var res = tr.b.math.pointInTriangle2(
+        [0.25, 0.25],
+        [0, 0],
+        [1, 0],
+        [0, 1]);
+    assert.isTrue(res);
+  });
+
+  test('pointNotInTri', function() {
+    var res = tr.b.math.pointInTriangle2(
+        [0.75, 0.75],
+        [0, 0],
+        [1, 0],
+        [0, 1]);
+    assert.isFalse(res);
+  });
+
+  test('pointInside', function() {
+    var q = tr.b.math.Quad.from4Vecs([0, 0],
+                                [1, 0],
+                                [1, 1],
+                                [0, 1]);
+    var res = q.pointInside([0.5, 0.5]);
+    assert.isTrue(res);
+  });
+
+  test('pointNotInQuad', function() {
+    var q = tr.b.math.Quad.from4Vecs([0, 0],
+                                [1, 0],
+                                [1, 1],
+                                [0, 1]);
+    var res = q.pointInside([1.5, 0.5]);
+    assert.isFalse(res);
+  });
+
+  test('isRectangle', function() {
+    assert.isTrue(tr.b.math.Quad.fromXYWH(0, 0, 10, 10).isRectangle());
+    assert.isTrue(tr.b.math.Quad.fromXYWH(-10, -10, 5, 5).isRectangle());
+    assert.isTrue(tr.b.math.Quad.fromXYWH(-10, -10, 20, 20).isRectangle());
+    assert.isTrue(tr.b.math.Quad.fromXYWH(-10, 10, 5, 5).isRectangle());
+
+    assert.isFalse(tr.b.math.Quad.fromXYWH(0, 0, -10, -10).isRectangle());
+    assert.isFalse(
+        tr.b.math.Quad.from8Array([0, 1, 2, 3, 4, 5, 6, 7]).isRectangle());
+    assert.isFalse(
+        tr.b.math.Quad.from8Array([0, 0, 0, 5, 5, 5, 0, 0]).isRectangle());
+  });
+
+  test('projectUnitRect', function() {
+    var container = tr.b.math.Quad.fromXYWH(0, 0, 10, 10);
+    var srcRect = tr.b.math.Rect.fromXYWH(0.1, 0.8, 0.8, 0.1);
+    var expectedRect = srcRect.scale(10);
+
+    var q = new tr.b.math.Quad();
+    container.projectUnitRectFast(q, srcRect);
+
+    assertQuadEquals(tr.b.math.Quad.fromRect(expectedRect), q);
+  });
+
+  test('projectUnitRectOntoUnitQuad', function() {
+    var container = tr.b.math.Quad.fromXYWH(0, 0, 1, 1);
+    var srcRect = tr.b.math.Rect.fromXYWH(0.0, 0, 1, 1);
+    var expectedRect = srcRect;
+
+    var q = new tr.b.math.Quad();
+    container.projectUnitRectFast(q, srcRect);
+
+    assertQuadEquals(tr.b.math.Quad.fromRect(expectedRect), q);
+  });
+
+  test('projectUnitRectOntoSizeTwoQuad', function() {
+    var container = tr.b.math.Quad.fromXYWH(0, 0, 2, 2);
+    var srcRect = tr.b.math.Rect.fromXYWH(0.0, 0, 1, 1);
+    var expectedRect = srcRect.scale(2);
+
+    var q = new tr.b.math.Quad();
+    container.projectUnitRectFast(q, srcRect);
+
+    assertQuadEquals(tr.b.math.Quad.fromRect(expectedRect), q);
+  });
+
+  test('projectUnitRectOntoTranslatedQuad', function() {
+    var container = tr.b.math.Quad.fromXYWH(1, 1, 1, 1);
+    var srcRect = tr.b.math.Rect.fromXYWH(0.0, 0, 1, 1);
+    var expectedRect = srcRect.translate([1, 1]);
+
+    var q = new tr.b.math.Quad();
+    container.projectUnitRectFast(q, srcRect);
+
+    assertQuadEquals(tr.b.math.Quad.fromRect(expectedRect), q);
+  });
+
+  test('projectShrunkUnitRectOntoUnitQuad', function() {
+    var container = tr.b.math.Quad.fromXYWH(0, 0, 1, 1);
+    var srcRect = tr.b.math.Rect.fromXYWH(0.1, 0.1, 0.8, 0.8);
+    var expectedRect = srcRect;
+
+    var q = new tr.b.math.Quad();
+    container.projectUnitRectFast(q, srcRect);
+
+    assertQuadEquals(tr.b.math.Quad.fromRect(expectedRect), q);
+  });
+});
+</script>
diff --git a/tracing/tracing/base/range.html b/tracing/tracing/base/math/range.html
similarity index 93%
rename from tracing/tracing/base/range.html
rename to tracing/tracing/base/math/range.html
index e81862e..54bcdd9 100644
--- a/tracing/tracing/base/range.html
+++ b/tracing/tracing/base/math/range.html
@@ -7,7 +7,7 @@
 
 <link rel="import" href="/tracing/base/base.html">
 <link rel="import" href="/tracing/base/iteration_helpers.html">
-<link rel="import" href="/tracing/base/math.html">
+<link rel="import" href="/tracing/base/math/math.html">
 
 <script>
 'use strict';
@@ -15,7 +15,7 @@
 /**
  * @fileoverview Quick range computations.
  */
-tr.exportTo('tr.b', function() {
+tr.exportTo('tr.b.math', function() {
   function Range() {
     this.isEmpty_ = true;
     this.min_ = undefined;
@@ -102,20 +102,20 @@
     enclosingPowers(opt_base) {
       if (this.isEmpty) return new Range();
       return Range.fromExplicitRange(
-          tr.b.lesserPower(this.min_, opt_base),
-          tr.b.greaterPower(this.max_, opt_base));
+          tr.b.math.lesserPower(this.min_, opt_base),
+          tr.b.math.greaterPower(this.max_, opt_base));
     },
 
     normalize: function(x) {
-      return tr.b.normalize(x, this.min, this.max);
+      return tr.b.math.normalize(x, this.min, this.max);
     },
 
     lerp: function(x) {
-      return tr.b.lerp(x, this.min, this.max);
+      return tr.b.math.lerp(x, this.min, this.max);
     },
 
     clamp: function(x) {
-      return tr.b.clamp(x, this.min, this.max);
+      return tr.b.math.clamp(x, this.min, this.max);
     },
 
     equals: function(that) {
@@ -123,8 +123,8 @@
         return true;
       if (this.isEmpty !== that.isEmpty)
         return false;
-      return (tr.b.approximately(this.min, that.min) &&
-          tr.b.approximately(this.max, that.max));
+      return (tr.b.math.approximately(this.min, that.min) &&
+          tr.b.math.approximately(this.max, that.max));
     },
 
     containsExplicitRangeInclusive: function(min, max) {
diff --git a/tracing/tracing/base/range_test.html b/tracing/tracing/base/math/range_test.html
similarity index 99%
rename from tracing/tracing/base/range_test.html
rename to tracing/tracing/base/math/range_test.html
index e404f73..37b1c4f 100644
--- a/tracing/tracing/base/range_test.html
+++ b/tracing/tracing/base/math/range_test.html
@@ -5,13 +5,13 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 
 <script>
 'use strict';
 
 tr.b.unittest.testSuite(function() {
-  var Range = tr.b.Range;
+  var Range = tr.b.math.Range;
 
   test('addValue', function() {
     var range = new Range();
diff --git a/tracing/tracing/base/range_utils.html b/tracing/tracing/base/math/range_utils.html
similarity index 92%
rename from tracing/tracing/base/range_utils.html
rename to tracing/tracing/base/math/range_utils.html
index 06127c0..dee6182 100644
--- a/tracing/tracing/base/range_utils.html
+++ b/tracing/tracing/base/math/range_utils.html
@@ -14,10 +14,10 @@
 /**
  * @fileoverview Provides event merging functionality for grouping/analysis.
  */
-tr.exportTo('tr.b', function() {
+tr.exportTo('tr.b.math', function() {
   function convertEventsToRanges(events) {
     return events.map(function(event) {
-      return tr.b.Range.fromExplicitRange(event.start, event.end);
+      return tr.b.math.Range.fromExplicitRange(event.start, event.end);
     });
   }
 
@@ -97,7 +97,7 @@
     });
     if (opt_totalRange &&
         (opt_totalRange.min < inRanges[0].min)) {
-      emptyRanges.push(tr.b.Range.fromExplicitRange(
+      emptyRanges.push(tr.b.math.Range.fromExplicitRange(
           opt_totalRange.min, inRanges[0].min));
     }
 
@@ -110,7 +110,7 @@
         if (other.min > range.max) {
           // |inRanges| is sorted, so |other| is the first range after |range|,
           // and there is an empty range between them.
-          emptyRanges.push(tr.b.Range.fromExplicitRange(
+          emptyRanges.push(tr.b.math.Range.fromExplicitRange(
               range.max, other.min));
           return;
         }
@@ -124,7 +124,7 @@
         }
       }
       if (opt_totalRange && (range.max < opt_totalRange.max)) {
-        emptyRanges.push(tr.b.Range.fromExplicitRange(
+        emptyRanges.push(tr.b.math.Range.fromExplicitRange(
             range.max, opt_totalRange.max));
       }
     });
diff --git a/tracing/tracing/base/range_utils_test.html b/tracing/tracing/base/math/range_utils_test.html
similarity index 80%
rename from tracing/tracing/base/range_utils_test.html
rename to tracing/tracing/base/math/range_utils_test.html
index 13cae71..a79a61b 100644
--- a/tracing/tracing/base/range_utils_test.html
+++ b/tracing/tracing/base/math/range_utils_test.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range_utils.html">
+<link rel="import" href="/tracing/base/math/range_utils.html">
 <link rel="import" href="/tracing/core/test_utils.html">
 
 <script>
@@ -25,7 +25,7 @@
       {min: 200, max: 220}
     ];
 
-    var merged = tr.b.mergeRanges(inEvents, 50, simpleMerger);
+    var merged = tr.b.math.mergeRanges(inEvents, 50, simpleMerger);
 
     assert.equal(merged.length, 2);
     assert.deepEqual(merged[0], {min: 0, max: 120});
@@ -39,7 +39,7 @@
       {min: 200, max: 220}
     ];
 
-    var merged = tr.b.mergeRanges(inEvents, 50, simpleMerger);
+    var merged = tr.b.math.mergeRanges(inEvents, 50, simpleMerger);
 
     assert.equal(merged.length, 2);
     assert.deepEqual(merged[0], {min: 0, max: 120});
@@ -53,7 +53,7 @@
       {min: 100, max: 120}
     ];
 
-    var merged = tr.b.mergeRanges(inEvents, 50, simpleMerger);
+    var merged = tr.b.math.mergeRanges(inEvents, 50, simpleMerger);
 
     assert.equal(merged.length, 1);
     assert.deepEqual(merged[0], {min: 0, max: 120});
@@ -65,7 +65,7 @@
       {min: 150, max: 200}
     ];
 
-    var merged = tr.b.mergeRanges(inEvents, 25, simpleMerger);
+    var merged = tr.b.math.mergeRanges(inEvents, 25, simpleMerger);
 
     assert.equal(merged.length, 2);
     assert.deepEqual(merged[0], {min: 0, max: 100});
@@ -78,7 +78,7 @@
     ];
 
     var mergeCount = 0;
-    tr.b.mergeRanges(inEvents, 25, function(events) {
+    tr.b.math.mergeRanges(inEvents, 25, function(events) {
       assert.deepEqual(events, inEvents);
       mergeCount++;
     });
@@ -88,7 +88,7 @@
   test('zeroDurationSplit', function() {
     var inEvents = [0, 10, 20, 50, 60];
     inEvents = inEvents.map(function(event) {
-      return tr.b.Range.fromExplicitRange(event, event);
+      return tr.b.math.Range.fromExplicitRange(event, event);
     });
     var timestampMerger = function(timestamps) {
       return {
@@ -96,7 +96,7 @@
         max: timestamps[timestamps.length - 1].max
       };
     };
-    var merged = tr.b.mergeRanges(inEvents, 15, timestampMerger);
+    var merged = tr.b.math.mergeRanges(inEvents, 15, timestampMerger);
     assert.equal(merged.length, 2);
     assert.deepEqual(merged[0], {min: 0, max: 20});
     assert.deepEqual(merged[1], {min: 50, max: 60});
@@ -108,7 +108,7 @@
       {min: 1, max: 3},
       {min: 6, max: 8}
     ];
-    var ranges = tr.b.findEmptyRangesBetweenRanges(
+    var ranges = tr.b.math.findEmptyRangesBetweenRanges(
         events, {min: 0, max: 10});
     assert.equal(3, ranges.length);
     assert.equal(0, ranges[0].min);
@@ -120,13 +120,13 @@
   });
 
   test('findEmptyRangesWithEmptyInput', function() {
-    var ranges = tr.b.findEmptyRangesBetweenRanges(
+    var ranges = tr.b.math.findEmptyRangesBetweenRanges(
         [], {min: 0, max: 10});
     assert.equal(1, ranges.length);
     assert.equal(0, ranges[0].min);
     assert.equal(10, ranges[0].max);
 
-    ranges = tr.b.findEmptyRangesBetweenRanges([]);
+    ranges = tr.b.math.findEmptyRangesBetweenRanges([]);
     assert.equal(0, ranges.length);
   });
 });
diff --git a/tracing/tracing/base/rect.html b/tracing/tracing/base/math/rect.html
similarity index 97%
rename from tracing/tracing/base/rect.html
rename to tracing/tracing/base/math/rect.html
index 1ceb399..a89d9b9 100644
--- a/tracing/tracing/base/rect.html
+++ b/tracing/tracing/base/math/rect.html
@@ -5,11 +5,11 @@
 found in the LICENSE file.
 -->
 <link rel="import" href="/tracing/base/base.html">
-<link rel="import" href="/tracing/base/math.html">
+<link rel="import" href="/tracing/base/math/math.html">
 <script>
 'use strict';
 
-tr.exportTo('tr.b', function() {
+tr.exportTo('tr.b.math', function() {
   /**
    * Tracks a 2D bounding box.
    * @constructor
diff --git a/tracing/tracing/base/rect_test.html b/tracing/tracing/base/math/rect_test.html
similarity index 76%
rename from tracing/tracing/base/rect_test.html
rename to tracing/tracing/base/math/rect_test.html
index 9f4765e..38604d4 100644
--- a/tracing/tracing/base/rect_test.html
+++ b/tracing/tracing/base/math/rect_test.html
@@ -4,7 +4,7 @@
 Use of this source code is governed by a BSD-style license that can be
 found in the LICENSE file.
 -->
-<link rel="import" href="/tracing/base/rect.html">
+<link rel="import" href="/tracing/base/math/rect.html">
 <script>
 'use strict';
 
@@ -20,10 +20,10 @@
           '", got "' + b.toString() + '"';
       assert.fail(a, b, message);
     }
-    var container = tr.b.Rect.fromXYWH(0, 0, 10, 10);
-    var inner = tr.b.Rect.fromXYWH(1, 1, 8, 8);
+    var container = tr.b.math.Rect.fromXYWH(0, 0, 10, 10);
+    var inner = tr.b.math.Rect.fromXYWH(1, 1, 8, 8);
     var uv = inner.asUVRectInside(container);
-    assertRectEquals(uv, tr.b.Rect.fromXYWH(0.1, 0.1, .8, .8));
+    assertRectEquals(uv, tr.b.math.Rect.fromXYWH(0.1, 0.1, .8, .8));
     assert.equal(10, container.size().width);
     assert.equal(10, container.size().height);
   });
diff --git a/tracing/tracing/base/running_statistics.html b/tracing/tracing/base/math/running_statistics.html
similarity index 98%
rename from tracing/tracing/base/running_statistics.html
rename to tracing/tracing/base/math/running_statistics.html
index 6ebc3d0..6fa614a 100644
--- a/tracing/tracing/base/running_statistics.html
+++ b/tracing/tracing/base/math/running_statistics.html
@@ -10,7 +10,7 @@
 <script>
 'use strict';
 
-tr.exportTo('tr.b', function() {
+tr.exportTo('tr.b.math', function() {
   /**
    * An object of this class computes basic statistics online in O(1).
    * Usage:
diff --git a/tracing/tracing/base/running_statistics_test.html b/tracing/tracing/base/math/running_statistics_test.html
similarity index 96%
rename from tracing/tracing/base/running_statistics_test.html
rename to tracing/tracing/base/math/running_statistics_test.html
index 49ea67d..4719337 100644
--- a/tracing/tracing/base/running_statistics_test.html
+++ b/tracing/tracing/base/math/running_statistics_test.html
@@ -4,14 +4,14 @@
 Use of this source code is governed by a BSD-style license that can be
 found in the LICENSE file.
 -->
-<link rel="import" href="/tracing/base/running_statistics.html">
-<link rel="import" href="/tracing/base/statistics.html">
+<link rel="import" href="/tracing/base/math/running_statistics.html">
+<link rel="import" href="/tracing/base/math/statistics.html">
 <script>
 'use strict';
 
 tr.b.unittest.testSuite(function() {
-  var RunningStatistics = tr.b.RunningStatistics;
-  var Statistics = tr.b.Statistics;
+  var RunningStatistics = tr.b.math.RunningStatistics;
+  var Statistics = tr.b.math.Statistics;
 
   function run(data) {
     var running = new RunningStatistics();
diff --git a/tracing/tracing/base/sorted_array_utils.html b/tracing/tracing/base/math/sorted_array_utils.html
similarity index 99%
rename from tracing/tracing/base/sorted_array_utils.html
rename to tracing/tracing/base/math/sorted_array_utils.html
index 7ba5e1c..0fae926 100644
--- a/tracing/tracing/base/sorted_array_utils.html
+++ b/tracing/tracing/base/math/sorted_array_utils.html
@@ -13,7 +13,7 @@
  * over sorted arrays and intervals.
  *
  */
-tr.exportTo('tr.b', function() {
+tr.exportTo('tr.b.math', function() {
   /**
    * Finds the first index in the array whose value is >= loVal.
    *
diff --git a/tracing/tracing/base/statistics.html b/tracing/tracing/base/math/statistics.html
similarity index 98%
rename from tracing/tracing/base/statistics.html
rename to tracing/tracing/base/math/statistics.html
index 071a860..5289637 100644
--- a/tracing/tracing/base/statistics.html
+++ b/tracing/tracing/base/math/statistics.html
@@ -5,8 +5,8 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/math.html">
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/math.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <script src="/mannwhitneyu/mannwhitneyu.js"></script>
 
 <script>
@@ -35,7 +35,7 @@
 // TODO(charliea): Remove:
 /* eslint-disable catapult-camelcase */
 
-tr.exportTo('tr.b', function() {
+tr.exportTo('tr.b.math', function() {
   var identity = x => x;
 
   var Statistics = {};
@@ -158,7 +158,7 @@
 
   Statistics.range = function(ary, opt_func, opt_this) {
     var func = opt_func || identity;
-    var ret = new tr.b.Range();
+    var ret = new tr.b.math.Range();
     var i = 0;
     for (var elt of ary)
       ret.addValue(func.call(opt_this, elt, i++));
@@ -383,7 +383,7 @@
       discrepancy /= sampleScale;
     } else {
       // Compute relative discrepancy
-      discrepancy = tr.b.clamp(
+      discrepancy = tr.b.math.clamp(
           (discrepancy - invSampleCount) / (1.0 - invSampleCount), 0.0, 1.0);
     }
     return discrepancy;
@@ -634,7 +634,7 @@
 
   Statistics.UniformDistribution = function(opt_range) {
     if (!opt_range)
-      opt_range = tr.b.Range.fromExplicitRange(0, 1);
+      opt_range = tr.b.math.Range.fromExplicitRange(0, 1);
     this.range = opt_range;
   };
 
@@ -646,7 +646,7 @@
     },
 
     computePercentile: function(x) {
-      return tr.b.normalize(x, this.range.min, this.range.max);
+      return tr.b.math.normalize(x, this.range.min, this.range.max);
     },
 
     get mean() {
@@ -694,7 +694,7 @@
     computePercentile: function(x) {
       var standardizedX = ((x - this.mean) /
                            Math.sqrt(2.0 * this.variance));
-      return (1.0 + tr.b.erf(standardizedX)) / 2.0;
+      return (1.0 + tr.b.math.erf(standardizedX)) / 2.0;
     },
 
     get mean() {
@@ -817,7 +817,7 @@
    * @typedef {Object} HypothesisTestResult
    * @property {number} p
    * @property {number} U
-   * @property {!tr.b.Statistics.Significance} significance
+   * @property {!tr.b.math.Statistics.Significance} significance
    */
 
   /**
diff --git a/tracing/tracing/base/statistics_test.html b/tracing/tracing/base/math/statistics_test.html
similarity index 99%
rename from tracing/tracing/base/statistics_test.html
rename to tracing/tracing/base/math/statistics_test.html
index ab4d7d0..f9ad8d9 100644
--- a/tracing/tracing/base/statistics_test.html
+++ b/tracing/tracing/base/math/statistics_test.html
@@ -4,7 +4,7 @@
 Use of this source code is governed by a BSD-style license that can be
 found in the LICENSE file.
 -->
-<link rel="import" href="/tracing/base/statistics.html">
+<link rel="import" href="/tracing/base/math/statistics.html">
 <script>
 'use strict';
 
@@ -12,7 +12,7 @@
 /* eslint-disable catapult-camelcase */
 
 tr.b.unittest.testSuite(function() {
-  var Statistics = tr.b.Statistics;
+  var Statistics = tr.b.math.Statistics;
 
   /**
    * Lloyd relaxation in 1D.
diff --git a/tracing/tracing/base/math_test.html b/tracing/tracing/base/math_test.html
deleted file mode 100644
index 4c71de1..0000000
--- a/tracing/tracing/base/math_test.html
+++ /dev/null
@@ -1,149 +0,0 @@
-<!DOCTYPE html>
-<!--
-Copyright (c) 2014 The Chromium Authors. All rights reserved.
-Use of this source code is governed by a BSD-style license that can be
-found in the LICENSE file.
--->
-<link rel="import" href="/tracing/base/math.html">
-
-<script>
-'use strict';
-
-tr.b.unittest.testSuite(function() {
-  test('erf', function() {
-    assert.closeTo(-1, tr.b.erf(-1e10), 1e-6);
-    assert.closeTo(-0.8427, tr.b.erf(-1), 1e-6);
-    assert.closeTo(-0.5205, tr.b.erf(-0.5), 1e-6);
-    assert.closeTo(0, tr.b.erf(0), 1e-6);
-    assert.closeTo(0.5205, tr.b.erf(0.5), 1e-6);
-    assert.closeTo(0.8427, tr.b.erf(1), 1e-6);
-    assert.closeTo(1, tr.b.erf(1e10), 1e-6);
-  });
-
-  test('clamping', function() {
-    assert.equal(tr.b.clamp(2, 1, 3), 2);
-    assert.equal(tr.b.clamp(1, 1, 3), 1);
-    assert.equal(tr.b.clamp(0, 1, 3), 1);
-    assert.equal(tr.b.clamp(3, 1, 3), 3);
-    assert.equal(tr.b.clamp(4, 1, 3), 3);
-  });
-
-  test('interpolatePiecewiseFunction', function() {
-    var points = [[0, 0], [0.1, 0.5], [1, 1]];
-    assert.equal(0, vec2.interpolatePiecewiseFunction(points, -1));
-    assert.equal(0, vec2.interpolatePiecewiseFunction(points, 0));
-    assert.equal(0.25, vec2.interpolatePiecewiseFunction(points, 0.05));
-    assert.equal(0.5, vec2.interpolatePiecewiseFunction(points, 0.1));
-    assert.equal(0.75, vec2.interpolatePiecewiseFunction(points, 0.55));
-    assert.equal(1, vec2.interpolatePiecewiseFunction(points, 1));
-    assert.equal(1, vec2.interpolatePiecewiseFunction(points, 2));
-  });
-
-  test('powers', function() {
-    assert.strictEqual(0.01, tr.b.lesserPower(0.05));
-    assert.strictEqual(0.1, tr.b.greaterPower(0.05));
-    assert.strictEqual(0.1, tr.b.lesserPower(0.5));
-    assert.strictEqual(1, tr.b.greaterPower(0.5));
-    assert.strictEqual(1, tr.b.lesserPower(5));
-    assert.strictEqual(10, tr.b.greaterPower(5));
-    assert.strictEqual(10, tr.b.lesserPower(50));
-    assert.strictEqual(100, tr.b.greaterPower(50));
-
-    assert.strictEqual(0, tr.b.lesserPower(0));
-    assert.strictEqual(0, tr.b.greaterPower(0));
-    assert.isTrue(isNaN(tr.b.lesserPower(-1)));
-    assert.isTrue(isNaN(tr.b.greaterPower(-1)));
-
-    assert.strictEqual(0.25, tr.b.lesserPower(0.3, 2));
-    assert.strictEqual(0.5, tr.b.greaterPower(0.3, 2));
-    assert.strictEqual(0.5, tr.b.lesserPower(0.8, 2));
-    assert.strictEqual(1, tr.b.greaterPower(0.8, 2));
-    assert.strictEqual(1, tr.b.lesserPower(1.5, 2));
-    assert.strictEqual(2, tr.b.greaterPower(1.5, 2));
-    assert.strictEqual(2, tr.b.lesserPower(3, 2));
-    assert.strictEqual(4, tr.b.greaterPower(3, 2));
-    assert.strictEqual(4, tr.b.lesserPower(5, 2));
-    assert.strictEqual(8, tr.b.greaterPower(5, 2));
-
-    assert.strictEqual(0, tr.b.lesserPower(0, 2));
-    assert.strictEqual(0, tr.b.greaterPower(0, 2));
-    assert.isTrue(isNaN(tr.b.lesserPower(-1, 2)));
-    assert.isTrue(isNaN(tr.b.greaterPower(-1, 2)));
-  });
-
-  test('lesserWholeNumber', function() {
-    // Use powers of 2 less than 10 to prevent float rounding errors from
-    // breaking Math.floor().
-    for (const i of [1, 2, 4, 8]) {
-      assert.strictEqual(-i, tr.b.lesserWholeNumber(-i));
-      assert.strictEqual(-i * 10, tr.b.lesserWholeNumber(-i * 10));
-      assert.strictEqual(-i / 10, tr.b.lesserWholeNumber(-i / 10));
-      assert.strictEqual(-i * 100, tr.b.lesserWholeNumber(-i * 100));
-      assert.strictEqual(-i / 100, tr.b.lesserWholeNumber(-i / 100));
-
-      assert.strictEqual(i, tr.b.lesserWholeNumber(i));
-      assert.strictEqual(i * 10, tr.b.lesserWholeNumber(i * 10));
-      assert.strictEqual(i / 10, tr.b.lesserWholeNumber(i / 10));
-      assert.strictEqual(i * 100, tr.b.lesserWholeNumber(i * 100));
-      assert.strictEqual(i / 100, tr.b.lesserWholeNumber(i / 100));
-
-      const x = i * 1.01;
-      assert.strictEqual(-i, tr.b.lesserWholeNumber(-x));
-      assert.strictEqual(-i * 10, tr.b.lesserWholeNumber(-x * 10));
-      assert.strictEqual(-i / 10, tr.b.lesserWholeNumber(-x / 10));
-      assert.strictEqual(-i * 100, tr.b.lesserWholeNumber(-x * 100));
-      assert.strictEqual(-i / 100, tr.b.lesserWholeNumber(-x / 100));
-
-      assert.strictEqual(i, tr.b.lesserWholeNumber(x));
-      assert.strictEqual(i * 10, tr.b.lesserWholeNumber(x * 10));
-      assert.strictEqual(i / 10, tr.b.lesserWholeNumber(x / 10));
-      assert.strictEqual(i * 100, tr.b.lesserWholeNumber(x * 100));
-      assert.strictEqual(i / 100, tr.b.lesserWholeNumber(x / 100));
-    }
-  });
-
-  test('greaterWholeNumber', function() {
-    // Use powers of 2 great than 10 to prevent float rounding errors from
-    // breaking Math.floor().
-    for (const i of [1, 2, 4, 8]) {
-      assert.strictEqual(-i, tr.b.greaterWholeNumber(-i));
-      assert.strictEqual(-i * 10, tr.b.greaterWholeNumber(-i * 10));
-      assert.strictEqual(-i / 10, tr.b.greaterWholeNumber(-i / 10));
-      assert.strictEqual(-i * 100, tr.b.greaterWholeNumber(-i * 100));
-      assert.strictEqual(-i / 100, tr.b.greaterWholeNumber(-i / 100));
-
-      assert.strictEqual(i, tr.b.greaterWholeNumber(i));
-      assert.strictEqual(i * 10, tr.b.greaterWholeNumber(i * 10));
-      assert.strictEqual(i / 10, tr.b.greaterWholeNumber(i / 10));
-      assert.strictEqual(i * 100, tr.b.greaterWholeNumber(i * 100));
-      assert.strictEqual(i / 100, tr.b.greaterWholeNumber(i / 100));
-
-      const x = i * 0.99;
-      assert.strictEqual(-i, tr.b.greaterWholeNumber(-x));
-      assert.strictEqual(-i * 10, tr.b.greaterWholeNumber(-x * 10));
-      assert.strictEqual(-i / 10, tr.b.greaterWholeNumber(-x / 10));
-      assert.strictEqual(-i * 100, tr.b.greaterWholeNumber(-x * 100));
-      assert.strictEqual(-i / 100, tr.b.greaterWholeNumber(-x / 100));
-
-      assert.strictEqual(i, tr.b.greaterWholeNumber(x));
-      assert.strictEqual(i * 10, tr.b.greaterWholeNumber(x * 10));
-      assert.strictEqual(i / 10, tr.b.greaterWholeNumber(x / 10));
-      assert.strictEqual(i * 100, tr.b.greaterWholeNumber(x * 100));
-      assert.strictEqual(i / 100, tr.b.greaterWholeNumber(x / 100));
-    }
-  });
-
-  test('preferedNumberLargerThanMin', function() {
-    assert.strictEqual(tr.b.preferredNumberLargerThanMin(0), 0);
-    assert.strictEqual(tr.b.preferredNumberLargerThanMin(1), 1);
-    assert.strictEqual(tr.b.preferredNumberLargerThanMin(2), 2);
-    assert.strictEqual(tr.b.preferredNumberLargerThanMin(3), 5);
-    assert.strictEqual(tr.b.preferredNumberLargerThanMin(7), 10);
-    assert.strictEqual(tr.b.preferredNumberLargerThanMin(0.03), 0.05);
-    assert.strictEqual(tr.b.preferredNumberLargerThanMin(-1), -1);
-    assert.strictEqual(tr.b.preferredNumberLargerThanMin(237538), 500000);
-    assert.strictEqual(tr.b.preferredNumberLargerThanMin(46.13246), 50);
-    assert.strictEqual(tr.b.preferredNumberLargerThanMin(-823.34561), -1000);
-  });
-});
-</script>
diff --git a/tracing/tracing/base/quad_test.html b/tracing/tracing/base/quad_test.html
deleted file mode 100644
index 289adde..0000000
--- a/tracing/tracing/base/quad_test.html
+++ /dev/null
@@ -1,130 +0,0 @@
-<!DOCTYPE html>
-<!--
-Copyright (c) 2014 The Chromium Authors. All rights reserved.
-Use of this source code is governed by a BSD-style license that can be
-found in the LICENSE file.
--->
-<link rel="import" href="/tracing/base/quad.html">
-<link rel="import" href="/tracing/base/rect.html">
-<script>
-'use strict';
-
-function assertQuadEquals(a, b, opt_message) {
-  var ok = true;
-  ok &= a.p1[0] === b.p1[0] && a.p1[1] === b.p1[1];
-  ok &= a.p2[0] === b.p2[0] && a.p2[1] === b.p2[1];
-  ok &= a.p3[0] === b.p3[0] && a.p3[1] === b.p3[1];
-  ok &= a.p4[0] === b.p4[0] && a.p4[1] === b.p4[1];
-  if (ok)
-    return;
-  var message = opt_message || 'Expected "' + a.toString() +
-      '", got "' + b.toString() + '"';
-  assert.fail(a, b, message);
-}
-
-tr.b.unittest.testSuite(function() {
-  test('pointInTri', function() {
-    var res = tr.b.pointInTriangle2(
-        [0.25, 0.25],
-        [0, 0],
-        [1, 0],
-        [0, 1]);
-    assert.isTrue(res);
-  });
-
-  test('pointNotInTri', function() {
-    var res = tr.b.pointInTriangle2(
-        [0.75, 0.75],
-        [0, 0],
-        [1, 0],
-        [0, 1]);
-    assert.isFalse(res);
-  });
-
-  test('pointInside', function() {
-    var q = tr.b.Quad.from4Vecs([0, 0],
-                                [1, 0],
-                                [1, 1],
-                                [0, 1]);
-    var res = q.pointInside([0.5, 0.5]);
-    assert.isTrue(res);
-  });
-
-  test('pointNotInQuad', function() {
-    var q = tr.b.Quad.from4Vecs([0, 0],
-                                [1, 0],
-                                [1, 1],
-                                [0, 1]);
-    var res = q.pointInside([1.5, 0.5]);
-    assert.isFalse(res);
-  });
-
-  test('isRectangle', function() {
-    assert.isTrue(tr.b.Quad.fromXYWH(0, 0, 10, 10).isRectangle());
-    assert.isTrue(tr.b.Quad.fromXYWH(-10, -10, 5, 5).isRectangle());
-    assert.isTrue(tr.b.Quad.fromXYWH(-10, -10, 20, 20).isRectangle());
-    assert.isTrue(tr.b.Quad.fromXYWH(-10, 10, 5, 5).isRectangle());
-
-    assert.isFalse(tr.b.Quad.fromXYWH(0, 0, -10, -10).isRectangle());
-    assert.isFalse(
-        tr.b.Quad.from8Array([0, 1, 2, 3, 4, 5, 6, 7]).isRectangle());
-    assert.isFalse(
-        tr.b.Quad.from8Array([0, 0, 0, 5, 5, 5, 0, 0]).isRectangle());
-  });
-
-  test('projectUnitRect', function() {
-    var container = tr.b.Quad.fromXYWH(0, 0, 10, 10);
-    var srcRect = tr.b.Rect.fromXYWH(0.1, 0.8, 0.8, 0.1);
-    var expectedRect = srcRect.scale(10);
-
-    var q = new tr.b.Quad();
-    container.projectUnitRectFast(q, srcRect);
-
-    assertQuadEquals(tr.b.Quad.fromRect(expectedRect), q);
-  });
-
-  test('projectUnitRectOntoUnitQuad', function() {
-    var container = tr.b.Quad.fromXYWH(0, 0, 1, 1);
-    var srcRect = tr.b.Rect.fromXYWH(0.0, 0, 1, 1);
-    var expectedRect = srcRect;
-
-    var q = new tr.b.Quad();
-    container.projectUnitRectFast(q, srcRect);
-
-    assertQuadEquals(tr.b.Quad.fromRect(expectedRect), q);
-  });
-
-  test('projectUnitRectOntoSizeTwoQuad', function() {
-    var container = tr.b.Quad.fromXYWH(0, 0, 2, 2);
-    var srcRect = tr.b.Rect.fromXYWH(0.0, 0, 1, 1);
-    var expectedRect = srcRect.scale(2);
-
-    var q = new tr.b.Quad();
-    container.projectUnitRectFast(q, srcRect);
-
-    assertQuadEquals(tr.b.Quad.fromRect(expectedRect), q);
-  });
-
-  test('projectUnitRectOntoTranslatedQuad', function() {
-    var container = tr.b.Quad.fromXYWH(1, 1, 1, 1);
-    var srcRect = tr.b.Rect.fromXYWH(0.0, 0, 1, 1);
-    var expectedRect = srcRect.translate([1, 1]);
-
-    var q = new tr.b.Quad();
-    container.projectUnitRectFast(q, srcRect);
-
-    assertQuadEquals(tr.b.Quad.fromRect(expectedRect), q);
-  });
-
-  test('projectShrunkUnitRectOntoUnitQuad', function() {
-    var container = tr.b.Quad.fromXYWH(0, 0, 1, 1);
-    var srcRect = tr.b.Rect.fromXYWH(0.1, 0.1, 0.8, 0.8);
-    var expectedRect = srcRect;
-
-    var q = new tr.b.Quad();
-    container.projectUnitRectFast(q, srcRect);
-
-    assertQuadEquals(tr.b.Quad.fromRect(expectedRect), q);
-  });
-});
-</script>
diff --git a/tracing/tracing/base/sinebow_color_generator.html b/tracing/tracing/base/sinebow_color_generator.html
index c6aba3c..436a406 100644
--- a/tracing/tracing/base/sinebow_color_generator.html
+++ b/tracing/tracing/base/sinebow_color_generator.html
@@ -7,7 +7,7 @@
 
 <link rel="import" href="/tracing/base/color.html">
 <link rel="import" href="/tracing/base/iteration_helpers.html">
-<link rel="import" href="/tracing/base/math.html">
+<link rel="import" href="/tracing/base/math/math.html">
 
 <script>
 'use strict';
@@ -75,9 +75,9 @@
       g *= brightness;
       b *= brightness;
     } else {
-      r = tr.b.lerp(tr.b.normalize(brightness, 1, 2), r, 255);
-      g = tr.b.lerp(tr.b.normalize(brightness, 1, 2), g, 255);
-      b = tr.b.lerp(tr.b.normalize(brightness, 1, 2), b, 255);
+      r = tr.b.math.lerp(tr.b.math.normalize(brightness, 1, 2), r, 255);
+      g = tr.b.math.lerp(tr.b.math.normalize(brightness, 1, 2), g, 255);
+      b = tr.b.math.lerp(tr.b.math.normalize(brightness, 1, 2), b, 255);
     }
     r = Math.round(r);
     g = Math.round(g);
diff --git a/tracing/tracing/base/sorted_array_utils_test.html b/tracing/tracing/base/sorted_array_utils_test.html
index 9b411b8..53ba261 100644
--- a/tracing/tracing/base/sorted_array_utils_test.html
+++ b/tracing/tracing/base/sorted_array_utils_test.html
@@ -4,7 +4,7 @@
 Use of this source code is governed by a BSD-style license that can be
 found in the LICENSE file.
 -->
-<link rel="import" href="/tracing/base/sorted_array_utils.html">
+<link rel="import" href="/tracing/base/math/sorted_array_utils.html">
 <script>
 'use strict';
 
@@ -20,14 +20,14 @@
     },
 
     findLowElementIndex: function(ts) {
-      return tr.b.findLowIndexInSortedArray(
+      return tr.b.math.findLowIndexInSortedArray(
           this.array,
           function(x) { return x.lo; },
           ts);
     },
 
     findIntervalIndex: function(ts) {
-      return tr.b.findIndexInSortedIntervals(
+      return tr.b.math.findIndexInSortedIntervals(
           this.array,
           function(x) { return x.lo; },
           function(x) { return x.hi - x.lo; },
@@ -35,7 +35,7 @@
     },
 
     findIndexInClosedIntervals: function(ts) {
-      return tr.b.findIndexInSortedClosedIntervals(
+      return tr.b.math.findIndexInSortedClosedIntervals(
           this.array,
           function(x) { return x.lo; },
           function(x) { return x.hi; },
@@ -45,7 +45,7 @@
     findIntersectingIntervals: function(tsA, tsB) {
       var array = this.array;
       var result = [];
-      tr.b.iterateOverIntersectingIntervals(
+      tr.b.math.iterateOverIntersectingIntervals(
           this.array,
           function(x) { return x.lo; },
           function(x) { return x.hi - x.lo; },
@@ -56,7 +56,7 @@
     },
 
     findClosestElement: function(ts, tsDiff) {
-      return tr.b.findClosestElementInSortedArray(
+      return tr.b.math.findClosestElementInSortedArray(
           this.array,
           function(x) { return x.lo; },
           ts,
@@ -64,7 +64,7 @@
     },
 
     findClosestInterval: function(ts, tsDiff) {
-      return tr.b.findClosestIntervalInSortedIntervals(
+      return tr.b.math.findClosestIntervalInSortedIntervals(
           this.array,
           function(x) { return x.lo; },
           function(x) { return x.hi; },
diff --git a/tracing/tracing/base/unittest/test_case.html b/tracing/tracing/base/unittest/test_case.html
index 447d03b..154d313 100644
--- a/tracing/tracing/base/unittest/test_case.html
+++ b/tracing/tracing/base/unittest/test_case.html
@@ -116,8 +116,8 @@
       var durationStrings = durations.map(function(d) {
         return d.toFixed(2) + 'ms';
       });
-      var average = tr.b.Statistics.mean(durations);
-      var min = tr.b.Statistics.min(durations);
+      var average = tr.b.math.Statistics.mean(durations);
+      var min = tr.b.math.Statistics.min(durations);
 
       var summaryString = ' [';
       summaryString += 'min ' + min.toFixed(2) + 'ms, ';
diff --git a/tracing/tracing/base/unittest/test_suite.html b/tracing/tracing/base/unittest/test_suite.html
index a2ed777..42cd5dd 100644
--- a/tracing/tracing/base/unittest/test_suite.html
+++ b/tracing/tracing/base/unittest/test_suite.html
@@ -6,7 +6,7 @@
 -->
 
 <link rel="import" href="/tracing/base/guid.html">
-<link rel="import" href="/tracing/base/statistics.html">
+<link rel="import" href="/tracing/base/math/statistics.html">
 <link rel="import" href="/tracing/base/unittest/constants.html">
 <link rel="import" href="/tracing/base/unittest/test_case.html">
 
diff --git a/tracing/tracing/extras/android/android_auditor.html b/tracing/tracing/extras/android/android_auditor.html
index 8cbe1fb..fceaf54 100644
--- a/tracing/tracing/extras/android/android_auditor.html
+++ b/tracing/tracing/extras/android/android_auditor.html
@@ -6,9 +6,9 @@
 -->
 
 <link rel="import" href="/tracing/base/iteration_helpers.html">
-<link rel="import" href="/tracing/base/range_utils.html">
+<link rel="import" href="/tracing/base/math/range_utils.html">
+<link rel="import" href="/tracing/base/math/statistics.html">
 <link rel="import" href="/tracing/base/scalar.html">
-<link rel="import" href="/tracing/base/statistics.html">
 <link rel="import" href="/tracing/base/unit.html">
 <link rel="import" href="/tracing/core/auditor.html">
 <link rel="import" href="/tracing/model/alert.html">
@@ -28,7 +28,7 @@
   var Auditor = tr.c.Auditor;
   var AndroidModelHelper = tr.model.helpers.AndroidModelHelper;
   var ColorScheme = tr.b.ColorScheme;
-  var Statistics = tr.b.Statistics;
+  var Statistics = tr.b.math.Statistics;
   var FRAME_PERF_CLASS = tr.model.FRAME_PERF_CLASS;
   var Alert = tr.model.Alert;
   var EventInfo = tr.model.EventInfo;
@@ -533,7 +533,8 @@
             events[events.length - 1].max - events[0].min);
         this.model.userModel.expectations.push(ir);
       }.bind(this);
-      tr.b.mergeRanges(tr.b.convertEventsToRanges(events), 30, mergerFunction);
+      tr.b.math.mergeRanges(
+          tr.b.math.convertEventsToRanges(events), 30, mergerFunction);
     },
 
     addInputInteractionRecords: function() {
@@ -550,9 +551,10 @@
         this.model.userModel.expectations.push(ir);
       }.bind(this);
       var inputRanges = inputSamples.map(function(sample) {
-        return tr.b.Range.fromExplicitRange(sample.timestamp, sample.timestamp);
+        return tr.b.math.Range.fromExplicitRange(
+            sample.timestamp, sample.timestamp);
       });
-      tr.b.mergeRanges(inputRanges, 30, mergerFunction);
+      tr.b.math.mergeRanges(inputRanges, 30, mergerFunction);
     }
   };
 
diff --git a/tracing/tracing/extras/chrome/cc/layer_impl.html b/tracing/tracing/extras/chrome/cc/layer_impl.html
index 2333239..7afd06e 100644
--- a/tracing/tracing/extras/chrome/cc/layer_impl.html
+++ b/tracing/tracing/extras/chrome/cc/layer_impl.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/rect.html">
+<link rel="import" href="/tracing/base/math/rect.html">
 <link rel="import" href="/tracing/extras/chrome/cc/constants.html">
 <link rel="import" href="/tracing/extras/chrome/cc/region.html">
 <link rel="import" href="/tracing/extras/chrome/cc/tile_coverage_rect.html">
@@ -54,13 +54,13 @@
       this.gpuMemoryUsageInBytes = this.args.gpuMemoryUsage;
 
       // Leave bounds in both places.
-      this.bounds = tr.b.Rect.fromXYWH(
+      this.bounds = tr.b.math.Rect.fromXYWH(
           0, 0,
           this.args.bounds.width, this.args.bounds.height);
 
       if (this.args.animationBounds) {
         // AnimationBounds[2] and [5] are the Z-component of the box.
-        this.animationBoundsRect = tr.b.Rect.fromXYWH(
+        this.animationBoundsRect = tr.b.math.Rect.fromXYWH(
             this.args.animationBounds[0], this.args.animationBounds[1],
             this.args.animationBounds[3], this.args.animationBounds[4]);
       }
diff --git a/tracing/tracing/extras/chrome/cc/layer_tree_host_impl.html b/tracing/tracing/extras/chrome/cc/layer_tree_host_impl.html
index 3ae9314..5ee04c7 100644
--- a/tracing/tracing/extras/chrome/cc/layer_tree_host_impl.html
+++ b/tracing/tracing/extras/chrome/cc/layer_tree_host_impl.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/bbox2.html">
+<link rel="import" href="/tracing/base/math/bbox2.html">
 <link rel="import" href="/tracing/extras/chrome/cc/constants.html">
 <link rel="import" href="/tracing/extras/chrome/cc/layer_tree_impl.html">
 <link rel="import" href="/tracing/extras/chrome/cc/util.html">
@@ -163,7 +163,7 @@
     get allLayersBBox() {
       if (this.allLayersBBox_)
         return this.allLayersBBox_;
-      var bbox = new tr.b.BBox2();
+      var bbox = new tr.b.math.BBox2();
       function handleTree(tree) {
         tree.renderSurfaceLayerList.forEach(function(layer) {
           bbox.addQuad(layer.layerQuad);
diff --git a/tracing/tracing/extras/chrome/cc/picture.html b/tracing/tracing/extras/chrome/cc/picture.html
index b1b4678..64aea65 100644
--- a/tracing/tracing/extras/chrome/cc/picture.html
+++ b/tracing/tracing/extras/chrome/cc/picture.html
@@ -6,8 +6,8 @@
 -->
 
 <link rel="import" href="/tracing/base/guid.html">
+<link rel="import" href="/tracing/base/math/rect.html">
 <link rel="import" href="/tracing/base/raf.html">
-<link rel="import" href="/tracing/base/rect.html">
 <link rel="import" href="/tracing/extras/chrome/cc/picture_as_image_data.html">
 <link rel="import" href="/tracing/extras/chrome/cc/util.html">
 <link rel="import" href="/tracing/model/object_instance.html">
diff --git a/tracing/tracing/extras/chrome/cc/region.html b/tracing/tracing/extras/chrome/cc/region.html
index ff53d56..e9b986c 100644
--- a/tracing/tracing/extras/chrome/cc/region.html
+++ b/tracing/tracing/extras/chrome/cc/region.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/rect.html">
+<link rel="import" href="/tracing/base/math/rect.html">
 <script>
 'use strict';
 
@@ -23,7 +23,7 @@
 
     var r = new Region();
     for (var i = 0; i < array.length; i += 4) {
-      r.rects.push(tr.b.Rect.fromXYWH(array[i], array[i + 1],
+      r.rects.push(tr.b.math.Rect.fromXYWH(array[i], array[i + 1],
           array[i + 2], array[i + 3]));
     }
     return r;
diff --git a/tracing/tracing/extras/chrome/cc/render_pass.html b/tracing/tracing/extras/chrome/cc/render_pass.html
index e80c807..d34863a 100644
--- a/tracing/tracing/extras/chrome/cc/render_pass.html
+++ b/tracing/tracing/extras/chrome/cc/render_pass.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/rect.html">
+<link rel="import" href="/tracing/base/math/rect.html">
 <link rel="import" href="/tracing/extras/chrome/cc/util.html">
 <link rel="import" href="/tracing/model/object_instance.html">
 
diff --git a/tracing/tracing/extras/chrome/cc/tile.html b/tracing/tracing/extras/chrome/cc/tile.html
index e325aef..6708089 100644
--- a/tracing/tracing/extras/chrome/cc/tile.html
+++ b/tracing/tracing/extras/chrome/cc/tile.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/rect.html">
+<link rel="import" href="/tracing/base/math/rect.html">
 <link rel="import" href="/tracing/extras/chrome/cc/debug_colors.html">
 <link rel="import" href="/tracing/extras/chrome/cc/util.html">
 <link rel="import" href="/tracing/model/object_instance.html">
diff --git a/tracing/tracing/extras/chrome/cc/util.html b/tracing/tracing/extras/chrome/cc/util.html
index 37784df..cdc024e 100644
--- a/tracing/tracing/extras/chrome/cc/util.html
+++ b/tracing/tracing/extras/chrome/cc/util.html
@@ -5,8 +5,8 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/quad.html">
-<link rel="import" href="/tracing/base/rect.html">
+<link rel="import" href="/tracing/base/math/quad.html">
+<link rel="import" href="/tracing/base/math/rect.html">
 <link rel="import" href="/tracing/model/object_instance.html">
 <script>
 
@@ -111,22 +111,22 @@
         key = newKey;
       }
 
-      // Convert objects with keys ending with Quad to tr.b.Quad type.
-      if (/Quad$/.test(key) && !(object[key] instanceof tr.b.Quad)) {
+      // Convert objects with keys ending with Quad to tr.b.math.Quad type.
+      if (/Quad$/.test(key) && !(object[key] instanceof tr.b.math.Quad)) {
         var q;
         try {
-          q = tr.b.Quad.from8Array(object[key]);
+          q = tr.b.math.Quad.from8Array(object[key]);
         } catch (e) {
         }
         object[key] = q;
         continue;
       }
 
-      // Convert objects with keys ending with Rect to tr.b.Rect type.
-      if (/Rect$/.test(key) && !(object[key] instanceof tr.b.Rect)) {
+      // Convert objects with keys ending with Rect to tr.b.math.Rect type.
+      if (/Rect$/.test(key) && !(object[key] instanceof tr.b.math.Rect)) {
         var r;
         try {
-          r = tr.b.Rect.fromArray(object[key]);
+          r = tr.b.math.Rect.fromArray(object[key]);
         } catch (e) {
         }
         object[key] = r;
diff --git a/tracing/tracing/extras/chrome/cc/util_test.html b/tracing/tracing/extras/chrome/cc/util_test.html
index ed9ff69..ff620ae 100644
--- a/tracing/tracing/extras/chrome/cc/util_test.html
+++ b/tracing/tracing/extras/chrome/cc/util_test.html
@@ -5,8 +5,8 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/quad.html">
-<link rel="import" href="/tracing/base/rect.html">
+<link rel="import" href="/tracing/base/math/quad.html">
+<link rel="import" href="/tracing/base/math/rect.html">
 <link rel="import" href="/tracing/extras/chrome/cc/util.html">
 
 <script>
@@ -70,7 +70,7 @@
       }
     };
     tr.e.cc.preInitializeObject(object);
-    assert.instanceOf(object.args.someQuad, tr.b.Quad);
+    assert.instanceOf(object.args.someQuad, tr.b.math.Quad);
   });
 
   test('quadConversionNested', function() {
@@ -83,8 +83,8 @@
       }
     };
     tr.e.cc.preInitializeObject(object);
-    assert.instanceOf(object.args.nestedField.aQuad, tr.b.Quad);
-    assert.instanceOf(object.args.nonNestedQuad, tr.b.Quad);
+    assert.instanceOf(object.args.nestedField.aQuad, tr.b.math.Quad);
+    assert.instanceOf(object.args.nonNestedQuad, tr.b.math.Quad);
   });
 
   test('rectCoversion', function() {
@@ -94,7 +94,7 @@
       }
     };
     tr.e.cc.preInitializeObject(object);
-    assert.instanceOf(object.args.someRect, tr.b.Rect);
+    assert.instanceOf(object.args.someRect, tr.b.math.Rect);
   });
 
   test('rectCoversionNested', function() {
@@ -107,8 +107,8 @@
       }
     };
     tr.e.cc.preInitializeObject(object);
-    assert.instanceOf(object.args.nestedField.aRect, tr.b.Rect);
-    assert.instanceOf(object.args.nonNestedRect, tr.b.Rect);
+    assert.instanceOf(object.args.nestedField.aRect, tr.b.math.Rect);
+    assert.instanceOf(object.args.nonNestedRect, tr.b.math.Rect);
   });
 });
 </script>
diff --git a/tracing/tracing/extras/chrome/chrome_auditor.html b/tracing/tracing/extras/chrome/chrome_auditor.html
index 2d6658b..44b4208 100644
--- a/tracing/tracing/extras/chrome/chrome_auditor.html
+++ b/tracing/tracing/extras/chrome/chrome_auditor.html
@@ -6,7 +6,7 @@
 -->
 
 <link rel="import" href="/tracing/base/base.html">
-<link rel="import" href="/tracing/base/range_utils.html">
+<link rel="import" href="/tracing/base/math/range_utils.html">
 <link rel="import" href="/tracing/core/auditor.html">
 <link rel="import"
     href="/tracing/extras/chrome/cc/input_latency_async_slice.html">
diff --git a/tracing/tracing/extras/chrome/estimated_input_latency.html b/tracing/tracing/extras/chrome/estimated_input_latency.html
index dd26567..18f0732 100644
--- a/tracing/tracing/extras/chrome/estimated_input_latency.html
+++ b/tracing/tracing/extras/chrome/estimated_input_latency.html
@@ -70,7 +70,7 @@
    * @param {!Array.<number>} interactiveTimestamps
    * @param {!Array.<number>} navStartTimestamps
    * @param {!number} traceEndTimestamp
-   * @returns {!Array.<tr.b.Range>}
+   * @returns {!Array.<tr.b.math.Range>}
    */
   function getPostInteractiveTaskWindows(
       interactiveTimestamps, navStartTimestamps, traceEndTimestamp) {
@@ -99,7 +99,7 @@
             'PostInteractiveTaskWindow is not well defined in this case.');
       }
 
-      taskWindows.push(tr.b.Range.fromExplicitRange(
+      taskWindows.push(tr.b.math.Range.fromExplicitRange(
           currTTI, taskWindowEndTs));
       lastTaskWindowEndTs = taskWindowEndTs;
     }
@@ -120,7 +120,7 @@
    * We assume that input arrival time is uniformly distributed in the given
    * time window.
    *
-   * @param {!tr.b.Range} A time window.
+   * @param {!tr.b.math.Range} A time window.
    * @param {!Array.<!{start: number, end: number, weight: number}>} A list of
    *        weighted tasks. The weight of a task must be between 0.0 and 1.0.
    * @returns {number}
@@ -153,7 +153,7 @@
    * We assume that input arrival time is uniformly distributed in the given
    * time window.
    *
-   * @param {!tr.b.Range} A time window.
+   * @param {!tr.b.math.Range} A time window.
    * @param {!Array.<!{start: number, end: number, weight: number}>} A list of
    *        weighted tasks. The weight of a task must be between 0.0 and 1.0.
    * @returns {number}
@@ -170,7 +170,7 @@
    * Returns expected queueing time for the given time window and
    * the given set of tasks. The tasks must not overlap.
    *
-   * @param {!tr.b.Range} A time window.
+   * @param {!tr.b.math.Range} A time window.
    * @param {!Array.<!{start: number, end: number}>} A list of tasks.
    * @returns {number}
    */
@@ -202,9 +202,9 @@
        */
       this.sortedTasks_ = sortedTasks;
       /**
-       * @private {!tr.b.Range} The endpoints of the sliding window.
+       * @private {!tr.b.math.Range} The endpoints of the sliding window.
        */
-      this.range_ = tr.b.Range.fromExplicitRange(
+      this.range_ = tr.b.math.Range.fromExplicitRange(
           startTime, startTime + windowSize);
       /**
        * @private {number} The index of the first task in the sortedTasks that
@@ -258,7 +258,7 @@
      * @param {number} The time.
      */
     slide(t) {
-      this.range_ = tr.b.Range.fromExplicitRange(t, t + this.windowSize_);
+      this.range_ = tr.b.math.Range.fromExplicitRange(t, t + this.windowSize_);
       if (this.firstTaskIndex_ < this.sortedTasks_.length &&
           this.sortedTasks_[this.firstTaskIndex_].end <= t) {
         // The first task moved out of the window.
diff --git a/tracing/tracing/extras/chrome/estimated_input_latency_test.html b/tracing/tracing/extras/chrome/estimated_input_latency_test.html
index 1edf5f4..da8e3d0 100644
--- a/tracing/tracing/extras/chrome/estimated_input_latency_test.html
+++ b/tracing/tracing/extras/chrome/estimated_input_latency_test.html
@@ -178,7 +178,7 @@
     var windows = getPostInteractiveTaskWindows(
         interactiveTimestamps, navStartTimestamps, traceEndTimestamp);
     assert.equal(windows.length, 1);
-    assertRangeEquals(windows[0], tr.b.Range.fromExplicitRange(50, 100));
+    assertRangeEquals(windows[0], tr.b.math.Range.fromExplicitRange(50, 100));
   });
 
   test('multiplePostInteractiveWindows', () => {
@@ -188,8 +188,8 @@
     var windows = getPostInteractiveTaskWindows(
         interactiveTimestamps, navStartTimestamps, traceEndTimestamp);
     assert.equal(windows.length, 2);
-    assertRangeEquals(windows[0], tr.b.Range.fromExplicitRange(50, 70));
-    assertRangeEquals(windows[1], tr.b.Range.fromExplicitRange(80, 100));
+    assertRangeEquals(windows[0], tr.b.math.Range.fromExplicitRange(50, 70));
+    assertRangeEquals(windows[1], tr.b.math.Range.fromExplicitRange(80, 100));
   });
 
   test('postInteractiveWindowWithOneNavigationNeverReachingInteractive', () => {
@@ -199,8 +199,8 @@
     var windows = getPostInteractiveTaskWindows(
         interactiveTimestamps, navStartTimestamps, traceEndTimestamp);
     assert.equal(windows.length, 2);
-    assertRangeEquals(windows[0], tr.b.Range.fromExplicitRange(50, 60));
-    assertRangeEquals(windows[1], tr.b.Range.fromExplicitRange(90, 100));
+    assertRangeEquals(windows[0], tr.b.math.Range.fromExplicitRange(50, 60));
+    assertRangeEquals(windows[1], tr.b.math.Range.fromExplicitRange(90, 100));
   });
 
   test('twoInteractiveTimeStampsWithNoNavStartInBetween', () => {
@@ -212,40 +212,40 @@
   });
 
   test('expectedQueueingTime_noTasks', () => {
-    var window = tr.b.Range.fromExplicitRange(0, 1000);
+    var window = tr.b.math.Range.fromExplicitRange(0, 1000);
     assert.closeTo(0, expectedQueueingTime(window, []), 1e-6);
   });
 
   test('expectedQueueingTime_singleTask', () => {
-    var window = tr.b.Range.fromExplicitRange(0, 1000);
+    var window = tr.b.math.Range.fromExplicitRange(0, 1000);
     assert.closeTo(1000 / 2,
         expectedQueueingTime(window, [{start: 0, end: 1000}]),
         1e-6);
   });
 
   test('expectedQueueingTime_singleTaskStartingBeforeWindow', () => {
-    var window = tr.b.Range.fromExplicitRange(0, 1000);
+    var window = tr.b.math.Range.fromExplicitRange(0, 1000);
     assert.closeTo(1000 / 2,
         expectedQueueingTime(window, [{start: -1, end: 1000}]),
         1e-6);
   });
 
   test('expectedQueueingTime_singleTaskEndingAfterWindow', () => {
-    var window = tr.b.Range.fromExplicitRange(0, 1000);
+    var window = tr.b.math.Range.fromExplicitRange(0, 1000);
     assert.closeTo(1500,
         expectedQueueingTime(window, [{start: 0, end: 2000}]),
         1e-6);
   });
 
   test('expectedQueueingTime_singleTaskInsideWindow', () => {
-    var window = tr.b.Range.fromExplicitRange(0, 1000);
+    var window = tr.b.math.Range.fromExplicitRange(0, 1000);
     assert.closeTo(10 / 1000 * 10 / 2,
         expectedQueueingTime(window, [{start: 500, end: 510}]),
         1e-6);
   });
 
   test('expectedQueueingTime_twoTasksInsideWindow', () => {
-    var window = tr.b.Range.fromExplicitRange(0, 1000);
+    var window = tr.b.math.Range.fromExplicitRange(0, 1000);
     assert.closeTo(10 / 1000 * 10 / 2 + 100 / 1000 * 100 / 2,
         expectedQueueingTime(window,
             [{start: 500, end: 510}, {start: 600, end: 700}]),
@@ -253,7 +253,7 @@
   });
 
   test('expectedQueueingTime_twoTasksPartiallyInsideWindow', () => {
-    var window = tr.b.Range.fromExplicitRange(0, 1000);
+    var window = tr.b.math.Range.fromExplicitRange(0, 1000);
     assert.closeTo(10 / 1000 * 10 / 2 + 100 / 1000 * (100 + 200) / 2,
         expectedQueueingTime(window,
             [{start: 500, end: 510}, {start: 900, end: 1100}]),
@@ -261,7 +261,7 @@
   });
 
   test('weightedExpectedQueueingTime', () => {
-    var window = tr.b.Range.fromExplicitRange(0, 1000);
+    var window = tr.b.math.Range.fromExplicitRange(0, 1000);
     assert.closeTo(1000 / 2 * 0.7,
         weightedExpectedQueueingTime(window,
             [{start: 0, end: 1000, weight: 0.7}]),
diff --git a/tracing/tracing/extras/chrome/layout_object.html b/tracing/tracing/extras/chrome/layout_object.html
index f23a181..e9528ab 100644
--- a/tracing/tracing/extras/chrome/layout_object.html
+++ b/tracing/tracing/extras/chrome/layout_object.html
@@ -46,9 +46,9 @@
     this.childLayoutObjects_ = [];
     this.otherProperties_ = {};
     this.tag_ = args.tag;
-    this.relativeRect_ = tr.b.Rect.fromXYWH(
+    this.relativeRect_ = tr.b.math.Rect.fromXYWH(
         args.relX, args.relY, args.width, args.height);
-    this.absoluteRect_ = tr.b.Rect.fromXYWH(
+    this.absoluteRect_ = tr.b.math.Rect.fromXYWH(
         args.absX, args.absY, args.width, args.height);
     this.isFloat_ = args.float;
     this.isStickyPositioned_ = args.stickyPositioned;
diff --git a/tracing/tracing/extras/cpu/cpu_usage_auditor.html b/tracing/tracing/extras/cpu/cpu_usage_auditor.html
index 3c42fe6..0282cf2 100644
--- a/tracing/tracing/extras/cpu/cpu_usage_auditor.html
+++ b/tracing/tracing/extras/cpu/cpu_usage_auditor.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/math.html">
+<link rel="import" href="/tracing/base/math/math.html">
 <link rel="import" href="/tracing/core/auditor.html">
 <link rel="import" href="/tracing/model/resource_usage_series.html">
 
@@ -93,7 +93,7 @@
               e.cpuSelfTime === undefined) {
             continue;
           }
-          var usage = tr.b.clamp(e.cpuSelfTime / e.selfTime, 0, 1);
+          var usage = tr.b.math.clamp(e.cpuSelfTime / e.selfTime, 0, 1);
 
           // Go through the area covered by this slice but not its subslices
           // and add the cpuSelfTimeRatio contribution over this area.
diff --git a/tracing/tracing/extras/importer/android/event_log_importer.html b/tracing/tracing/extras/importer/android/event_log_importer.html
index 40f6d5e..74ab069 100644
--- a/tracing/tracing/extras/importer/android/event_log_importer.html
+++ b/tracing/tracing/extras/importer/android/event_log_importer.html
@@ -196,7 +196,7 @@
       var process = this.model_.getOrCreateProcess(activity.pid);
       // The range of the activity is the time from resume to time
       // of pause; limit the start time to the beginning of the model
-      var range = tr.b.Range.fromExplicitRange(
+      var range = tr.b.math.Range.fromExplicitRange(
           Math.max(this.model_.bounds.min, activity.lastResumeTs),
           activity.lastPauseTs);
       var newActivity = new tr.model.Activity(activity.name,
diff --git a/tracing/tracing/extras/importer/trace_code_map.html b/tracing/tracing/extras/importer/trace_code_map.html
index ec159f5..53180d4 100644
--- a/tracing/tracing/extras/importer/trace_code_map.html
+++ b/tracing/tracing/extras/importer/trace_code_map.html
@@ -80,7 +80,7 @@
       if (this.entries_.length === 0)
         return undefined;
 
-      var index = tr.b.findLowIndexInSortedArray(
+      var index = tr.b.math.findLowIndexInSortedArray(
           this.entries_, function(entry) { return entry.address; }, address);
       var entry = this.entries_[index];
       if (!entry || entry.address !== address)
@@ -91,7 +91,7 @@
     },
 
     lookupEntry: function(address) {
-      var index = tr.b.findHighIndexInSortedArray(
+      var index = tr.b.math.findHighIndexInSortedArray(
           this.entries_, function(e) { return address - e.address; }) - 1;
       var entry = this.entries_[index];
       return entry &&
@@ -105,7 +105,7 @@
         this.entries_.push(newEntry);
 
       var endAddress = newEntry.address + newEntry.size;
-      var lastIndex = tr.b.findLowIndexInSortedArray(
+      var lastIndex = tr.b.math.findLowIndexInSortedArray(
           this.entries_, function(entry) { return entry.address; }, endAddress);
       var index;
       for (index = lastIndex - 1; index >= 0; --index) {
diff --git a/tracing/tracing/extras/importer/trace_event_importer.html b/tracing/tracing/extras/importer/trace_event_importer.html
index 1441550..980505a 100644
--- a/tracing/tracing/extras/importer/trace_event_importer.html
+++ b/tracing/tracing/extras/importer/trace_event_importer.html
@@ -7,7 +7,7 @@
 
 <link rel="import" href="/tracing/base/base64.html">
 <link rel="import" href="/tracing/base/color_scheme.html">
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/base/scalar.html">
 <link rel="import" href="/tracing/base/unit.html">
 <link rel="import" href="/tracing/base/utils.html">
@@ -2373,7 +2373,7 @@
       // the events, all of which have the same dump ID.
 
       // Calculate the range of the global memory dump.
-      var globalRange = new tr.b.Range();
+      var globalRange = new tr.b.math.Range();
       for (var pid in dumpIdEvents) {
         var processEvents = dumpIdEvents[pid];
         for (var i = 0; i < processEvents.length; i++)
@@ -2425,7 +2425,7 @@
         globalMemoryAllocatorDumpsByFullName, levelsOfDetail,
         allMemoryAllocatorDumpsByGuid, processEvents, pid, dumpId) {
       // Calculate the range of the process memory dump.
-      var processRange = new tr.b.Range();
+      var processRange = new tr.b.math.Range();
       for (var i = 0; i < processEvents.length; i++)
         processRange.addValue(this.toModelTimeFromUs_(processEvents[i].ts));
       if (processRange.isEmpty)
diff --git a/tracing/tracing/importer/find_input_expectations.html b/tracing/tracing/importer/find_input_expectations.html
index d755179..992d054 100644
--- a/tracing/tracing/importer/find_input_expectations.html
+++ b/tracing/tracing/importer/find_input_expectations.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range_utils.html">
+<link rel="import" href="/tracing/base/math/range_utils.html">
 <link rel="import" href="/tracing/extras/chrome/cc/input_latency_async_slice.html">
 <link rel="import" href="/tracing/importer/proto_expectation.html">
 <link rel="import" href="/tracing/model/user_model/user_expectation.html">
@@ -796,7 +796,7 @@
     // This helper function will be called when a time range is found
     // during which the animation is actually running.
     function pushAnimationRange(start, end, animation) {
-      var range = tr.b.Range.fromExplicitRange(start, end);
+      var range = tr.b.math.Range.fromExplicitRange(start, end);
       range.animation = animation;
       animationRanges.push(range);
     }
@@ -1181,7 +1181,7 @@
       var frameEvents = [];
       // TODO(benjhayden): Use frame blame contexts here.
       for (var pid of Object.keys(modelHelper.rendererHelpers)) {
-        var range = tr.b.Range.fromExplicitRange(pe.start, pe.end);
+        var range = tr.b.math.Range.fromExplicitRange(pe.start, pe.end);
         frameEvents.push.apply(frameEvents,
             range.filterArray(frameEventsByPid[pid], e => e.start));
       }
diff --git a/tracing/tracing/importer/proto_expectation.html b/tracing/tracing/importer/proto_expectation.html
index fd326b5..939fad1 100644
--- a/tracing/tracing/importer/proto_expectation.html
+++ b/tracing/tracing/importer/proto_expectation.html
@@ -6,7 +6,7 @@
 -->
 
 <link rel="import" href="/tracing/base/base.html">
-<link rel="import" href="/tracing/base/range_utils.html">
+<link rel="import" href="/tracing/base/math/range_utils.html">
 <link rel="import" href="/tracing/core/auditor.html">
 <link rel="import" href="/tracing/model/event_info.html">
 <link rel="import" href="/tracing/model/user_model/animation_expectation.html">
diff --git a/tracing/tracing/importer/user_model_builder.html b/tracing/tracing/importer/user_model_builder.html
index 41a919f..b2722e8 100644
--- a/tracing/tracing/importer/user_model_builder.html
+++ b/tracing/tracing/importer/user_model_builder.html
@@ -6,7 +6,7 @@
 -->
 
 <link rel="import" href="/tracing/base/base.html">
-<link rel="import" href="/tracing/base/range_utils.html">
+<link rel="import" href="/tracing/base/math/range_utils.html">
 <link rel="import" href="/tracing/core/auditor.html">
 <link rel="import" href="/tracing/extras/chrome/cc/input_latency_async_slice.html">
 <link rel="import" href="/tracing/importer/find_input_expectations.html">
@@ -80,10 +80,10 @@
         var segment = new tr.model.um.Segment(
             timestamps[i], timestamps[i + 1] - timestamps[i]);
         segments.push(segment);
-        var segmentRange = tr.b.Range.fromExplicitRange(
+        var segmentRange = tr.b.math.Range.fromExplicitRange(
             segment.start, segment.end);
         for (var expectation of this.model.userModel.expectations) {
-          var expectationRange = tr.b.Range.fromExplicitRange(
+          var expectationRange = tr.b.math.Range.fromExplicitRange(
               expectation.start, expectation.end);
           if (segmentRange.intersectsRangeExclusive(expectationRange)) {
             segment.expectations.push(expectation);
@@ -156,8 +156,8 @@
     findIdleExpectations(otherUEs) {
       if (this.model.bounds.isEmpty) return;
 
-      var emptyRanges = tr.b.findEmptyRangesBetweenRanges(
-          tr.b.convertEventsToRanges(otherUEs),
+      var emptyRanges = tr.b.math.findEmptyRangesBetweenRanges(
+          tr.b.math.convertEventsToRanges(otherUEs),
           this.model.bounds);
       var expectations = [];
       var model = this.model;
diff --git a/tracing/tracing/metrics/blink/gc_metric.html b/tracing/tracing/metrics/blink/gc_metric.html
index 0507869..4b8731d 100644
--- a/tracing/tracing/metrics/blink/gc_metric.html
+++ b/tracing/tracing/metrics/blink/gc_metric.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/base/unit.html">
 <link rel="import" href="/tracing/metrics/metric_registry.html">
 <link rel="import" href="/tracing/metrics/v8/utils.html">
diff --git a/tracing/tracing/metrics/compare_samples_cmdline.html b/tracing/tracing/metrics/compare_samples_cmdline.html
index c0a7d4e..0b557e1 100644
--- a/tracing/tracing/metrics/compare_samples_cmdline.html
+++ b/tracing/tracing/metrics/compare_samples_cmdline.html
@@ -6,7 +6,7 @@
 -->
 
 <link rel="import" href="/tracing/base/iteration_helpers.html">
-<link rel="import" href="/tracing/base/statistics.html">
+<link rel="import" href="/tracing/base/math/statistics.html">
 <link rel="import" href="/tracing/base/xhr.html">
 <link rel="import" href="/tracing/value/histogram_set.html">
 
@@ -84,7 +84,7 @@
             'list_of_scalar_values') {
           if (charts.charts[chartName][traceName].values === null)
             continue;
-          allValues.push(tr.b.Statistics.mean(
+          allValues.push(tr.b.math.Statistics.mean(
               charts.charts[chartName][traceName].values));
         }
         if (charts.charts[chartName][traceName].type === 'histogram')
@@ -227,12 +227,12 @@
 var buildComparisonResultOutput = function(a, b) {
   if (!a.length || !b.length) {
     var comparisonResult = {
-      significance: tr.b.Statistics.Significance.NEED_MORE_DATA
+      significance: tr.b.math.Statistics.Significance.NEED_MORE_DATA
     };
   } else {
-    var comparisonResult = tr.b.Statistics.mwu(
-        a, b, tr.b.Statistics.DEFAULT_ALPHA,
-        tr.b.Statistics.MAX_SUGGESTED_SAMPLE_SIZE);
+    var comparisonResult = tr.b.math.Statistics.mwu(
+        a, b, tr.b.math.Statistics.DEFAULT_ALPHA,
+        tr.b.math.Statistics.MAX_SUGGESTED_SAMPLE_SIZE);
   }
   return {
     sampleA: a,
diff --git a/tracing/tracing/metrics/sample_metric.html b/tracing/tracing/metrics/sample_metric.html
index 533733d..6e34bae 100644
--- a/tracing/tracing/metrics/sample_metric.html
+++ b/tracing/tracing/metrics/sample_metric.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/metrics/metric_registry.html">
 <link rel="import" href="/tracing/value/histogram.html">
 
diff --git a/tracing/tracing/metrics/spa_navigation_metric.html b/tracing/tracing/metrics/spa_navigation_metric.html
index 4a20d23..357251f 100644
--- a/tracing/tracing/metrics/spa_navigation_metric.html
+++ b/tracing/tracing/metrics/spa_navigation_metric.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/metrics/metric_registry.html">
 <link rel="import" href="/tracing/metrics/spa_navigation_helper.html">
 <link rel="import" href="/tracing/value/histogram.html">
diff --git a/tracing/tracing/metrics/system_health/cpu_time_metric.html b/tracing/tracing/metrics/system_health/cpu_time_metric.html
index d9f5302..778bdf6 100644
--- a/tracing/tracing/metrics/system_health/cpu_time_metric.html
+++ b/tracing/tracing/metrics/system_health/cpu_time_metric.html
@@ -66,7 +66,8 @@
             return;
           if (!slice.cpuDuration)
             return;
-          var sliceRange = tr.b.Range.fromExplicitRange(slice.start, slice.end);
+          var sliceRange = tr.b.math.Range.fromExplicitRange(
+              slice.start, slice.end);
           var intersection = rangeOfInterest.findIntersection(sliceRange);
           var fractionOfSliceInsideRangeOfInterest =
               intersection.duration / slice.duration;
diff --git a/tracing/tracing/metrics/system_health/cpu_time_metric_test.html b/tracing/tracing/metrics/system_health/cpu_time_metric_test.html
index bff1689..0038e3d 100644
--- a/tracing/tracing/metrics/system_health/cpu_time_metric_test.html
+++ b/tracing/tracing/metrics/system_health/cpu_time_metric_test.html
@@ -90,7 +90,7 @@
   test('cpuTimeMetric_oneProcess_rangeOfInterest', function() {
     var sliceDuration = 50;
     var totalDuration = 3000;
-    var rangeOfInterest = new tr.b.Range.fromExplicitRange(-10, 30);
+    var rangeOfInterest = new tr.b.math.Range.fromExplicitRange(-10, 30);
     var options = {};
     options.rangeOfInterest = rangeOfInterest;
     var value = computeCpuTime(function(model) {
diff --git a/tracing/tracing/metrics/system_health/expected_queueing_time_metric.html b/tracing/tracing/metrics/system_health/expected_queueing_time_metric.html
index aa090f6..a34e0ac 100644
--- a/tracing/tracing/metrics/system_health/expected_queueing_time_metric.html
+++ b/tracing/tracing/metrics/system_health/expected_queueing_time_metric.html
@@ -125,7 +125,7 @@
         continue;
       }
       const interactiveWindow =
-          tr.b.Range.fromExplicitRange(interactiveTimestamps[0], Infinity)
+          tr.b.math.Range.fromExplicitRange(interactiveTimestamps[0], Infinity)
           .findIntersection(rendererHelper.mainThread.bounds);
       interactiveHistogram.addSample(
           tr.e.chrome.maxExpectedQueueingTimeInSlidingWindow(
@@ -247,7 +247,7 @@
         continue;
       }
       const interactiveWindow =
-          tr.b.Range.fromExplicitRange(interactiveTimestamps[0], Infinity)
+          tr.b.math.Range.fromExplicitRange(interactiveTimestamps[0], Infinity)
           .findIntersection(rendererHelper.mainThread.bounds);
       interactiveHistogram.addSample(
           tr.e.chrome.maxExpectedQueueingTimeInSlidingWindow(
diff --git a/tracing/tracing/metrics/system_health/loading_metric.html b/tracing/tracing/metrics/system_health/loading_metric.html
index 89439cb..dabd832 100644
--- a/tracing/tracing/metrics/system_health/loading_metric.html
+++ b/tracing/tracing/metrics/system_health/loading_metric.html
@@ -6,7 +6,7 @@
 -->
 
 <link rel="import" href="/tracing/base/category_util.html">
-<link rel="import" href="/tracing/base/statistics.html">
+<link rel="import" href="/tracing/base/math/statistics.html">
 <link rel="import" href="/tracing/metrics/metric_registry.html">
 <link rel="import" href="/tracing/metrics/system_health/utils.html">
 <link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
@@ -215,8 +215,8 @@
 
   function addFirstMeaningfulPaintCpuTimeSample(samples, rendererHelper,
       frameIdRef, navigationStart, fmpMarkerEvent) {
-    var rangeOfInterest = tr.b.Range.fromExplicitRange(navigationStart.cpuStart,
-        fmpMarkerEvent.cpuStart);
+    var rangeOfInterest = tr.b.math.Range.fromExplicitRange(
+        navigationStart.cpuStart, fmpMarkerEvent.cpuStart);
     var snapshot = findFrameLoaderSnapshotAt(
         rendererHelper, frameIdRef, fmpMarkerEvent.start);
     if (!snapshot || !snapshot.args.isLoadingMainFrame) return;
@@ -249,7 +249,7 @@
     var mainThreadCpuTime = 0;
     for (var slice of rendererHelper.mainThread.sliceGroup.topLevelSlices) {
       if (!slice.cpuDuration) continue;
-      var sliceRange = tr.b.Range.fromExplicitRange(slice.cpuStart,
+      var sliceRange = tr.b.math.Range.fromExplicitRange(slice.cpuStart,
           slice.cpuStart + slice.cpuDuration);
       var intersection = rangeOfInterest.findIntersection(sliceRange);
       mainThreadCpuTime += intersection.duration;
diff --git a/tracing/tracing/metrics/system_health/long_tasks_metric.html b/tracing/tracing/metrics/system_health/long_tasks_metric.html
index 0e156a9..9ae18c5 100644
--- a/tracing/tracing/metrics/system_health/long_tasks_metric.html
+++ b/tracing/tracing/metrics/system_health/long_tasks_metric.html
@@ -25,7 +25,7 @@
    * given thread in the given range whose duration is longer than LONG_TASK_MS.
    *
    * @param {tr.model.Thread} thread
-   * @param {tr.b.Range=} opt_range
+   * @param {tr.b.math.Range=} opt_range
    * @param {function()} cb
    * @param {Object=} opt_this
    */
diff --git a/tracing/tracing/metrics/system_health/memory_metric.html b/tracing/tracing/metrics/system_health/memory_metric.html
index 7e6067d..e7291f5 100644
--- a/tracing/tracing/metrics/system_health/memory_metric.html
+++ b/tracing/tracing/metrics/system_health/memory_metric.html
@@ -6,8 +6,8 @@
 -->
 
 <link rel="import" href="/tracing/base/iteration_helpers.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/base/multi_dimensional_view.html">
-<link rel="import" href="/tracing/base/range.html">
 <link rel="import" href="/tracing/base/unit.html">
 <link rel="import" href="/tracing/metrics/metric_registry.html">
 <link rel="import" href="/tracing/metrics/system_health/chrome_processes.html">
@@ -68,8 +68,8 @@
    *
    * @param {!tr.Model} model The trace model from which the global dumps
    *     should be extracted.
-   * @param {!tr.b.Range=} opt_rangeOfInterest If proided, global memory dumps
-   *     that do not inclusively intersect the range will be skipped.
+   * @param {!tr.b.math.Range=} opt_rangeOfInterest If proided, global memory
+   *     dumps that do not inclusively intersect the range will be skipped.
    * @return {!Map<string, !Array<!tr.model.GlobalMemoryDump>} A map from
    *     browser names to the associated global memory dumps.
    */
diff --git a/tracing/tracing/metrics/system_health/memory_metric_test.html b/tracing/tracing/metrics/system_health/memory_metric_test.html
index e13d7d6..c04e56b 100644
--- a/tracing/tracing/metrics/system_health/memory_metric_test.html
+++ b/tracing/tracing/metrics/system_health/memory_metric_test.html
@@ -6,7 +6,7 @@
 -->
 
 <link rel="import" href="/tracing/base/iteration_helpers.html">
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/core/test_utils.html">
 <link rel="import" href="/tracing/metrics/system_health/memory_metric.html">
 <link rel="import" href="/tracing/model/container_memory_dump.html">
@@ -3291,7 +3291,7 @@
     addGlobalMemoryDump(model, {ts: 9, duration: 12, levelOfDetail: LIGHT});
     addGlobalMemoryDump(model, {ts: 22, duration: 3, levelOfDetail: DETAILED});
   }, {  /* opt_options */
-    rangeOfInterest: tr.b.Range.fromExplicitRange(10, 20)
+    rangeOfInterest: tr.b.math.Range.fromExplicitRange(10, 20)
   }, {
     'memory:chrome:all_processes:dump_count': {
       value: [3],
diff --git a/tracing/tracing/metrics/system_health/power_metric.html b/tracing/tracing/metrics/system_health/power_metric.html
index b8559b8..27d9e78 100644
--- a/tracing/tracing/metrics/system_health/power_metric.html
+++ b/tracing/tracing/metrics/system_health/power_metric.html
@@ -5,8 +5,8 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range.html">
-<link rel="import" href="/tracing/base/statistics.html">
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/math/statistics.html">
 <link rel="import" href="/tracing/base/unit_scale.html">
 <link rel="import" href="/tracing/importer/find_input_expectations.html">
 <link rel="import" href="/tracing/metrics/metric_registry.html">
@@ -82,7 +82,7 @@
           rendererHelper).firstInteractiveSamples;
       for (var sample of samples) {
         var info = sample.diagnostics['Navigation infos'].value;
-        intervals.push(tr.b.Range.fromExplicitRange(
+        intervals.push(tr.b.math.Range.fromExplicitRange(
             info.start, info.interactive));
       }
     }
@@ -134,7 +134,7 @@
    * in the following form:
    *
    *   {
-   *     bounds {tr.b.Range}: Boundaries of the time interval.
+   *     bounds {tr.b.math.Range}: Boundaries of the time interval.
    *     name {string}: Name of this interval. Used to generate the
    *       metric names.
    *     description {string}: Human readable description of the interval.
@@ -165,7 +165,7 @@
     var chromeBounds = computeChromeBounds_(model);
     if (chromeBounds.isEmpty) return;
 
-    var powerSeriesBoundsWithGracePeriod = tr.b.Range.fromExplicitRange(
+    var powerSeriesBoundsWithGracePeriod = tr.b.math.Range.fromExplicitRange(
         powerSeries.bounds.min - CHROME_POWER_GRACE_PERIOD_MS,
         powerSeries.bounds.max + CHROME_POWER_GRACE_PERIOD_MS);
     if (!powerSeriesBoundsWithGracePeriod.containsRangeExclusive(
@@ -204,7 +204,7 @@
    * in the following form:
    *
    *   {
-   *     bounds {tr.b.Range}: Boundaries of the time interval.
+   *     bounds {tr.b.math.Range}: Boundaries of the time interval.
    *     name {string}: Name of this interval. Used to generate the
    *       metric names.
    *     description {string}: Human readable description of the interval.
@@ -221,7 +221,7 @@
       var energyHist = undefined;
       if (histogramName.includes('response')) {
         yield {
-          bounds: tr.b.Range.fromExplicitRange(exp.start, exp.end),
+          bounds: tr.b.math.Range.fromExplicitRange(exp.start, exp.end),
           name: histogramName,
           description: 'RAIL stage ' + histogramName,
           perSecond: false
@@ -229,7 +229,7 @@
       } else if (histogramName.includes('animation') ||
           histogramName.includes('idle')) {
         yield {
-          bounds: tr.b.Range.fromExplicitRange(exp.start, exp.end),
+          bounds: tr.b.math.Range.fromExplicitRange(exp.start, exp.end),
           name: histogramName,
           description: 'RAIL stage ' + histogramName,
           perSecond: true
@@ -246,7 +246,7 @@
    * in the following form:
    *
    *   {
-   *     bounds {tr.b.Range}: Boundaries of the time interval.
+   *     bounds {tr.b.math.Range}: Boundaries of the time interval.
    *     name {string}: Name of this interval. Used to generate the
    *       metric names.
    *     description {string}: Human readable description of the interval.
@@ -272,7 +272,7 @@
     }
     if (lastLoadTime !== undefined) {
       yield {
-        bounds: tr.b.Range.fromExplicitRange(
+        bounds: tr.b.math.Range.fromExplicitRange(
             lastLoadTime, chromeBounds.max),
         name: 'after_load',
         description: 'period after load',
@@ -282,10 +282,11 @@
   }
 
   /**
-   * @returns {tr.b.Range} The boundaries of the Chrome portion of the trace.
+   * @returns {tr.b.math.Range} The boundaries of the Chrome portion of the
+   * trace.
    */
   function computeChromeBounds_(model) {
-    var chromeBounds = new tr.b.Range();
+    var chromeBounds = new tr.b.math.Range();
     var chromeHelper = model.getOrCreateHelper(
         tr.model.helpers.ChromeModelHelper);
     if (chromeHelper === undefined) return chromeBounds;
diff --git a/tracing/tracing/metrics/system_health/responsiveness_metric.html b/tracing/tracing/metrics/system_health/responsiveness_metric.html
index e1a4ab3..89309cc 100644
--- a/tracing/tracing/metrics/system_health/responsiveness_metric.html
+++ b/tracing/tracing/metrics/system_health/responsiveness_metric.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/statistics.html">
+<link rel="import" href="/tracing/base/math/statistics.html">
 <link rel="import" href="/tracing/metrics/metric_registry.html">
 <link rel="import" href="/tracing/metrics/system_health/utils.html">
 <link rel="import" href="/tracing/model/user_model/animation_expectation.html">
@@ -51,7 +51,8 @@
     });
 
     var absolute = true;
-    return tr.b.Statistics.timestampsDiscrepancy(frameTimestamps, absolute);
+    return tr.b.math.Statistics.timestampsDiscrepancy(
+        frameTimestamps, absolute);
   }
 
   /**
diff --git a/tracing/tracing/metrics/system_health/utils.html b/tracing/tracing/metrics/system_health/utils.html
index 459f955..5edbb63 100644
--- a/tracing/tracing/metrics/system_health/utils.html
+++ b/tracing/tracing/metrics/system_health/utils.html
@@ -12,8 +12,8 @@
 tr.exportTo('tr.metrics.sh', function() {
   // Returns a weight for this score.
   // score should be a number between 0 and 1 inclusive.
-  // This function is expected to be passed to tr.b.Statistics.weightedMean as
-  // its weightCallback.
+  // This function is expected to be passed to tr.b.math.Statistics.weightedMean
+  // as its weightCallback.
   function perceptualBlend(ir, index, score) {
     // Lower scores are exponentially more important than higher scores
     // due to the Peak-end rule.
diff --git a/tracing/tracing/metrics/v8/execution_metric.html b/tracing/tracing/metrics/v8/execution_metric.html
index 619065d..2d4bf19 100644
--- a/tracing/tracing/metrics/v8/execution_metric.html
+++ b/tracing/tracing/metrics/v8/execution_metric.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/base/unit.html">
 <link rel="import" href="/tracing/metrics/metric_registry.html">
 <link rel="import" href="/tracing/value/histogram.html">
diff --git a/tracing/tracing/metrics/v8/gc_metric.html b/tracing/tracing/metrics/v8/gc_metric.html
index 377997a..2dcd8fe 100644
--- a/tracing/tracing/metrics/v8/gc_metric.html
+++ b/tracing/tracing/metrics/v8/gc_metric.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/base/unit.html">
 <link rel="import" href="/tracing/metrics/metric_registry.html">
 <link rel="import" href="/tracing/metrics/v8/utils.html">
diff --git a/tracing/tracing/metrics/v8/runtime_stats_metric.html b/tracing/tracing/metrics/v8/runtime_stats_metric.html
index 9624821..3973a4e 100644
--- a/tracing/tracing/metrics/v8/runtime_stats_metric.html
+++ b/tracing/tracing/metrics/v8/runtime_stats_metric.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/base/unit.html">
 <link rel="import" href="/tracing/extras/v8/runtime_stats_entry.html">
 <link rel="import" href="/tracing/metrics/metric_registry.html">
diff --git a/tracing/tracing/metrics/v8/utils.html b/tracing/tracing/metrics/v8/utils.html
index 79c3af2..b394de7 100644
--- a/tracing/tracing/metrics/v8/utils.html
+++ b/tracing/tracing/metrics/v8/utils.html
@@ -6,9 +6,9 @@
 -->
 
 <link rel="import" href="/tracing/base/category_util.html">
-<link rel="import" href="/tracing/base/piecewise_linear_function.html">
-<link rel="import" href="/tracing/base/range.html">
-<link rel="import" href="/tracing/base/range_utils.html">
+<link rel="import" href="/tracing/base/math/piecewise_linear_function.html">
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/math/range_utils.html">
 <link rel="import" href="/tracing/base/unit.html">
 <link rel="import" href="/tracing/metrics/metric_registry.html">
 <link rel="import" href="/tracing/value/histogram.html">
@@ -185,7 +185,7 @@
   function unionOfIntervals(intervals) {
     if (intervals.length === 0)
       return [];
-    return tr.b.mergeRanges(
+    return tr.b.math.mergeRanges(
         intervals.map(x => { return { min: x.start, max: x.end }; }), 1e-6,
         function(ranges) {
           return {
@@ -210,8 +210,8 @@
         model.globalMemoryDumps.filter(hasV8Stats).reduce(
             (start, dump) => Math.min(start, dump.start), Infinity);
     if (startOfFirstDumpWithV8 === Infinity)
-      return new tr.b.Range(); // Empty range.
-    return tr.b.Range.fromExplicitRange(startOfFirstDumpWithV8, Infinity);
+      return new tr.b.math.Range(); // Empty range.
+    return tr.b.math.Range.fromExplicitRange(startOfFirstDumpWithV8, Infinity);
   }
 
   return {
diff --git a/tracing/tracing/metrics/webrtc/webrtc_rendering_metric.html b/tracing/tracing/metrics/webrtc/webrtc_rendering_metric.html
index 8747508..cccedf0 100644
--- a/tracing/tracing/metrics/webrtc/webrtc_rendering_metric.html
+++ b/tracing/tracing/metrics/webrtc/webrtc_rendering_metric.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/base/unit.html">
 <link rel="import" href="/tracing/base/utils.html">
 <link rel="import" href="/tracing/metrics/metric_registry.html">
@@ -266,7 +266,7 @@
       oldIdealRender = currentIdealRender;
     }
 
-    let discrepancySum = tr.b.Statistics.sum(discrepancy) - discrepancy[0];
+    let discrepancySum = tr.b.math.Statistics.sum(discrepancy) - discrepancy[0];
     let lastIdealRender =
         events[events.length - 1].args[IDEAL_RENDER_INSTANT_NAME];
     let firstIdealRender = events[0].args[IDEAL_RENDER_INSTANT_NAME];
@@ -293,7 +293,7 @@
    * percentOutOfSync and smoothnesScore calculated from the driftTimes array.
    */
   function getSmoothnessStats(driftTimes) {
-    let meanDriftTime = tr.b.Statistics.mean(driftTimes);
+    let meanDriftTime = tr.b.math.Statistics.mean(driftTimes);
     let normDriftTimes = driftTimes.map(driftTime =>
         Math.abs(driftTime - meanDriftTime));
 
diff --git a/tracing/tracing/metrics/webrtc/webrtc_rendering_metric_test.html b/tracing/tracing/metrics/webrtc/webrtc_rendering_metric_test.html
index 9d1b0c4..9b7af55 100644
--- a/tracing/tracing/metrics/webrtc/webrtc_rendering_metric_test.html
+++ b/tracing/tracing/metrics/webrtc/webrtc_rendering_metric_test.html
@@ -171,19 +171,21 @@
     // We don't have access to the values stored in the histogram, so we check
     // for equality in the summary statistics.
     let hist = histograms.getHistogramNamed('WebRTCRendering_drift_time');
-    assert.strictEqual(hist.sum, tr.b.Statistics.sum(fakeDriftTimes));
+    assert.strictEqual(hist.sum, tr.b.math.Statistics.sum(fakeDriftTimes));
     assert.strictEqual(hist.numValues, fakeDriftTimes.length);
-    assert.strictEqual(hist.running.min, tr.b.Statistics.min(fakeDriftTimes));
-    assert.strictEqual(hist.running.max, tr.b.Statistics.max(fakeDriftTimes));
+    assert.strictEqual(hist.running.min,
+        tr.b.math.Statistics.min(fakeDriftTimes));
+    assert.strictEqual(hist.running.max,
+        tr.b.math.Statistics.max(fakeDriftTimes));
     assert.closeTo(hist.standardDeviation,
-        tr.b.Statistics.stddev(fakeDriftTimes), 1e-2);
+        tr.b.math.Statistics.stddev(fakeDriftTimes), 1e-2);
   });
 
   test('framesBadlyOutOfSyncPerfect', function() {
     // None of these will exceed the threshold for badly out of sync events,
     // which is about 33 333.
     let normDriftTimes = [-16700, 17640, 15000, -17640, -15000, 16700];
-    assert.strictEqual(tr.b.Statistics.sum(normDriftTimes), 0);
+    assert.strictEqual(tr.b.math.Statistics.sum(normDriftTimes), 0);
     let fakeEvents = eventsFromNormDriftTimes(normDriftTimes);
     let histograms = runWebrtcRenderingMetric(fakeEvents);
 
@@ -197,7 +199,7 @@
     // Only 34 000 will exceed the threshold for badly out of sync events,
     // which is about 33 333.
     let normDriftTimes = [-34000, 10000, 10000, 10000, 4000];
-    assert.strictEqual(tr.b.Statistics.sum(normDriftTimes), 0);
+    assert.strictEqual(tr.b.math.Statistics.sum(normDriftTimes), 0);
     let fakeEvents = eventsFromNormDriftTimes(normDriftTimes);
     let histograms = runWebrtcRenderingMetric(fakeEvents);
 
@@ -211,7 +213,7 @@
     // None of these will exceed the threshold for badly out of sync, which is
     // about 16 667.
     let normDriftTimes = [-16600, 15640, 15000, -15640, -15000, 16600];
-    assert.strictEqual(tr.b.Statistics.sum(normDriftTimes), 0);
+    assert.strictEqual(tr.b.math.Statistics.sum(normDriftTimes), 0);
     let fakeEvents = eventsFromNormDriftTimes(normDriftTimes);
     let histograms = runWebrtcRenderingMetric(fakeEvents);
 
@@ -225,7 +227,7 @@
     // Only 17000 will exceed the threshold for badly out of sync, which is
     // about 16 667.
     let normDriftTimes = [-17000, 5000, 5000, 5000, 2000];
-    assert.strictEqual(tr.b.Statistics.sum(normDriftTimes), 0);
+    assert.strictEqual(tr.b.math.Statistics.sum(normDriftTimes), 0);
     let fakeEvents = eventsFromNormDriftTimes(normDriftTimes);
     let histograms = runWebrtcRenderingMetric(fakeEvents);
 
@@ -239,7 +241,7 @@
     // None of these will exceed the threshold for badly out of sync events,
     // which is about 33 333.
     let normDriftTimes = [-16700, 17640, 15000, -17640, -15000, 16700];
-    assert.strictEqual(tr.b.Statistics.sum(normDriftTimes), 0);
+    assert.strictEqual(tr.b.math.Statistics.sum(normDriftTimes), 0);
     let fakeEvents = eventsFromNormDriftTimes(normDriftTimes);
     let histograms = runWebrtcRenderingMetric(fakeEvents);
 
@@ -253,7 +255,7 @@
     // Only 34 000 will exceed the threshold for badly out of sync events,
     // which is about 33 333.
     let normDriftTimes = [-34000, 10000, 10000, 10000, 4000];
-    assert.strictEqual(tr.b.Statistics.sum(normDriftTimes), 0);
+    assert.strictEqual(tr.b.math.Statistics.sum(normDriftTimes), 0);
     let fakeEvents = eventsFromNormDriftTimes(normDriftTimes);
     let histograms = runWebrtcRenderingMetric(fakeEvents);
 
@@ -267,7 +269,7 @@
     // None of these will exceed the threshold for badly out of sync, which is
     // about 16 667.
     let normDriftTimes = [-16600, 15640, 15000, -15640, -15000, 16600];
-    assert.strictEqual(tr.b.Statistics.sum(normDriftTimes), 0);
+    assert.strictEqual(tr.b.math.Statistics.sum(normDriftTimes), 0);
     let fakeEvents = eventsFromNormDriftTimes(normDriftTimes);
     let histograms = runWebrtcRenderingMetric(fakeEvents);
 
@@ -281,7 +283,7 @@
     // Only 17000 will exceed the threshold for badly out of sync, which is
     // about 16 667.
     let normDriftTimes = [-17000, 5000, 5000, 5000, 2000];
-    assert.strictEqual(tr.b.Statistics.sum(normDriftTimes), 0);
+    assert.strictEqual(tr.b.math.Statistics.sum(normDriftTimes), 0);
     let fakeEvents = eventsFromNormDriftTimes(normDriftTimes);
     let histograms = runWebrtcRenderingMetric(fakeEvents);
 
@@ -295,7 +297,7 @@
     // None of these will exceed the threshold for badly out of sync, which is
     // about 16 667, so the smoothnessScore wil be perfect.
     let normDriftTimes = [-16600, 15640, 15000, -15640, -15000, 16600];
-    assert.strictEqual(tr.b.Statistics.sum(normDriftTimes), 0);
+    assert.strictEqual(tr.b.math.Statistics.sum(normDriftTimes), 0);
     let fakeEvents = eventsFromNormDriftTimes(normDriftTimes);
     let histograms = runWebrtcRenderingMetric(fakeEvents);
 
@@ -311,7 +313,7 @@
     // 1 - (frames out of sync + 3 * frames badly out of sync) / n
     //   = 1 - (2 + 3) / 5 = 0
     let normDriftTimes = [-17000, 34000, -17000, -10000, 10000];
-    assert.strictEqual(tr.b.Statistics.sum(normDriftTimes), 0);
+    assert.strictEqual(tr.b.math.Statistics.sum(normDriftTimes), 0);
     let fakeEvents = eventsFromNormDriftTimes(normDriftTimes);
     let histograms = runWebrtcRenderingMetric(fakeEvents);
 
@@ -435,7 +437,7 @@
     // The rendering length error is then the sum of the errors, normalized by
     // the span between the first and the last Ideal Render Instants.
     let idealRenderSpan = fakePairs[fakePairs.length - 1][0] - fakePairs[0][0];
-    let expectedRenderingLengthError = tr.b.Statistics.sum(errors) /
+    let expectedRenderingLengthError = tr.b.math.Statistics.sum(errors) /
       idealRenderSpan;
 
     let fakeEvents = fakePairs.map(eventFromPair);
diff --git a/tracing/tracing/model/async_slice_group.html b/tracing/tracing/model/async_slice_group.html
index f962217..e5066ef 100644
--- a/tracing/tracing/model/async_slice_group.html
+++ b/tracing/tracing/model/async_slice_group.html
@@ -6,7 +6,7 @@
 -->
 
 <link rel="import" href="/tracing/base/guid.html">
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/model/async_slice.html">
 <link rel="import" href="/tracing/model/event_container.html">
 
diff --git a/tracing/tracing/model/counter.html b/tracing/tracing/model/counter.html
index 8d26cda..469f4e0 100644
--- a/tracing/tracing/model/counter.html
+++ b/tracing/tracing/model/counter.html
@@ -6,7 +6,7 @@
 -->
 
 <link rel="import" href="/tracing/base/guid.html">
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/model/counter_series.html">
 <link rel="import" href="/tracing/model/event_container.html">
 
diff --git a/tracing/tracing/model/counter_sample.html b/tracing/tracing/model/counter_sample.html
index e01cb4f..624530b 100644
--- a/tracing/tracing/model/counter_sample.html
+++ b/tracing/tracing/model/counter_sample.html
@@ -6,7 +6,7 @@
 -->
 
 <link rel="import" href="/tracing/base/iteration_helpers.html">
-<link rel="import" href="/tracing/base/sorted_array_utils.html">
+<link rel="import" href="/tracing/base/math/sorted_array_utils.html">
 <link rel="import" href="/tracing/base/unit.html">
 <link rel="import" href="/tracing/model/event.html">
 <link rel="import" href="/tracing/model/event_registry.html">
@@ -75,7 +75,7 @@
     },
 
     getSampleIndex: function() {
-      return tr.b.findLowIndexInSortedArray(
+      return tr.b.math.findLowIndexInSortedArray(
           this.series.timestamps,
           function(x) { return x; },
           this.timestamp_);
diff --git a/tracing/tracing/model/cpu.html b/tracing/tracing/model/cpu.html
index 1ab71d5..51e7916 100644
--- a/tracing/tracing/model/cpu.html
+++ b/tracing/tracing/model/cpu.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/model/counter.html">
 <link rel="import" href="/tracing/model/cpu_slice.html">
 <link rel="import" href="/tracing/model/process_base.html">
@@ -33,7 +33,7 @@
     this.cpuNumber = number;
     this.slices = [];
     this.counters = {};
-    this.bounds_ = new tr.b.Range();
+    this.bounds_ = new tr.b.math.Range();
     this.samples_ = undefined; // Set during createSubSlices
 
     // Start timestamp of the last active thread.
@@ -150,7 +150,7 @@
      * Returns the index of the slice in the CPU's slices, or undefined.
      */
     indexOf: function(cpuSlice) {
-      var i = tr.b.findLowIndexInSortedArray(
+      var i = tr.b.math.findLowIndexInSortedArray(
           this.slices,
           function(slice) { return slice.start; },
           cpuSlice.start);
@@ -226,7 +226,7 @@
         var freqEnd = (index < freqSample.series_.length - 1) ?
             freqSample.series_.samples_[index + 1].timestamp : range.max;
 
-        var freqRange = tr.b.Range.fromExplicitRange(freqSample.timestamp,
+        var freqRange = tr.b.math.Range.fromExplicitRange(freqSample.timestamp,
             freqEnd);
         var intersection = freqRange.findIntersection(range);
         if (!(freqSample.value in stats))
@@ -240,7 +240,7 @@
         if (!freqSeries)
           return;
 
-        tr.b.iterateOverIntersectingIntervals(freqSeries.samples_,
+        tr.b.math.iterateOverIntersectingIntervals(freqSeries.samples_,
             function(x) { return x.timestamp; },
             function(x, index) {
               if (index < freqSeries.length - 1) {
diff --git a/tracing/tracing/model/cpu_slice.html b/tracing/tracing/model/cpu_slice.html
index 53c266c..f42704b 100644
--- a/tracing/tracing/model/cpu_slice.html
+++ b/tracing/tracing/model/cpu_slice.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/model/thread_time_slice.html">
 
 <script>
diff --git a/tracing/tracing/model/cpu_test.html b/tracing/tracing/model/cpu_test.html
index 06c406d..7db87f5 100644
--- a/tracing/tracing/model/cpu_test.html
+++ b/tracing/tracing/model/cpu_test.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/core/test_utils.html">
 <link rel="import" href="/tracing/model/model.html">
 
@@ -191,7 +191,7 @@
     series.addCounterSample(80, 500000);
     series.addCounterSample(100, 300000);
 
-    var range = tr.b.Range.fromExplicitRange(10, 90);
+    var range = tr.b.math.Range.fromExplicitRange(10, 90);
     var stats = cpu.getFreqStatsForRange(range);
     assert.equal(stats[100000], 60);
     assert.equal(stats[300000], 10);
diff --git a/tracing/tracing/model/device.html b/tracing/tracing/model/device.html
index 9c8134f..20b81b2 100644
--- a/tracing/tracing/model/device.html
+++ b/tracing/tracing/model/device.html
@@ -6,7 +6,8 @@
 -->
 
 <link rel="import" href="/tracing/base/guid.html">
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/model/cpu.html">
 <link rel="import" href="/tracing/model/event_container.html">
 <link rel="import" href="/tracing/model/power_series.html">
 
diff --git a/tracing/tracing/model/event.html b/tracing/tracing/model/event.html
index e3a87a0..c087609 100644
--- a/tracing/tracing/model/event.html
+++ b/tracing/tracing/model/event.html
@@ -6,7 +6,7 @@
 -->
 
 <link rel="import" href="/tracing/base/guid.html">
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/model/event_set.html">
 <link rel="import" href="/tracing/model/selectable_item.html">
 <link rel="import" href="/tracing/model/selection_state.html">
@@ -48,7 +48,7 @@
     },
 
     get range() {
-      var range = new tr.b.Range();
+      var range = new tr.b.math.Range();
       this.addBoundsToRange(range);
       return range;
     },
diff --git a/tracing/tracing/model/event_container.html b/tracing/tracing/model/event_container.html
index aebe5f8..fa01a6d 100644
--- a/tracing/tracing/model/event_container.html
+++ b/tracing/tracing/model/event_container.html
@@ -7,7 +7,7 @@
 
 <link rel="import" href="/tracing/base/base.html">
 <link rel="import" href="/tracing/base/guid.html">
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 
 <script>
 'use strict';
@@ -25,7 +25,7 @@
   function EventContainer() {
     this.guid_ = tr.b.GUID.allocateSimple();
     this.important = true;
-    this.bounds_ = new tr.b.Range();
+    this.bounds_ = new tr.b.math.Range();
   }
 
   EventContainer.prototype = {
diff --git a/tracing/tracing/model/event_set.html b/tracing/tracing/model/event_set.html
index 91c98eb..d2dfd52 100644
--- a/tracing/tracing/model/event_set.html
+++ b/tracing/tracing/model/event_set.html
@@ -8,7 +8,7 @@
 <link rel="import" href="/tracing/base/event.html">
 <link rel="import" href="/tracing/base/guid.html">
 <link rel="import" href="/tracing/base/iteration_helpers.html">
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/model/event_registry.html">
 
 <script>
@@ -25,7 +25,7 @@
    * @constructor
    */
   function EventSet(opt_events) {
-    this.bounds_ = new tr.b.Range();
+    this.bounds_ = new tr.b.math.Range();
     this.events_ = new Set();
     this.guid_ = tr.b.GUID.allocateSimple();
 
@@ -68,7 +68,7 @@
     },
 
     clear: function() {
-      this.bounds_ = new tr.b.Range();
+      this.bounds_ = new tr.b.math.Range();
       this.events_.clear();
     },
 
diff --git a/tracing/tracing/model/frame.html b/tracing/tracing/model/frame.html
index cd02f23..8274e7e 100644
--- a/tracing/tracing/model/frame.html
+++ b/tracing/tracing/model/frame.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 <link rel="import" href="/tracing/base/color_scheme.html">
-<link rel="import" href="/tracing/base/statistics.html">
+<link rel="import" href="/tracing/base/math/statistics.html">
 <link rel="import" href="/tracing/model/event.html">
 <link rel="import" href="/tracing/model/event_set.html">
 
@@ -20,7 +20,7 @@
  */
 tr.exportTo('tr.model', function() {
   var ColorScheme = tr.b.ColorScheme;
-  var Statistics = tr.b.Statistics;
+  var Statistics = tr.b.math.Statistics;
 
   var FRAME_PERF_CLASS = {
     GOOD: 'good',
diff --git a/tracing/tracing/model/helpers/android_app.html b/tracing/tracing/model/helpers/android_app.html
index c2d4509..06e4b88 100644
--- a/tracing/tracing/model/helpers/android_app.html
+++ b/tracing/tracing/model/helpers/android_app.html
@@ -4,9 +4,9 @@
 Use of this source code is governed by a BSD-style license that can be
 found in the LICENSE file.
 -->
-<link rel="import" href="/tracing/base/range_utils.html">
-<link rel="import" href="/tracing/base/sorted_array_utils.html">
-<link rel="import" href="/tracing/base/statistics.html">
+<link rel="import" href="/tracing/base/math/range_utils.html">
+<link rel="import" href="/tracing/base/math/sorted_array_utils.html">
+<link rel="import" href="/tracing/base/math/statistics.html">
 <link rel="import" href="/tracing/model/frame.html">
 
 <script>
@@ -18,7 +18,7 @@
  */
 tr.exportTo('tr.model.helpers', function() {
   var Frame = tr.model.Frame;
-  var Statistics = tr.b.Statistics;
+  var Statistics = tr.b.math.Statistics;
 
   var UI_DRAW_TYPE = {
     NONE: 'none',
@@ -69,7 +69,7 @@
     // of all top level renderthread slices, find the one that has a 'sync'
     // within the uiDrawSlice
     var overlappingDrawFrame;
-    var slices = tr.b.iterateOverIntersectingIntervals(
+    var slices = tr.b.math.iterateOverIntersectingIntervals(
         renderThread.sliceGroup.slices,
         function(range) { return range.start; },
         function(range) { return range.end; },
@@ -114,8 +114,8 @@
         preFrameEvents.push(slice);
     });
 
-    return tr.b.mergeRanges(
-        tr.b.convertEventsToRanges(preFrameEvents),
+    return tr.b.math.mergeRanges(
+        tr.b.math.convertEventsToRanges(preFrameEvents),
         3,
         function(events) {
           return {
@@ -126,7 +126,7 @@
   }
 
   function getFrameStartTime(traversalStart, preTraversalWorkRanges) {
-    var preTraversalWorkRange = tr.b.findClosestIntervalInSortedIntervals(
+    var preTraversalWorkRange = tr.b.math.findClosestIntervalInSortedIntervals(
         preTraversalWorkRanges,
         function(range) { return range.start; },
         function(range) { return range.end; },
diff --git a/tracing/tracing/model/helpers/android_model_helper.html b/tracing/tracing/model/helpers/android_model_helper.html
index 3b13283..ab0e1b3 100644
--- a/tracing/tracing/model/helpers/android_model_helper.html
+++ b/tracing/tracing/model/helpers/android_model_helper.html
@@ -6,7 +6,7 @@
 -->
 
 <link rel="import" href="/tracing/base/guid.html">
-<link rel="import" href="/tracing/base/range_utils.html">
+<link rel="import" href="/tracing/base/math/range_utils.html">
 <link rel="import" href="/tracing/core/auditor.html">
 <link rel="import" href="/tracing/model/helpers/android_app.html">
 <link rel="import" href="/tracing/model/helpers/android_surface_flinger.html">
diff --git a/tracing/tracing/model/helpers/android_surface_flinger.html b/tracing/tracing/model/helpers/android_surface_flinger.html
index 1acf869..41f9fc7 100644
--- a/tracing/tracing/model/helpers/android_surface_flinger.html
+++ b/tracing/tracing/model/helpers/android_surface_flinger.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/sorted_array_utils.html">
+<link rel="import" href="/tracing/base/math/sorted_array_utils.html">
 
 <script>
 'use strict';
@@ -14,7 +14,7 @@
  * @fileoverview Class for representing SurfaceFlinger process and its Vsyncs.
  */
 tr.exportTo('tr.model.helpers', function() {
-  var findLowIndexInSortedArray = tr.b.findLowIndexInSortedArray;
+  var findLowIndexInSortedArray = tr.b.math.findLowIndexInSortedArray;
 
   var VSYNC_SF_NAME = 'android.VSYNC-sf';
   var VSYNC_APP_NAME = 'android.VSYNC-app';
diff --git a/tracing/tracing/model/helpers/chrome_browser_helper_test.html b/tracing/tracing/model/helpers/chrome_browser_helper_test.html
index 8c19e12..3cfd949 100644
--- a/tracing/tracing/model/helpers/chrome_browser_helper_test.html
+++ b/tracing/tracing/model/helpers/chrome_browser_helper_test.html
@@ -20,7 +20,7 @@
   var INPUT_TYPE = tr.e.cc.INPUT_EVENT_TYPE_NAMES;
 
   function getRange(min, max) {
-    var range = new tr.b.Range();
+    var range = new tr.b.math.Range();
     range.min = min;
     range.max = max;
     return range;
diff --git a/tracing/tracing/model/helpers/chrome_model_helper.html b/tracing/tracing/model/helpers/chrome_model_helper.html
index e454392..47e435f 100644
--- a/tracing/tracing/model/helpers/chrome_model_helper.html
+++ b/tracing/tracing/model/helpers/chrome_model_helper.html
@@ -150,7 +150,7 @@
      */
     get chromeBounds() {
       if (!this.chromeBounds_) {
-        this.chromeBounds_ = new tr.b.Range();
+        this.chromeBounds_ = new tr.b.math.Range();
         for (var browserHelper of
              tr.b.dictionaryValues(this.browserHelpers)) {
           this.chromeBounds_.addRange(browserHelper.process.bounds);
diff --git a/tracing/tracing/model/helpers/chrome_process_helper.html b/tracing/tracing/model/helpers/chrome_process_helper.html
index 7f3736d..c86714d 100644
--- a/tracing/tracing/model/helpers/chrome_process_helper.html
+++ b/tracing/tracing/model/helpers/chrome_process_helper.html
@@ -66,8 +66,8 @@
             start = slice.start;
           } else if (/^telemetry\.internal\.[^.]*\.end$/.test(slice.title) &&
               start !== undefined) {
-            this.telemetryInternalRanges_.push(tr.b.Range.fromExplicitRange(
-                start, slice.end));
+            this.telemetryInternalRanges_.push(
+                tr.b.math.Range.fromExplicitRange(start, slice.end));
             start = undefined;
           }
         }
diff --git a/tracing/tracing/model/helpers/chrome_renderer_helper.html b/tracing/tracing/model/helpers/chrome_renderer_helper.html
index fc61918..8e9af04 100644
--- a/tracing/tracing/model/helpers/chrome_renderer_helper.html
+++ b/tracing/tracing/model/helpers/chrome_renderer_helper.html
@@ -4,7 +4,7 @@
 Use of this source code is governed by a BSD-style license that can be
 found in the LICENSE file.
 -->
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/extras/chrome/chrome_user_friendly_category_driver.html">
 <link rel="import" href="/tracing/model/helpers/chrome_process_helper.html">
 
@@ -67,7 +67,7 @@
       getEventStart, getEventDuration, getEventSelfTime) {
     if (mainThread === null) return;
     var breakdownTree = {};
-    var range = tr.b.Range.fromExplicitRange(rangeStart, rangeEnd);
+    var range = tr.b.math.Range.fromExplicitRange(rangeStart, rangeEnd);
     for (var title of
         tr.e.chrome.ChromeUserFriendlyCategoryDriver.ALL_TITLES) {
       breakdownTree[title] = {total: 0, events: {}};
diff --git a/tracing/tracing/model/model.html b/tracing/tracing/model/model.html
index db9e0cf..33b43be 100644
--- a/tracing/tracing/model/model.html
+++ b/tracing/tracing/model/model.html
@@ -8,8 +8,8 @@
 <link rel="import" href="/tracing/base/base.html">
 <link rel="import" href="/tracing/base/event.html">
 <link rel="import" href="/tracing/base/interval_tree.html">
-<link rel="import" href="/tracing/base/quad.html">
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/quad.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/base/task.html">
 <link rel="import" href="/tracing/base/time_display_modes.html">
 <link rel="import" href="/tracing/base/unit.html">
@@ -617,7 +617,7 @@
 
         if ((object instanceof tr.model.ObjectSnapshot) ||
             (object instanceof Float32Array) ||
-            (object instanceof tr.b.Quad))
+            (object instanceof tr.b.math.Quad))
           return;
 
         if (object instanceof Array) {
diff --git a/tracing/tracing/model/object_collection.html b/tracing/tracing/model/object_collection.html
index 721d8a4..0a370cc 100644
--- a/tracing/tracing/model/object_collection.html
+++ b/tracing/tracing/model/object_collection.html
@@ -5,8 +5,8 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range.html">
-<link rel="import" href="/tracing/base/sorted_array_utils.html">
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/math/sorted_array_utils.html">
 <link rel="import" href="/tracing/base/utils.html">
 <link rel="import" href="/tracing/model/event_container.html">
 <link rel="import" href="/tracing/model/object_instance.html">
diff --git a/tracing/tracing/model/object_instance.html b/tracing/tracing/model/object_instance.html
index 72935e0..b4f1121 100644
--- a/tracing/tracing/model/object_instance.html
+++ b/tracing/tracing/model/object_instance.html
@@ -5,8 +5,8 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range.html">
-<link rel="import" href="/tracing/base/sorted_array_utils.html">
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/math/sorted_array_utils.html">
 <link rel="import" href="/tracing/model/event.html">
 <link rel="import" href="/tracing/model/object_snapshot.html">
 
@@ -38,7 +38,7 @@
     this.deletionTs = Number.MAX_VALUE;
     this.deletionTsWasExplicit = false;
     this.colorId = 0;
-    this.bounds = new tr.b.Range();
+    this.bounds = new tr.b.math.Range();
     this.snapshots = [];
     this.hasImplicitSnapshots = false;
   }
@@ -138,7 +138,7 @@
         throw new Error('ts must be within lifetime of this instance');
 
       var snapshots = this.snapshots;
-      var i = tr.b.findIndexInSortedIntervals(
+      var i = tr.b.math.findIndexInSortedIntervals(
           snapshots,
           function(snapshot) { return snapshot.ts; },
           function(snapshot, i) {
diff --git a/tracing/tracing/model/power_sample_test.html b/tracing/tracing/model/power_sample_test.html
index 78cf554..be9d2c6 100644
--- a/tracing/tracing/model/power_sample_test.html
+++ b/tracing/tracing/model/power_sample_test.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/model/model.html">
 <link rel="import" href="/tracing/model/power_sample.html">
 
@@ -36,7 +36,7 @@
     var sample1 = new PowerSample(series, 0.0, 1000.0);
     var sample2 = new PowerSample(series, 1.0, 2000.0);
 
-    var range = new tr.b.Range();
+    var range = new tr.b.math.Range();
     sample1.addBoundsToRange(range);
 
     assert.equal(range.min, 0);
diff --git a/tracing/tracing/model/power_series.html b/tracing/tracing/model/power_series.html
index af7f060..5e302fc 100644
--- a/tracing/tracing/model/power_series.html
+++ b/tracing/tracing/model/power_series.html
@@ -5,8 +5,8 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range.html">
-<link rel="import" href="/tracing/base/sorted_array_utils.html">
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/math/sorted_array_utils.html">
 <link rel="import" href="/tracing/base/unit_scale.html">
 <link rel="import" href="/tracing/model/event_container.html">
 <link rel="import" href="/tracing/model/power_sample.html">
@@ -61,12 +61,12 @@
      * start and end timestamps (in milliseconds).
      */
     getEnergyConsumedInJ: function(start, end) {
-      var measurementRange = tr.b.Range.fromExplicitRange(start, end);
+      var measurementRange = tr.b.math.Range.fromExplicitRange(start, end);
 
       var energyConsumedInJ = 0;
-      var startIndex = tr.b.findLowIndexInSortedArray(
+      var startIndex = tr.b.math.findLowIndexInSortedArray(
           this.samples, x => x.start, start) - 1;
-      var endIndex = tr.b.findLowIndexInSortedArray(
+      var endIndex = tr.b.math.findLowIndexInSortedArray(
           this.samples, x => x.start, end);
 
       if (startIndex < 0)
@@ -76,7 +76,7 @@
         var sample = this.samples[i];
         var nextSample = this.samples[i + 1];
 
-        var sampleRange = new tr.b.Range();
+        var sampleRange = new tr.b.math.Range();
         sampleRange.addValue(sample.start);
         sampleRange.addValue(nextSample ? nextSample.start : sample.start);
 
@@ -94,9 +94,9 @@
     },
 
     getSamplesWithinRange: function(start, end) {
-      var startIndex = tr.b.findLowIndexInSortedArray(
+      var startIndex = tr.b.math.findLowIndexInSortedArray(
           this.samples, x => x.start, start);
-      var endIndex = tr.b.findLowIndexInSortedArray(
+      var endIndex = tr.b.math.findLowIndexInSortedArray(
           this.samples, x => x.start, end);
       return this.samples.slice(startIndex, endIndex);
     },
diff --git a/tracing/tracing/model/process_base.html b/tracing/tracing/model/process_base.html
index f738509..1f8da58 100644
--- a/tracing/tracing/model/process_base.html
+++ b/tracing/tracing/model/process_base.html
@@ -6,7 +6,7 @@
 -->
 
 <link rel="import" href="/tracing/base/guid.html">
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/model/counter.html">
 <link rel="import" href="/tracing/model/event_container.html">
 <link rel="import" href="/tracing/model/object_collection.html">
diff --git a/tracing/tracing/model/resource_usage_sample_test.html b/tracing/tracing/model/resource_usage_sample_test.html
index 26e3338..af51aec 100644
--- a/tracing/tracing/model/resource_usage_sample_test.html
+++ b/tracing/tracing/model/resource_usage_sample_test.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/model/model.html">
 <link rel="import" href="/tracing/model/resource_usage_sample.html">
 
@@ -36,7 +36,7 @@
     var sample1 = new ResourceUsageSample(series, 0.0, 0.11);
     var sample2 = new ResourceUsageSample(series, 1.0, 0.22);
 
-    var range = new tr.b.Range();
+    var range = new tr.b.math.Range();
     sample1.addBoundsToRange(range);
 
     assert.equal(range.min, 0);
diff --git a/tracing/tracing/model/resource_usage_series.html b/tracing/tracing/model/resource_usage_series.html
index e9ba2f6..282278b 100644
--- a/tracing/tracing/model/resource_usage_series.html
+++ b/tracing/tracing/model/resource_usage_series.html
@@ -5,8 +5,8 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range.html">
-<link rel="import" href="/tracing/base/sorted_array_utils.html">
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/math/sorted_array_utils.html">
 <link rel="import" href="/tracing/base/unit_scale.html">
 <link rel="import" href="/tracing/model/event_container.html">
 <link rel="import" href="/tracing/model/resource_usage_sample.html">
@@ -59,12 +59,12 @@
      * the specified start and end timestamps (in milliseconds).
      */
     computeResourceTimeConsumedInMs(start, end) {
-      var measurementRange = tr.b.Range.fromExplicitRange(start, end);
+      var measurementRange = tr.b.math.Range.fromExplicitRange(start, end);
 
       var resourceTimeInMs = 0;
-      var startIndex = tr.b.findLowIndexInSortedArray(
+      var startIndex = tr.b.math.findLowIndexInSortedArray(
           this.samples, x => x.start, start) - 1;
-      var endIndex = tr.b.findLowIndexInSortedArray(
+      var endIndex = tr.b.math.findLowIndexInSortedArray(
           this.samples, x => x.start, end);
 
       if (startIndex < 0) startIndex = 0;
@@ -73,7 +73,7 @@
         var sample = this.samples[i];
         var nextSample = this.samples[i + 1];
 
-        var sampleRange = new tr.b.Range();
+        var sampleRange = new tr.b.math.Range();
         sampleRange.addValue(sample.start);
         sampleRange.addValue(nextSample ? nextSample.start : sample.start);
 
@@ -87,9 +87,9 @@
     }
 
     getSamplesWithinRange(start, end) {
-      var startIndex = tr.b.findLowIndexInSortedArray(
+      var startIndex = tr.b.math.findLowIndexInSortedArray(
           this.samples, x => x.start, start);
-      var endIndex = tr.b.findLowIndexInSortedArray(
+      var endIndex = tr.b.math.findLowIndexInSortedArray(
           this.samples, x => x.start, end);
       return this.samples.slice(startIndex, endIndex);
     }
diff --git a/tracing/tracing/model/slice_group.html b/tracing/tracing/model/slice_group.html
index f8e460c..adc695a 100644
--- a/tracing/tracing/model/slice_group.html
+++ b/tracing/tracing/model/slice_group.html
@@ -7,7 +7,7 @@
 
 <link rel="import" href="/tracing/base/color_scheme.html">
 <link rel="import" href="/tracing/base/guid.html">
-<link rel="import" href="/tracing/base/sorted_array_utils.html">
+<link rel="import" href="/tracing/base/math/sorted_array_utils.html">
 <link rel="import" href="/tracing/core/filter.html">
 <link rel="import" href="/tracing/model/event_container.html">
 <link rel="import" href="/tracing/model/thread_slice.html">
@@ -313,7 +313,7 @@
 
     iterSlicesInTimeRange: function(callback, start, end) {
       var ret = [];
-      tr.b.iterateOverIntersectingIntervals(
+      tr.b.math.iterateOverIntersectingIntervals(
           this.topLevelSlices,
           function(s) { return s.start; },
           function(s) { return s.duration; },
@@ -338,7 +338,7 @@
     findSliceAtTs: function(ts) {
       if (!this.haveTopLevelSlicesBeenBuilt)
         throw new Error('Nope');
-      var i = tr.b.findIndexInSortedClosedIntervals(
+      var i = tr.b.math.findIndexInSortedClosedIntervals(
           this.topLevelSlices,
           getSliceLo, getSliceHi,
           ts);
@@ -349,7 +349,7 @@
 
       // Now recurse on slice looking for subSlice of given ts.
       while (true) {
-        var i = tr.b.findIndexInSortedClosedIntervals(
+        var i = tr.b.math.findIndexInSortedClosedIntervals(
             curSlice.subSlices,
             getSliceLo, getSliceHi,
             ts);
@@ -360,7 +360,7 @@
     },
 
     findNextSliceAfter: function(ts, refGuid) {
-      var i = tr.b.findLowIndexInSortedArray(
+      var i = tr.b.math.findLowIndexInSortedArray(
           this.slices, getSliceLo, ts);
       if (i === this.slices.length)
         return undefined;
diff --git a/tracing/tracing/model/thread.html b/tracing/tracing/model/thread.html
index 8295d7f..1ae344e 100644
--- a/tracing/tracing/model/thread.html
+++ b/tracing/tracing/model/thread.html
@@ -6,7 +6,7 @@
 -->
 
 <link rel="import" href="/tracing/base/guid.html">
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/model/async_slice_group.html">
 <link rel="import" href="/tracing/model/event_container.html">
 <link rel="import" href="/tracing/model/slice_group.html">
@@ -225,7 +225,7 @@
      * Returns the index of the slice in the timeSlices array, or undefined.
      */
     indexOfTimeSlice: function(timeSlice) {
-      var i = tr.b.findLowIndexInSortedArray(
+      var i = tr.b.math.findLowIndexInSortedArray(
           this.timeSlices,
           function(slice) { return slice.start; },
           timeSlice.start);
@@ -249,7 +249,7 @@
         return stats;
 
       function addStatsForSlice(threadTimeSlice) {
-        var freqRange = tr.b.Range.fromExplicitRange(threadTimeSlice.start,
+        var freqRange = tr.b.math.Range.fromExplicitRange(threadTimeSlice.start,
             threadTimeSlice.end);
         var intersection = freqRange.findIntersection(range);
 
@@ -264,7 +264,7 @@
         }
       }
 
-      tr.b.iterateOverIntersectingIntervals(this.timeSlices,
+      tr.b.math.iterateOverIntersectingIntervals(this.timeSlices,
           function(x) { return x.start; },
           function(x) { return x.end; },
           range.min,
@@ -288,7 +288,7 @@
         stats[schedulingState] += overlapEnd - overlapStart;
       }
 
-      tr.b.iterateOverIntersectingIntervals(this.timeSlices,
+      tr.b.math.iterateOverIntersectingIntervals(this.timeSlices,
           function(x) { return x.start; },
           function(x) { return x.end; },
           start,
diff --git a/tracing/tracing/model/thread_test.html b/tracing/tracing/model/thread_test.html
index 953e30f..293e2bc 100644
--- a/tracing/tracing/model/thread_test.html
+++ b/tracing/tracing/model/thread_test.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/core/test_utils.html">
 <link rel="import" href="/tracing/model/model.html">
 
@@ -147,7 +147,7 @@
         newThreadSlice(thread, SCHEDULING_STATE.RUNNING, 8, 2, cpu1),
         newThreadSlice(thread, SCHEDULING_STATE.RUNNING, 20, 5, cpu1)
       ];
-      var range = tr.b.Range.fromExplicitRange(1, 22);
+      var range = tr.b.math.Range.fromExplicitRange(1, 22);
       var stats = thread.getCpuStatsForRange(range);
       assert.deepEqual(stats, {
         0: 2,
@@ -169,7 +169,7 @@
         newThreadSlice(thread, SCHEDULING_STATE.SLEEPING, 15, 10),
         newThreadSlice(thread, SCHEDULING_STATE.RUNNING, 25, 10, cpu1)
       ];
-      var range = tr.b.Range.fromExplicitRange(1, 26);
+      var range = tr.b.math.Range.fromExplicitRange(1, 26);
       var stats = thread.getCpuStatsForRange(range);
       assert.deepEqual(stats, {
         0: 7,
diff --git a/tracing/tracing/model/thread_time_slice.html b/tracing/tracing/model/thread_time_slice.html
index 1d835f2..e788978 100644
--- a/tracing/tracing/model/thread_time_slice.html
+++ b/tracing/tracing/model/thread_time_slice.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/model/slice.html">
 
 <script>
diff --git a/tracing/tracing/model/time_to_object_instance_map.html b/tracing/tracing/model/time_to_object_instance_map.html
index 274bee9..d8f1588 100644
--- a/tracing/tracing/model/time_to_object_instance_map.html
+++ b/tracing/tracing/model/time_to_object_instance_map.html
@@ -4,8 +4,8 @@
 Use of this source code is governed by a BSD-style license that can be
 found in the LICENSE file.
 -->
-<link rel="import" href="/tracing/base/range.html">
-<link rel="import" href="/tracing/base/sorted_array_utils.html">
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/math/sorted_array_utils.html">
 
 <script>
 'use strict';
@@ -59,7 +59,7 @@
             this.parent, this.scopedId, category, name, ts, opt_baseTypeName));
       }
 
-      var i = tr.b.findIndexInSortedIntervals(
+      var i = tr.b.math.findIndexInSortedIntervals(
           this.instances,
           function(inst) { return inst.creationTs; },
           function(inst) { return inst.deletionTs - inst.creationTs; },
@@ -154,7 +154,7 @@
     },
 
     getInstanceAt: function(ts) {
-      var i = tr.b.findIndexInSortedIntervals(
+      var i = tr.b.math.findIndexInSortedIntervals(
           this.instances,
           function(inst) { return inst.creationTs; },
           function(inst) { return inst.deletionTs - inst.creationTs; },
diff --git a/tracing/tracing/model/user_model/user_expectation.html b/tracing/tracing/model/user_model/user_expectation.html
index 6641dba..b4eb17e 100644
--- a/tracing/tracing/model/user_model/user_expectation.html
+++ b/tracing/tracing/model/user_model/user_expectation.html
@@ -5,8 +5,8 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range_utils.html">
-<link rel="import" href="/tracing/base/statistics.html">
+<link rel="import" href="/tracing/base/math/range_utils.html">
+<link rel="import" href="/tracing/base/math/statistics.html">
 <link rel="import" href="/tracing/base/unit.html">
 <link rel="import" href="/tracing/model/compound_event_selection_state.html">
 <link rel="import" href="/tracing/model/event_set.html">
diff --git a/tracing/tracing/ui/analysis/generic_object_view.html b/tracing/tracing/ui/analysis/generic_object_view.html
index d25516c..3ba32e4 100644
--- a/tracing/tracing/ui/analysis/generic_object_view.html
+++ b/tracing/tracing/ui/analysis/generic_object_view.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/rect.html">
+<link rel="import" href="/tracing/base/math/rect.html">
 <link rel="import" href="/tracing/base/scalar.html">
 <link rel="import" href="/tracing/base/utils.html">
 <link rel="import" href="/tracing/model/event_set.html">
@@ -166,7 +166,7 @@
       return;
     }
 
-    if (object instanceof tr.b.Rect) {
+    if (object instanceof tr.b.math.Rect) {
       this.appendSimpleText_(label, indent, object.toString(), suffix);
       return;
     }
diff --git a/tracing/tracing/ui/analysis/memory_dump_allocator_details_pane.html b/tracing/tracing/ui/analysis/memory_dump_allocator_details_pane.html
index 3dc9a18..a208266 100644
--- a/tracing/tracing/ui/analysis/memory_dump_allocator_details_pane.html
+++ b/tracing/tracing/ui/analysis/memory_dump_allocator_details_pane.html
@@ -6,7 +6,7 @@
 -->
 
 <link rel="import" href="/tracing/base/iteration_helpers.html">
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/base/unit.html">
 <link rel="import" href="/tracing/model/memory_allocator_dump.html">
 <link rel="import" href="/tracing/ui/analysis/memory_dump_heap_details_pane.html">
@@ -349,7 +349,7 @@
         map, dump, link, opt_withSharerNameToEntry) {
       var entry = getAndUpdateEntry(map, dump.quantifiedName,
           function(newEntry) {
-            newEntry.importanceRange = new tr.b.Range();
+            newEntry.importanceRange = new tr.b.math.Range();
             if (opt_withSharerNameToEntry)
               newEntry.sharerNameToEntry = new Map();
           });
diff --git a/tracing/tracing/ui/analysis/multi_event_sub_view.html b/tracing/tracing/ui/analysis/multi_event_sub_view.html
index d7e494a..a33b3b4 100644
--- a/tracing/tracing/ui/analysis/multi_event_sub_view.html
+++ b/tracing/tracing/ui/analysis/multi_event_sub_view.html
@@ -152,7 +152,7 @@
 
     buildHistogram_(selectedKey) {
       var leftBoundary = Number.MAX_VALUE;
-      var rightBoundary = tr.b.Statistics.percentile(
+      var rightBoundary = tr.b.math.Statistics.percentile(
           this.currentSelection_, 0.95,
           function(value) {
             leftBoundary = Math.min(leftBoundary, value[selectedKey]);
diff --git a/tracing/tracing/ui/analysis/multi_event_summary.html b/tracing/tracing/ui/analysis/multi_event_summary.html
index 5a10460..bbf0b06 100644
--- a/tracing/tracing/ui/analysis/multi_event_summary.html
+++ b/tracing/tracing/ui/analysis/multi_event_summary.html
@@ -7,7 +7,7 @@
 
 <link rel="import" href="/tracing/base/base.html">
 <link rel="import" href="/tracing/base/iteration_helpers.html">
-<link rel="import" href="/tracing/base/statistics.html">
+<link rel="import" href="/tracing/base/math/statistics.html">
 
 <script>
 'use strict';
@@ -44,7 +44,7 @@
 
     get duration() {
       if (this.duration_ === undefined) {
-        this.duration_ = tr.b.Statistics.sum(
+        this.duration_ = tr.b.math.Statistics.sum(
             this.events_, function(event) {
               return event.duration;
             });
@@ -107,9 +107,9 @@
 
     get numAlerts() {
       if (this.numAlerts_ === undefined) {
-        this.numAlerts_ = tr.b.Statistics.sum(this.events_, function(event) {
-          return event.associatedAlerts.length;
-        });
+        this.numAlerts_ = tr.b.math.Statistics.sum(this.events_, event =>
+          event.associatedAlerts.length
+        );
       }
       return this.numAlerts_;
     },
@@ -127,7 +127,7 @@
 
     get maxDuration() {
       if (this.maxDuration_ === undefined) {
-        this.maxDuration_ = tr.b.Statistics.max(
+        this.maxDuration_ = tr.b.math.Statistics.max(
             this.events_, function(event) {
               return event.duration;
             });
@@ -138,7 +138,7 @@
 
     get maxCpuDuration() {
       if (this.maxCpuDuration_ === undefined) {
-        this.maxCpuDuration_ = tr.b.Statistics.max(
+        this.maxCpuDuration_ = tr.b.math.Statistics.max(
             this.events_, function(event) {
               return event.cpuDuration;
             });
@@ -149,7 +149,7 @@
 
     get maxSelfTime() {
       if (this.maxSelfTime_ === undefined) {
-        this.maxSelfTime_ = tr.b.Statistics.max(
+        this.maxSelfTime_ = tr.b.math.Statistics.max(
             this.events_, function(event) {
               return event.selfTime;
             });
@@ -160,7 +160,7 @@
 
     get maxCpuSelfTime() {
       if (this.maxCpuSelfTime_ === undefined) {
-        this.maxCpuSelfTime_ = tr.b.Statistics.max(
+        this.maxCpuSelfTime_ = tr.b.math.Statistics.max(
             this.events_, function(event) {
               return event.cpuSelfTime;
             });
diff --git a/tracing/tracing/ui/analysis/multi_event_summary_table.html b/tracing/tracing/ui/analysis/multi_event_summary_table.html
index fcd506a..6fc55d7 100644
--- a/tracing/tracing/ui/analysis/multi_event_summary_table.html
+++ b/tracing/tracing/ui/analysis/multi_event_summary_table.html
@@ -7,8 +7,8 @@
 
 <link rel="import" href="/tracing/base/base.html">
 <link rel="import" href="/tracing/base/iteration_helpers.html">
-<link rel="import" href="/tracing/base/range.html">
-<link rel="import" href="/tracing/base/statistics.html">
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/math/statistics.html">
 <link rel="import" href="/tracing/base/unit.html">
 <link rel="import" href="/tracing/model/event_set.html">
 <link rel="import" href="/tracing/ui/analysis/analysis_link.html">
@@ -86,7 +86,7 @@
           return tr.v.ui.createScalarSpan(row.duration, {
             unit: tr.b.Unit.byName.timeDurationInMs,
             customContextRange: row.totalsRow ? undefined :
-                tr.b.Range.fromExplicitRange(0, maxValues.duration),
+                tr.b.math.Range.fromExplicitRange(0, maxValues.duration),
             ownerDocument: ownerDocument,
           });
         },
@@ -104,7 +104,7 @@
           return tr.v.ui.createScalarSpan(row.cpuDuration, {
             unit: tr.b.Unit.byName.timeDurationInMs,
             customContextRange: row.totalsRow ? undefined :
-                tr.b.Range.fromExplicitRange(0, maxValues.cpuDuration),
+                tr.b.math.Range.fromExplicitRange(0, maxValues.cpuDuration),
             ownerDocument: ownerDocument,
           });
         },
@@ -122,7 +122,7 @@
           return tr.v.ui.createScalarSpan(row.selfTime, {
             unit: tr.b.Unit.byName.timeDurationInMs,
             customContextRange: row.totalsRow ? undefined :
-                tr.b.Range.fromExplicitRange(0, maxValues.selfTime),
+                tr.b.math.Range.fromExplicitRange(0, maxValues.selfTime),
             ownerDocument: ownerDocument,
           });
         },
@@ -140,7 +140,7 @@
           return tr.v.ui.createScalarSpan(row.cpuSelfTime, {
             unit: tr.b.Unit.byName.timeDurationInMs,
             customContextRange: row.totalsRow ? undefined :
-                tr.b.Range.fromExplicitRange(0, maxValues.cpuSelfTime),
+                tr.b.math.Range.fromExplicitRange(0, maxValues.cpuSelfTime),
             ownerDocument: ownerDocument,
           });
         },
@@ -159,7 +159,7 @@
           return tr.v.ui.createScalarSpan(totalDuration / row.numEvents, {
             unit: tr.b.Unit.byName.timeDurationInMs,
             customContextRange: row.totalsRow ? undefined :
-                tr.b.Range.fromExplicitRange(0, maxValues.duration),
+                tr.b.math.Range.fromExplicitRange(0, maxValues.duration),
             ownerDocument: ownerDocument,
           });
         },
@@ -313,7 +313,7 @@
 
     if (this.eventsHaveDuration) {
       for (var column in maxValues) {
-        maxValues[column] = tr.b.Statistics.max(rows, function(event) {
+        maxValues[column] = tr.b.math.Statistics.max(rows, function(event) {
           return event[column];
         });
       }
diff --git a/tracing/tracing/ui/analysis/multi_object_sub_view.html b/tracing/tracing/ui/analysis/multi_object_sub_view.html
index 1077544..7856557 100644
--- a/tracing/tracing/ui/analysis/multi_object_sub_view.html
+++ b/tracing/tracing/ui/analysis/multi_object_sub_view.html
@@ -47,7 +47,7 @@
     this.currentSelection_ = selection;
 
     var objectEvents = tr.b.asArray(selection).sort(
-        tr.b.Range.compareByMinTimes);
+        tr.b.math.Range.compareByMinTimes);
 
     var timeSpanConfig = {
       unit: tr.b.Unit.byName.timeStampInMs,
diff --git a/tracing/tracing/ui/analysis/multi_sample_sub_view.html b/tracing/tracing/ui/analysis/multi_sample_sub_view.html
index 8b47adf..beff12a 100644
--- a/tracing/tracing/ui/analysis/multi_sample_sub_view.html
+++ b/tracing/tracing/ui/analysis/multi_sample_sub_view.html
@@ -5,8 +5,8 @@
 found in the LICENSE file.
 -->
 
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/base/multi_dimensional_view.html">
-<link rel="import" href="/tracing/base/range.html">
 <link rel="import" href="/tracing/base/unit.html">
 <link rel="import" href="/tracing/ui/analysis/analysis_sub_view.html">
 <link rel="import" href="/tracing/ui/base/table.html">
@@ -197,7 +197,7 @@
         value: function(row) {
           return tr.v.ui.createScalarSpan(
               row.values[0][field] / samplingDataTotal, {
-                customContextRange: tr.b.Range.PERCENT_RANGE,
+                customContextRange: tr.b.math.Range.PERCENT_RANGE,
                 unit: tr.b.Unit.byName.normalizedPercentage,
                 context: { minimumFractionDigits: 2, maximumFractionDigits: 2 },
               });
diff --git a/tracing/tracing/ui/analysis/related_events.html b/tracing/tracing/ui/analysis/related_events.html
index cd043b5..b25fdc8 100644
--- a/tracing/tracing/ui/analysis/related_events.html
+++ b/tracing/tracing/ui/analysis/related_events.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/base/task.html">
 <link rel="import" href="/tracing/model/event_set.html">
 <link rel="import" href="/tracing/ui/analysis/analysis_link.html">
@@ -251,7 +251,7 @@
       if (!slice.parentContainer || !slice.parentContainer.samples)
         continue;
       let candidates = slice.parentContainer.samples;
-      let range = tr.b.Range.fromExplicitRange(
+      let range = tr.b.math.Range.fromExplicitRange(
           slice.start, slice.start + slice.duration);
       let filteredSamples = range.filterArray(
           candidates, function(value) {return value.start;});
@@ -320,7 +320,7 @@
         continue;
       }
       let sliceGroup = slice.parentContainer.sliceGroup.slices;
-      let range = tr.b.Range.fromExplicitRange(
+      let range = tr.b.math.Range.fromExplicitRange(
           slice.start, slice.start + slice.duration);
       let filteredSlices = range.filterArray(
           sliceGroup, value => value.start);
diff --git a/tracing/tracing/ui/analysis/selection_summary_table.html b/tracing/tracing/ui/analysis/selection_summary_table.html
index f4f2b62..746837f 100644
--- a/tracing/tracing/ui/analysis/selection_summary_table.html
+++ b/tracing/tracing/ui/analysis/selection_summary_table.html
@@ -33,7 +33,7 @@
 Polymer({
   is: 'tr-ui-a-selection-summary-table',
   created: function() {
-    this.selection_ = new tr.b.Range();
+    this.selection_ = new tr.b.math.Range();
   },
 
   ready: function() {
diff --git a/tracing/tracing/ui/analysis/single_thread_time_slice_sub_view.html b/tracing/tracing/ui/analysis/single_thread_time_slice_sub_view.html
index 032dbbe..8839a13 100644
--- a/tracing/tracing/ui/analysis/single_thread_time_slice_sub_view.html
+++ b/tracing/tracing/ui/analysis/single_thread_time_slice_sub_view.html
@@ -7,7 +7,7 @@
 
 <link rel="import" href="/tracing/base/color_scheme.html">
 <link rel="import" href="/tracing/base/iteration_helpers.html">
-<link rel="import" href="/tracing/base/sorted_array_utils.html">
+<link rel="import" href="/tracing/base/math/sorted_array_utils.html">
 <link rel="import" href="/tracing/base/unit.html">
 <link rel="import" href="/tracing/base/utils.html">
 <link rel="import" href="/tracing/model/event_set.html">
diff --git a/tracing/tracing/ui/base/bar_chart_test.html b/tracing/tracing/ui/base/bar_chart_test.html
index d628a01..559530d 100644
--- a/tracing/tracing/ui/base/bar_chart_test.html
+++ b/tracing/tracing/ui/base/bar_chart_test.html
@@ -60,7 +60,7 @@
       {x: 30, alpha: 100, beta: 125},
       {x: 40, alpha: 50, beta: 125}
     ];
-    chart.brushedRange = tr.b.Range.fromExplicitRange(20, 40);
+    chart.brushedRange = tr.b.math.Range.fromExplicitRange(20, 40);
   });
 
   test('instantiation_twoSparseSeriesWithFirstValueSparse', function() {
@@ -106,10 +106,10 @@
 
     function updateBrushedRange() {
       if (mouseDownX === undefined || (mouseDownX === curMouseX)) {
-        chart.brushedRange = new tr.b.Range();
+        chart.brushedRange = new tr.b.math.Range();
         return;
       }
-      var r = new tr.b.Range();
+      var r = new tr.b.math.Range();
       r.min = Math.min(mouseDownX, curMouseX);
       r.max = Math.max(mouseDownX, curMouseX);
       chart.brushedRange = r;
@@ -134,7 +134,7 @@
 
   test('instantiation_overrideDataRange', function() {
     var chart = new tr.ui.b.BarChart();
-    chart.overrideDataRange = tr.b.Range.fromExplicitRange(10, 90);
+    chart.overrideDataRange = tr.b.math.Range.fromExplicitRange(10, 90);
     this.addHTMLOutput(chart);
     chart.data = [
       {x: 0, value: -20},
@@ -144,7 +144,7 @@
     ];
 
     chart = new tr.ui.b.BarChart();
-    chart.overrideDataRange = tr.b.Range.fromExplicitRange(-10, 100);
+    chart.overrideDataRange = tr.b.math.Range.fromExplicitRange(-10, 100);
     this.addHTMLOutput(chart);
     chart.data = [
       {x: 0, value: 0},
diff --git a/tracing/tracing/ui/base/camera.html b/tracing/tracing/ui/base/camera.html
index 70ed50d..b8cd350 100644
--- a/tracing/tracing/ui/base/camera.html
+++ b/tracing/tracing/ui/base/camera.html
@@ -13,6 +13,8 @@
 'use strict';
 
 tr.exportTo('tr.ui.b', function() {
+  let deg2rad = tr.b.math.deg2rad;
+
   var constants = {
     DEFAULT_SCALE: 0.5,
     DEFAULT_EYE_DISTANCE: 10000,
@@ -24,7 +26,6 @@
     SETTINGS_NAMESPACE: 'tr.ui_camera'
   };
 
-
   var Camera = tr.ui.b.define('camera');
 
   Camera.prototype = {
@@ -77,7 +78,7 @@
       var aspectRatio = rect.width / rect.height;
       var matrix = mat4.create();
       mat4.perspective(
-          matrix, tr.b.deg2rad(constants.FOV), aspectRatio, 1, 100000);
+          matrix, deg2rad(constants.FOV), aspectRatio, 1, 100000);
 
       return matrix;
     },
@@ -161,15 +162,15 @@
 
       var halfFov = constants.FOV / 2;
       var multiplier =
-          2.0 * length * Math.tan(tr.b.deg2rad(halfFov)) / rect.height;
+          2.0 * length * Math.tan(deg2rad(halfFov)) / rect.height;
 
       // Get the up and right vectors.
       var up = [0, 1, 0];
       var rotMatrix = mat4.create();
       mat4.rotate(
-          rotMatrix, rotMatrix, tr.b.deg2rad(this.rotation_[1]), [0, 1, 0]);
+          rotMatrix, rotMatrix, deg2rad(this.rotation_[1]), [0, 1, 0]);
       mat4.rotate(
-          rotMatrix, rotMatrix, tr.b.deg2rad(this.rotation_[0]), [1, 0, 0]);
+          rotMatrix, rotMatrix, deg2rad(this.rotation_[0]), [1, 0, 0]);
       vec3.transformMat4(up, up, rotMatrix);
 
       var right = [0, 0, 0];
@@ -188,7 +189,7 @@
       // to be on the plane z = 0 with normal [0, 0, 1].
       if (Math.abs(this.gazeTarget_[2]) > 1e-6) {
         var gazeVector = [-eyeVector[0], -eyeVector[1], -eyeVector[2]];
-        var newLength = tr.b.clamp(
+        var newLength = tr.b.math.clamp(
             -this.eye_[2] / gazeVector[2],
             constants.MINIMUM_DISTANCE,
             constants.MAXIMUM_DISTANCE);
@@ -203,7 +204,7 @@
 
     updateZoomByDelta: function(delta) {
       var deltaY = delta[1];
-      deltaY = tr.b.clamp(deltaY, -50, 50);
+      deltaY = tr.b.math.clamp(deltaY, -50, 50);
       var scale = 1.0 - deltaY / 100.0;
 
       var eyeVector = [0, 0, 0];
@@ -239,9 +240,9 @@
       // Undo the current rotation.
       var rotMatrix = mat4.create();
       mat4.rotate(
-          rotMatrix, rotMatrix, -tr.b.deg2rad(this.rotation_[0]), [1, 0, 0]);
+          rotMatrix, rotMatrix, -deg2rad(this.rotation_[0]), [1, 0, 0]);
       mat4.rotate(
-          rotMatrix, rotMatrix, -tr.b.deg2rad(this.rotation_[1]), [0, 1, 0]);
+          rotMatrix, rotMatrix, -deg2rad(this.rotation_[1]), [0, 1, 0]);
       vec4.transformMat4(eyeVector, eyeVector, rotMatrix);
 
       // Update rotation values.
@@ -251,9 +252,9 @@
       // Redo the new rotation.
       mat4.identity(rotMatrix);
       mat4.rotate(
-          rotMatrix, rotMatrix, tr.b.deg2rad(this.rotation_[1]), [0, 1, 0]);
+          rotMatrix, rotMatrix, deg2rad(this.rotation_[1]), [0, 1, 0]);
       mat4.rotate(
-          rotMatrix, rotMatrix, tr.b.deg2rad(this.rotation_[0]), [1, 0, 0]);
+          rotMatrix, rotMatrix, deg2rad(this.rotation_[0]), [1, 0, 0]);
       vec4.transformMat4(eyeVector, eyeVector, rotMatrix);
 
       vec3.add(this.eye_, this.gazeTarget_, eyeVector);
diff --git a/tracing/tracing/ui/base/camera_test.html b/tracing/tracing/ui/base/camera_test.html
index 1908781..b7c6d63 100644
--- a/tracing/tracing/ui/base/camera_test.html
+++ b/tracing/tracing/ui/base/camera_test.html
@@ -4,9 +4,9 @@
 Use of this source code is governed by a BSD-style license that can be
 found in the LICENSE file.
 -->
-<link rel="import" href="/tracing/base/bbox2.html">
-<link rel="import" href="/tracing/base/quad.html">
-<link rel="import" href="/tracing/base/rect.html">
+<link rel="import" href="/tracing/base/math/bbox2.html">
+<link rel="import" href="/tracing/base/math/quad.html">
+<link rel="import" href="/tracing/base/math/rect.html">
 <link rel="import" href="/tracing/ui/base/quad_stack_view.html">
 <script>
 'use strict';
@@ -14,14 +14,14 @@
 tr.b.unittest.testSuite(function() {
   function createQuads() {
     var quads = [
-      tr.b.Quad.fromXYWH(-500, -500, 30, 30), // 4 corners
-      tr.b.Quad.fromXYWH(-500, 470, 30, 30),
-      tr.b.Quad.fromXYWH(470, -500, 30, 30),
-      tr.b.Quad.fromXYWH(470, 470, 30, 30),
-      tr.b.Quad.fromXYWH(-250, -250, 250, 250), // crosshairs
-      tr.b.Quad.fromXYWH(0, -250, 250, 250), // crosshairs
-      tr.b.Quad.fromXYWH(-250, 0, 250, 250), // crosshairs
-      tr.b.Quad.fromXYWH(0, 0, 250, 250) // crosshairs
+      tr.b.math.Quad.fromXYWH(-500, -500, 30, 30), // 4 corners
+      tr.b.math.Quad.fromXYWH(-500, 470, 30, 30),
+      tr.b.math.Quad.fromXYWH(470, -500, 30, 30),
+      tr.b.math.Quad.fromXYWH(470, 470, 30, 30),
+      tr.b.math.Quad.fromXYWH(-250, -250, 250, 250), // crosshairs
+      tr.b.math.Quad.fromXYWH(0, -250, 250, 250), // crosshairs
+      tr.b.math.Quad.fromXYWH(-250, 0, 250, 250), // crosshairs
+      tr.b.math.Quad.fromXYWH(0, 0, 250, 250) // crosshairs
     ];
     quads[0].stackingGroupId = 0;
     quads[1].stackingGroupId = 0;
@@ -40,7 +40,7 @@
     // simulate the constraints of the layer-tree-view
     view.style.height = '400px';
     view.style.width = '800px';
-    view.deviceRect = tr.b.Rect.fromXYWH(-250, -250, 500, 500);
+    view.deviceRect = tr.b.math.Rect.fromXYWH(-250, -250, 500, 500);
     view.quads = quads;
 
     testFramework.addHTMLOutput(view);
diff --git a/tracing/tracing/ui/base/chart_base_2d.html b/tracing/tracing/ui/base/chart_base_2d.html
index ffab853..9996dc2 100644
--- a/tracing/tracing/ui/base/chart_base_2d.html
+++ b/tracing/tracing/ui/base/chart_base_2d.html
@@ -6,10 +6,10 @@
 -->
 
 <link rel="import" href="/tracing/base/iteration_helpers.html">
-<link rel="import" href="/tracing/base/math.html">
+<link rel="import" href="/tracing/base/math/math.html">
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/math/statistics.html">
 <link rel="import" href="/tracing/base/raf.html">
-<link rel="import" href="/tracing/base/range.html">
-<link rel="import" href="/tracing/base/statistics.html">
 <link rel="import" href="/tracing/ui/base/chart_base.html">
 <link rel="import" href="/tracing/ui/base/mouse_tracker.html">
 
@@ -53,7 +53,7 @@
       this.yScale_ = d3.scale.linear();
       this.isYLogScale_ = false;
       this.yLogScaleMin_ = undefined;
-      this.autoDataRange_ = new tr.b.Range();
+      this.autoDataRange_ = new tr.b.math.Range();
       this.overrideDataRange_ = undefined;
       this.hideXAxis_ = false;
       this.hideYAxis_ = false;
@@ -166,7 +166,7 @@
         this.getXForDatum_(data[leftIndex], leftIndex);
       var rightWidth = this.getXForDatum_(data[rightIndex], rightIndex) -
         this.getXForDatum_(data[index], index);
-      return tr.b.Statistics.mean([leftWidth, rightWidth]);
+      return tr.b.math.Statistics.mean([leftWidth, rightWidth]);
     },
 
     updateSeriesKeys_() {
@@ -325,7 +325,7 @@
         if (minValue === 0)
           minValue = 1;
 
-        var onePowerLess = tr.b.lesserPower(minValue / 10);
+        var onePowerLess = tr.b.math.lesserPower(minValue / 10);
         this.yLogScaleMin_ = onePowerLess;
       }
     },
@@ -469,9 +469,9 @@
 
     getDataPointAtChartPoint_(chartPoint) {
       return {
-        x: tr.b.clamp(this.xScale_.invert(chartPoint.x),
+        x: tr.b.math.clamp(this.xScale_.invert(chartPoint.x),
             this.xScale_.domain()[0], this.xScale_.domain()[1]),
-        y: tr.b.clamp(this.yScale_.invert(chartPoint.y),
+        y: tr.b.math.clamp(this.yScale_.invert(chartPoint.y),
             this.yScale_.domain()[0], this.yScale_.domain()[1])
       };
     },
diff --git a/tracing/tracing/ui/base/chart_base_2d_brushable_x.html b/tracing/tracing/ui/base/chart_base_2d_brushable_x.html
index 2e96b32..7db4a8a 100644
--- a/tracing/tracing/ui/base/chart_base_2d_brushable_x.html
+++ b/tracing/tracing/ui/base/chart_base_2d_brushable_x.html
@@ -19,7 +19,7 @@
 
     decorate() {
       super.decorate();
-      this.brushedRange_ = new tr.b.Range();
+      this.brushedRange_ = new tr.b.math.Range();
     },
 
     set brushedRange(range) {
@@ -29,16 +29,16 @@
     },
 
     get brushedRange() {
-      return tr.b.Range.fromDict(this.brushedRange_.toJSON());
+      return tr.b.math.Range.fromDict(this.brushedRange_.toJSON());
     },
 
     computeBrushRangeFromIndices(indexA, indexB) {
-      indexA = tr.b.clamp(indexA, 0, this.data_.length - 1);
-      indexB = tr.b.clamp(indexB, 0, this.data_.length - 1);
+      indexA = tr.b.math.clamp(indexA, 0, this.data_.length - 1);
+      indexB = tr.b.math.clamp(indexB, 0, this.data_.length - 1);
       var leftIndex = Math.min(indexA, indexB);
       var rightIndex = Math.max(indexA, indexB);
 
-      var brushRange = new tr.b.Range();
+      var brushRange = new tr.b.math.Range();
       brushRange.addValue(
           this.getXForDatum_(this.data_[leftIndex], leftIndex) -
           this.getSampleWidth_(this.data_, leftIndex, true));
diff --git a/tracing/tracing/ui/base/column_chart_test.html b/tracing/tracing/ui/base/column_chart_test.html
index 75c74ea..fdecc38 100644
--- a/tracing/tracing/ui/base/column_chart_test.html
+++ b/tracing/tracing/ui/base/column_chart_test.html
@@ -115,7 +115,7 @@
       {x: 40, alpha: 50, beta: 125}
     ];
 
-    var r = new tr.b.Range();
+    var r = new tr.b.math.Range();
     r.addValue(20);
     r.addValue(40);
     chart.brushedRange = r;
@@ -132,7 +132,7 @@
       {x: 40, alpha: 50, beta: 125}
     ];
 
-    var r = new tr.b.Range();
+    var r = new tr.b.math.Range();
     r.addValue(20);
     r.addValue(40);
     chart.brushedRange = r;
@@ -172,7 +172,7 @@
       {x: 120, value: 90}
     ];
     chart.data = data;
-    var r = new tr.b.Range();
+    var r = new tr.b.math.Range();
 
     // Range min should be 10.
     r = chart.computeBrushRangeFromIndices(-2, 1);
@@ -212,10 +212,10 @@
 
     function updateBrushedRange() {
       if (mouseDownX === undefined || (mouseDownX === curMouseX)) {
-        chart.brushedRange = new tr.b.Range();
+        chart.brushedRange = new tr.b.math.Range();
         return;
       }
-      var r = new tr.b.Range();
+      var r = new tr.b.math.Range();
       r.min = Math.min(mouseDownX, curMouseX);
       r.max = Math.max(mouseDownX, curMouseX);
       chart.brushedRange = r;
@@ -240,7 +240,7 @@
 
   test('overrideDataRange', function() {
     var chart = new tr.ui.b.ColumnChart();
-    chart.overrideDataRange = tr.b.Range.fromExplicitRange(10, 90);
+    chart.overrideDataRange = tr.b.math.Range.fromExplicitRange(10, 90);
     this.addHTMLOutput(chart);
     chart.data = [
       {x: 0, value: 0},
@@ -248,7 +248,7 @@
     ];
 
     chart = new tr.ui.b.ColumnChart();
-    chart.overrideDataRange = tr.b.Range.fromExplicitRange(-10, 100);
+    chart.overrideDataRange = tr.b.math.Range.fromExplicitRange(-10, 100);
     this.addHTMLOutput(chart);
     chart.data = [
       {x: 0, value: 0},
diff --git a/tracing/tracing/ui/base/draw_helpers.html b/tracing/tracing/ui/base/draw_helpers.html
index 9843db0..4b24bf6 100644
--- a/tracing/tracing/ui/base/draw_helpers.html
+++ b/tracing/tracing/ui/base/draw_helpers.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/sorted_array_utils.html">
+<link rel="import" href="/tracing/base/math/sorted_array_utils.html">
 <link rel="import" href="/tracing/ui/base/elided_cache.html">
 <link rel="import" href="/tracing/ui/base/event_presenter.html">
 
@@ -163,7 +163,7 @@
         ctx, 2 * pixWidth, 2 * pixWidth, colorsAsStrings);
     rect.setYandH(0, height);
 
-    var lowSlice = tr.b.findLowIndexInSortedArray(
+    var lowSlice = tr.b.math.findLowIndexInSortedArray(
         slices,
         function(slice) { return slice.start + slice.duration; },
         viewLWorld);
@@ -307,7 +307,7 @@
     dt.applyTransformToCanvas(ctx);
     ctx.beginPath();
 
-    var lowSlice = tr.b.findLowIndexInSortedArray(
+    var lowSlice = tr.b.math.findLowIndexInSortedArray(
         slices,
         function(slice) { return slice.start; },
         viewLWorld);
@@ -362,7 +362,7 @@
 
     var cY = yOffset * pixelRatio;
 
-    var lowSlice = tr.b.findLowIndexInSortedArray(
+    var lowSlice = tr.b.math.findLowIndexInSortedArray(
         slices,
         function(slice) { return slice.start + slice.duration; },
         viewLWorld);
diff --git a/tracing/tracing/ui/base/line_chart_test.html b/tracing/tracing/ui/base/line_chart_test.html
index adacdf7..447c649 100644
--- a/tracing/tracing/ui/base/line_chart_test.html
+++ b/tracing/tracing/ui/base/line_chart_test.html
@@ -30,7 +30,7 @@
       {x: 40, alpha: 50, beta: 125}
     ];
 
-    var r = new tr.b.Range();
+    var r = new tr.b.math.Range();
     r.addValue(20);
     r.addValue(40);
     chart.brushedRange = r;
@@ -70,7 +70,7 @@
       {x: 80, value: 80},
       {x: 120, value: 90}
     ];
-    var r = new tr.b.Range();
+    var r = new tr.b.math.Range();
 
     // Range min should be 10.
     r = chart.computeBrushRangeFromIndices(-2, 1);
@@ -110,7 +110,7 @@
 
     function updateBrushedRange() {
       if (mouseDownIndex === undefined) {
-        chart.brushedRange = new tr.b.Range();
+        chart.brushedRange = new tr.b.math.Range();
         return;
       }
       chart.brushedRange = chart.computeBrushRangeFromIndices(
@@ -137,7 +137,7 @@
   test('overrideDataRange', function() {
     var chart = new tr.ui.b.LineChart();
     this.addHTMLOutput(chart);
-    chart.overrideDataRange = tr.b.Range.fromExplicitRange(10, 90);
+    chart.overrideDataRange = tr.b.math.Range.fromExplicitRange(10, 90);
     chart.data = [
       {x: 0, value: 0},
       {x: 1, value: 100},
@@ -145,7 +145,7 @@
 
     chart = new tr.ui.b.LineChart();
     this.addHTMLOutput(chart);
-    chart.overrideDataRange = tr.b.Range.fromExplicitRange(-10, 100);
+    chart.overrideDataRange = tr.b.math.Range.fromExplicitRange(-10, 100);
     chart.data = [
       {x: 0, value: 0},
       {x: 1, value: 50},
diff --git a/tracing/tracing/ui/base/name_bar_chart.html b/tracing/tracing/ui/base/name_bar_chart.html
index 6ed295b..3f93b07 100644
--- a/tracing/tracing/ui/base/name_bar_chart.html
+++ b/tracing/tracing/ui/base/name_bar_chart.html
@@ -35,7 +35,7 @@
 
     get yAxisWidth() {
       if (this.data.length === 0) return 0;
-      return Y_AXIS_PADDING + tr.b.Statistics.max(
+      return Y_AXIS_PADDING + tr.b.math.Statistics.max(
           this.data_, d => tr.ui.b.getSVGTextSize(this, d.x).width);
     },
 
diff --git a/tracing/tracing/ui/base/name_bar_chart_test.html b/tracing/tracing/ui/base/name_bar_chart_test.html
index c7efae7..8cecbb1 100644
--- a/tracing/tracing/ui/base/name_bar_chart_test.html
+++ b/tracing/tracing/ui/base/name_bar_chart_test.html
@@ -39,7 +39,7 @@
       {x: 'dog', alpha: 50, beta: 125}
     ];
 
-    var r = new tr.b.Range();
+    var r = new tr.b.math.Range();
     r.addValue(20);
     r.addValue(40);
     chart.brushedRange = r;
@@ -87,7 +87,7 @@
     var currentMouseIndex = undefined;
 
     function updateBrushedRange() {
-      var r = new tr.b.Range();
+      var r = new tr.b.math.Range();
       r.min = Math.max(0, Math.min(mouseDownIndex, currentMouseIndex));
       r.max = Math.min(chart.data.length, Math.max(mouseDownIndex,
           currentMouseIndex) + 1);
diff --git a/tracing/tracing/ui/base/name_column_chart_test.html b/tracing/tracing/ui/base/name_column_chart_test.html
index 4cdfde9..1278786 100644
--- a/tracing/tracing/ui/base/name_column_chart_test.html
+++ b/tracing/tracing/ui/base/name_column_chart_test.html
@@ -44,7 +44,7 @@
       {x: 'dog', alpha: 50, beta: 125}
     ];
 
-    var r = new tr.b.Range();
+    var r = new tr.b.math.Range();
     r.addValue(20);
     r.addValue(40);
     chart.brushedRange = r;
@@ -92,7 +92,7 @@
     var currentMouseIndex = undefined;
 
     function updateBrushedRange() {
-      var r = new tr.b.Range();
+      var r = new tr.b.math.Range();
       r.min = Math.max(0, Math.min(mouseDownIndex, currentMouseIndex));
       r.max = Math.min(chart.data.length,
           Math.max(mouseDownIndex, currentMouseIndex) + 1);
diff --git a/tracing/tracing/ui/base/name_line_chart_test.html b/tracing/tracing/ui/base/name_line_chart_test.html
index e893642..61603b7 100644
--- a/tracing/tracing/ui/base/name_line_chart_test.html
+++ b/tracing/tracing/ui/base/name_line_chart_test.html
@@ -39,7 +39,7 @@
       {x: 'dog', alpha: 50, beta: 125}
     ];
 
-    var r = new tr.b.Range();
+    var r = new tr.b.math.Range();
     r.addValue(20);
     r.addValue(40);
     chart.brushedRange = r;
@@ -87,7 +87,7 @@
     var currentMouseIndex = undefined;
 
     function updateBrushedRange() {
-      var r = new tr.b.Range();
+      var r = new tr.b.math.Range();
       r.min = Math.max(0, Math.min(mouseDownIndex, currentMouseIndex));
       r.max = Math.min(chart.data.length, Math.max(mouseDownIndex,
           currentMouseIndex) + 1);
diff --git a/tracing/tracing/ui/base/quad_stack_view.html b/tracing/tracing/ui/base/quad_stack_view.html
index a373091..c114102 100644
--- a/tracing/tracing/ui/base/quad_stack_view.html
+++ b/tracing/tracing/ui/base/quad_stack_view.html
@@ -4,11 +4,11 @@
 Use of this source code is governed by a BSD-style license that can be
 found in the LICENSE file.
 -->
-<link rel="import" href="/tracing/base/bbox2.html">
-<link rel="import" href="/tracing/base/math.html">
-<link rel="import" href="/tracing/base/quad.html">
+<link rel="import" href="/tracing/base/math/bbox2.html">
+<link rel="import" href="/tracing/base/math/math.html">
+<link rel="import" href="/tracing/base/math/quad.html">
+<link rel="import" href="/tracing/base/math/rect.html">
 <link rel="import" href="/tracing/base/raf.html">
-<link rel="import" href="/tracing/base/rect.html">
 <link rel="import" href="/tracing/base/settings.html">
 <link rel="import" href="/tracing/ui/base/camera.html">
 <link rel="import" href="/tracing/ui/base/mouse_mode_selector.html">
@@ -251,7 +251,7 @@
       quadCanvas.width = quad.imageData.width;
       quadCanvas.height = quad.imageData.height;
       quadCanvas.getContext('2d').putImageData(quad.imageData, 0, 0);
-      var quadBBox = new tr.b.BBox2();
+      var quadBBox = new tr.b.math.BBox2();
       quadBBox.addQuad(quad);
       var iw = quadCanvas.width;
       var ih = quadCanvas.height;
@@ -400,7 +400,7 @@
       this.cameraWasReset_ = false;
       this.camera_.canvas = this.canvas_;
 
-      this.viewportRect_ = tr.b.Rect.fromXYWH(0, 0, 0, 0);
+      this.viewportRect_ = tr.b.math.Rect.fromXYWH(0, 0, 0, 0);
 
       this.pixelRatio_ = window.devicePixelRatio || 1;
     },
@@ -460,7 +460,7 @@
 
       var width = parseInt(window.getComputedStyle(this.offsetParent).width);
       var height = parseInt(window.getComputedStyle(this.offsetParent).height);
-      var rect = tr.b.Rect.fromXYWH(0, 0, width, height);
+      var rect = tr.b.math.Rect.fromXYWH(0, 0, width, height);
 
       if (rect.equalTo(this.viewportRect_))
         return false;
@@ -539,12 +539,12 @@
           this.chromeImages_.right, leftWidth + s * midWidth, 0);
 
       // Construct the quad.
-      var chromeRect = tr.b.Rect.fromXYWH(
+      var chromeRect = tr.b.math.Rect.fromXYWH(
           this.deviceRect_.x,
           this.deviceRect_.y - offsetY,
           this.deviceRect_.width,
           this.deviceRect_.height + offsetY);
-      var chromeQuad = tr.b.Quad.fromRect(chromeRect);
+      var chromeQuad = tr.b.math.Quad.fromRect(chromeRect);
       chromeQuad.stackingGroupId = this.maxStackingGroupId_ + 1;
       chromeQuad.imageData = chromeCtx.getImageData(
           0, 0, chromeCanvas.width, chromeCanvas.height);
@@ -571,7 +571,7 @@
       var mv = this.camera_.modelViewMatrix;
       var p = this.camera_.projectionMatrix;
 
-      var viewport = tr.b.Rect.fromXYWH(
+      var viewport = tr.b.math.Rect.fromXYWH(
           0, 0, this.canvas_.width, this.canvas_.height);
 
       // Calculate the quad stacks.
@@ -671,7 +671,7 @@
       var mousePos = this.extractRelativeMousePosition_(e);
       var res = [];
       function handleQuad(passNumber, quad, p1, p2, p3, p4) {
-        if (tr.b.pointInImplicitQuad(mousePos, p1, p2, p3, p4))
+        if (tr.b.math.pointInImplicitQuad(mousePos, p1, p2, p3, p4))
           res.push(quad);
       }
       this.stackTransformAndProcessQuads_(1, handleQuad, false);
diff --git a/tracing/tracing/ui/base/scatter_chart.html b/tracing/tracing/ui/base/scatter_chart.html
index ee94887..784d2a6 100644
--- a/tracing/tracing/ui/base/scatter_chart.html
+++ b/tracing/tracing/ui/base/scatter_chart.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/ui/base/chart_base_2d.html">
 
 <script>
@@ -28,8 +28,8 @@
 
     decorate() {
       super.decorate();
-      this.brushedXRange_ = new tr.b.Range();
-      this.brushedYRange_ = new tr.b.Range();
+      this.brushedXRange_ = new tr.b.math.Range();
+      this.brushedYRange_ = new tr.b.math.Range();
     },
 
     get hideLegend() {
@@ -48,11 +48,11 @@
       super.updateMargins_();
       if (this.data.length === 0) return;
 
-      var rightOverhangPx = tr.b.Statistics.max(
+      var rightOverhangPx = tr.b.math.Statistics.max(
           this.data, d => this.xScale_(d.x) + d.radius - this.graphWidth);
       this.margin.right = Math.max(this.margin.right, rightOverhangPx);
 
-      var topOverhangPx = tr.b.Statistics.max(
+      var topOverhangPx = tr.b.math.Statistics.max(
           this.data, d => (this.graphHeight - this.yScale_(d.y)) + d.radius) -
         this.graphHeight;
       this.margin.top = Math.max(this.margin.top, topOverhangPx);
diff --git a/tracing/tracing/ui/base/scatter_chart_test.html b/tracing/tracing/ui/base/scatter_chart_test.html
index a2072f8..b79fb53 100644
--- a/tracing/tracing/ui/base/scatter_chart_test.html
+++ b/tracing/tracing/ui/base/scatter_chart_test.html
@@ -39,12 +39,12 @@
     var mouseDown = undefined;
 
     function updateBrushedRange(e) {
-      var xRange = new tr.b.Range();
+      var xRange = new tr.b.math.Range();
       if (e.x !== mouseDown.x) {
         xRange.addValue(mouseDown.x);
         xRange.addValue(e.x);
       }
-      var yRange = new tr.b.Range();
+      var yRange = new tr.b.math.Range();
       if (e.y !== mouseDown.y) {
         yRange.addValue(mouseDown.y);
         yRange.addValue(e.y);
diff --git a/tracing/tracing/ui/base/timing_tool.html b/tracing/tracing/ui/base/timing_tool.html
index aea9e33..66652a8 100644
--- a/tracing/tracing/ui/base/timing_tool.html
+++ b/tracing/tracing/ui/base/timing_tool.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/model/event_set.html">
 <link rel="import" href="/tracing/model/slice.html">
 <link rel="import" href="/tracing/ui/base/ui.html">
@@ -272,7 +272,7 @@
         snapped: false
       };
 
-      var eventBounds = new tr.b.Range();
+      var eventBounds = new tr.b.math.Range();
       for (var event of selection) {
         var track = viewport.trackForEvent(event);
         var trackRect = track.getBoundingClientRect();
diff --git a/tracing/tracing/ui/base/utils.html b/tracing/tracing/ui/base/utils.html
index 3ebe825..13133c9 100644
--- a/tracing/tracing/ui/base/utils.html
+++ b/tracing/tracing/ui/base/utils.html
@@ -6,7 +6,7 @@
 -->
 
 <link rel="import" href="/tracing/base/base.html">
-<link rel="import" href="/tracing/base/rect.html">
+<link rel="import" href="/tracing/base/math/rect.html">
 
 <script>
 'use strict';
@@ -30,7 +30,7 @@
       position[1] += node.offsetTop;
       node = node.offsetParent;
     }
-    return tr.b.Rect.fromXYWH(position[0], position[1], size[0], size[1]);
+    return tr.b.math.Rect.fromXYWH(position[0], position[1], size[0], size[1]);
   }
 
   function scrollIntoViewIfNeeded(el) {
diff --git a/tracing/tracing/ui/extras/chrome/cc/layer_tree_quad_stack_view.html b/tracing/tracing/ui/extras/chrome/cc/layer_tree_quad_stack_view.html
index a01dd11..c6d8fb8 100644
--- a/tracing/tracing/ui/extras/chrome/cc/layer_tree_quad_stack_view.html
+++ b/tracing/tracing/ui/extras/chrome/cc/layer_tree_quad_stack_view.html
@@ -6,9 +6,9 @@
 -->
 
 <link rel="import" href="/tracing/base/color.html">
-<link rel="import" href="/tracing/base/quad.html">
+<link rel="import" href="/tracing/base/math/quad.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/base/raf.html">
-<link rel="import" href="/tracing/base/range.html">
 <link rel="import" href="/tracing/base/unit_scale.html">
 <link rel="import" href="/tracing/extras/chrome/cc/debug_colors.html">
 <link rel="import" href="/tracing/extras/chrome/cc/picture.html">
@@ -423,7 +423,7 @@
 
       var lthi = this.layerTreeImpl_.layerTreeHostImpl;
       var lthiInstance = lthi.objectInstance;
-      var worldViewportRect = tr.b.Rect.fromXYWH(
+      var worldViewportRect = tr.b.math.Rect.fromXYWH(
           0, 0,
           lthi.deviceViewportSize.width, lthi.deviceViewportSize.height);
       this.quadStackView_.deviceRect = worldViewportRect;
@@ -702,7 +702,7 @@
         return;
 
       var rect = layer.animationBoundsRect;
-      var abq = tr.b.Quad.fromRect(rect);
+      var abq = tr.b.math.Quad.fromRect(rect);
 
       abq.backgroundColor = 'rgba(164,191,48,0.5)';
       abq.borderColor = 'rgba(205,255,0,0.75)';
@@ -884,7 +884,7 @@
     },
 
     getMinMaxForHeatmap_: function(tiles, heatmapType) {
-      var range = new tr.b.Range();
+      var range = new tr.b.math.Range();
       if (heatmapType === TILE_HEATMAP_TYPE.USING_GPU_MEMORY) {
         range.addValue(0);
         range.addValue(1);
@@ -1116,7 +1116,7 @@
         for (var i = 0; i < tracedInputLatencies.length; i++) {
           var coordinatesArray = tracedInputLatencies[i].args.data.coordinates;
           for (var j = 0; j < coordinatesArray.length; j++) {
-            var inputQuad = tr.b.Quad.fromXYWH(
+            var inputQuad = tr.b.math.Quad.fromXYWH(
                 coordinatesArray[j].x - 25,
                 coordinatesArray[j].y - 25,
                 50,
diff --git a/tracing/tracing/ui/extras/chrome/cc/picture_debugger.html b/tracing/tracing/ui/extras/chrome/cc/picture_debugger.html
index 30e1e8f..3adfd37 100644
--- a/tracing/tracing/ui/extras/chrome/cc/picture_debugger.html
+++ b/tracing/tracing/ui/extras/chrome/cc/picture_debugger.html
@@ -385,7 +385,7 @@
         this.selectedOpIndex = 0;
         return;
       }
-      this.selectedOpIndex = tr.b.clamp(
+      this.selectedOpIndex = tr.b.math.clamp(
           this.selectedOpIndex + increment,
           0, this.numOps);
     },
diff --git a/tracing/tracing/ui/extras/chrome/cc/picture_ops_chart_summary_view.html b/tracing/tracing/ui/extras/chrome/cc/picture_ops_chart_summary_view.html
index 3df8ddf..15a2abc 100644
--- a/tracing/tracing/ui/extras/chrome/cc/picture_ops_chart_summary_view.html
+++ b/tracing/tracing/ui/extras/chrome/cc/picture_ops_chart_summary_view.html
@@ -118,7 +118,7 @@
         this.currentBarMouseOverTarget_ = Math.floor(
             (x - chartLeft) / chartInnerWidth * this.opsTimingData_.length);
 
-        this.currentBarMouseOverTarget_ = tr.b.clamp(
+        this.currentBarMouseOverTarget_ = tr.b.math.clamp(
             this.currentBarMouseOverTarget_, 0, this.opsTimingData_.length - 1);
       }
 
diff --git a/tracing/tracing/ui/extras/chrome/cc/picture_ops_chart_view.html b/tracing/tracing/ui/extras/chrome/cc/picture_ops_chart_view.html
index 97f4987..870e8a8 100644
--- a/tracing/tracing/ui/extras/chrome/cc/picture_ops_chart_view.html
+++ b/tracing/tracing/ui/extras/chrome/cc/picture_ops_chart_view.html
@@ -163,7 +163,7 @@
       index = Math.floor((x - chartLeft) / totalBarWidth *
           this.pictureOps_.length);
 
-      index = tr.b.clamp(index, 0, this.pictureOps_.length - 1);
+      index = tr.b.math.clamp(index, 0, this.pictureOps_.length - 1);
 
       return index;
     },
diff --git a/tracing/tracing/ui/extras/drive/comments_side_panel.html b/tracing/tracing/ui/extras/drive/comments_side_panel.html
index a834ab1..4c72fa6 100644
--- a/tracing/tracing/ui/extras/drive/comments_side_panel.html
+++ b/tracing/tracing/ui/extras/drive/comments_side_panel.html
@@ -61,7 +61,7 @@
   behaviors: [tr.ui.behaviors.SidePanel],
 
   ready: function() {
-    this.rangeOfInterest_ = new tr.b.Range();
+    this.rangeOfInterest_ = new tr.b.math.Range();
     this.selection_ = undefined;
     this.comments_ = [];
     this.annotationFromComment_ = undefined;
diff --git a/tracing/tracing/ui/extras/side_panel/alerts_side_panel.html b/tracing/tracing/ui/extras/side_panel/alerts_side_panel.html
index 0988f63..344b558 100644
--- a/tracing/tracing/ui/extras/side_panel/alerts_side_panel.html
+++ b/tracing/tracing/ui/extras/side_panel/alerts_side_panel.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/statistics.html">
+<link rel="import" href="/tracing/base/math/statistics.html">
 <link rel="import" href="/tracing/model/event_set.html">
 <link rel="import" href="/tracing/ui/base/dom_helpers.html">
 <link rel="import" href="/tracing/ui/base/line_chart.html">
@@ -44,7 +44,7 @@
 
 
   ready: function() {
-    this.rangeOfInterest_ = new tr.b.Range();
+    this.rangeOfInterest_ = new tr.b.math.Range();
     this.selection_ = undefined;
   },
 
diff --git a/tracing/tracing/ui/extras/side_panel/frame_data_side_panel.html b/tracing/tracing/ui/extras/side_panel/frame_data_side_panel.html
index da1f0b2..bb0aff5 100644
--- a/tracing/tracing/ui/extras/side_panel/frame_data_side_panel.html
+++ b/tracing/tracing/ui/extras/side_panel/frame_data_side_panel.html
@@ -170,7 +170,7 @@
 
     ready: function() {
       this.model_ = undefined;
-      this.rangeOfInterest_ = new tr.b.Range();
+      this.rangeOfInterest_ = new tr.b.math.Range();
 
       this.$.table.showHeader = true;
       this.$.table.selectionMode = tr.ui.b.TableFormat.SelectionMode.ROW;
diff --git a/tracing/tracing/ui/extras/side_panel/frame_data_side_panel_test.html b/tracing/tracing/ui/extras/side_panel/frame_data_side_panel_test.html
index 5d5301d..7dc3b52 100644
--- a/tracing/tracing/ui/extras/side_panel/frame_data_side_panel_test.html
+++ b/tracing/tracing/ui/extras/side_panel/frame_data_side_panel_test.html
@@ -129,7 +129,7 @@
         new tr.model.EventSet([topLevel, slice1, slice2])));
 
     // The new range of interest contains only slice2.
-    panel.rangeOfInterest = tr.b.Range.fromExplicitRange(slice2.start,
+    panel.rangeOfInterest = tr.b.math.Range.fromExplicitRange(slice2.start,
         slice2.end);
     assert.isTrue(panel.$.table.tableRows[0].eventsOfInterest.equals(
         new tr.model.EventSet([topLevel, slice2])));
diff --git a/tracing/tracing/ui/extras/side_panel/input_latency_side_panel.html b/tracing/tracing/ui/extras/side_panel/input_latency_side_panel.html
index d6ff935..7934274 100644
--- a/tracing/tracing/ui/extras/side_panel/input_latency_side_panel.html
+++ b/tracing/tracing/ui/extras/side_panel/input_latency_side_panel.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/statistics.html">
+<link rel="import" href="/tracing/base/math/statistics.html">
 <link rel="import" href="/tracing/model/event_set.html">
 <link rel="import" href="/tracing/model/helpers/chrome_model_helper.html">
 <link rel="import" href="/tracing/ui/base/dom_helpers.html">
@@ -46,7 +46,7 @@
 
 
   ready: function() {
-    this.rangeOfInterest_ = new tr.b.Range();
+    this.rangeOfInterest_ = new tr.b.math.Range();
     this.frametimeType_ = tr.model.helpers.IMPL_FRAMETIME_TYPE;
     this.latencyChart_ = undefined;
     this.frametimeChart_ = undefined;
@@ -111,7 +111,7 @@
     if (this.latencyChart_ === undefined)
       return;
 
-    var r = new tr.b.Range();
+    var r = new tr.b.math.Range();
     if (this.mouseDownIndex_ === undefined) {
       this.latencyChart_.brushedRange = r;
       return;
@@ -235,9 +235,9 @@
 
     var frametimeData = tr.model.helpers.getFrametimeDataFromEvents(
         frameEvents);
-    var averageFrametime = tr.b.Statistics.mean(frametimeData, function(d) {
-      return d.frametime;
-    });
+    var averageFrametime = tr.b.math.Statistics.mean(frametimeData, d =>
+      d.frametime
+    );
 
     var latencyEvents = this.modelHelper_.browserHelper.
       getLatencyEventsInRange(
@@ -253,7 +253,7 @@
       });
     });
 
-    var averageLatency = tr.b.Statistics.mean(latencyData, function(d) {
+    var averageLatency = tr.b.math.Statistics.mean(latencyData, function(d) {
       return d.latency;
     });
 
diff --git a/tracing/tracing/ui/extras/system_stats/system_stats_instance_track.html b/tracing/tracing/ui/extras/system_stats/system_stats_instance_track.html
index 71f2adf..72dbb2f 100644
--- a/tracing/tracing/ui/extras/system_stats/system_stats_instance_track.html
+++ b/tracing/tracing/ui/extras/system_stats/system_stats_instance_track.html
@@ -8,7 +8,7 @@
 <link rel="stylesheet"
       href="/tracing/ui/extras/system_stats/system_stats_instance_track.css">
 
-<link rel="import" href="/tracing/base/sorted_array_utils.html">
+<link rel="import" href="/tracing/base/math/sorted_array_utils.html">
 <link rel="import" href="/tracing/ui/base/event_presenter.html">
 <link rel="import" href="/tracing/ui/base/ui.html">
 <link rel="import" href="/tracing/ui/tracks/object_instance_track.html">
@@ -212,7 +212,7 @@
       var maxStats = this.maxStats_;
 
       var objectSnapshots = this.objectInstance_.snapshots;
-      var lowIndex = tr.b.findLowIndexInSortedArray(
+      var lowIndex = tr.b.math.findLowIndexInSortedArray(
           objectSnapshots,
           function(snapshot) {
             return snapshot.ts;
diff --git a/tracing/tracing/ui/side_panel/file_size_stats_side_panel.html b/tracing/tracing/ui/side_panel/file_size_stats_side_panel.html
index 6de0354..46e7cad 100644
--- a/tracing/tracing/ui/side_panel/file_size_stats_side_panel.html
+++ b/tracing/tracing/ui/side_panel/file_size_stats_side_panel.html
@@ -5,8 +5,8 @@
 found in the LICENSE file.
 -->
 
+<link rel="import" href="/tracing/base/math/statistics.html">
 <link rel="import" href="/tracing/base/scalar.html">
-<link rel="import" href="/tracing/base/statistics.html">
 <link rel="import" href="/tracing/base/unit.html">
 <link rel="import" href="/tracing/ui/base/grouping_table.html">
 <link rel="import" href="/tracing/ui/base/grouping_table_groupby_picker.html">
@@ -185,12 +185,12 @@
 
       var columns = this.createColumns_(this.model.stats);
       table.rowStatsConstructor = function ModelStatsRowStats(row) {
-        var sum = tr.b.Statistics.sum(row.data, function(x) {
+        var sum = tr.b.math.Statistics.sum(row.data, function(x) {
           return x.numEvents;
         });
-        var totalEventSizeinBytes = tr.b.Statistics.sum(row.data, function(x) {
-          return x.totalEventSizeinBytes;
-        });
+        var totalEventSizeinBytes = tr.b.math.Statistics.sum(row.data, x =>
+          x.totalEventSizeinBytes
+        );
         return {
           numEvents: sum,
           totalEventSizeinBytes: totalEventSizeinBytes
diff --git a/tracing/tracing/ui/side_panel/metrics_side_panel.html b/tracing/tracing/ui/side_panel/metrics_side_panel.html
index 99980ca..b9351e5 100644
--- a/tracing/tracing/ui/side_panel/metrics_side_panel.html
+++ b/tracing/tracing/ui/side_panel/metrics_side_panel.html
@@ -89,7 +89,7 @@
      * @return {undefined|number}
      */
     get metricLatencyMs() {
-      return tr.b.Statistics.mean(this.metricLatenciesMs_);
+      return tr.b.math.Statistics.mean(this.metricLatenciesMs_);
     },
 
     onMetricChange_: function() {
@@ -139,7 +139,7 @@
     },
 
     /**
-     * @return {undefined|!tr.b.Range}
+     * @return {undefined|!tr.b.math.Range}
      */
     get rangeOfInterest() {
       return this.rangeOfInterest_;
@@ -151,7 +151,7 @@
      * will be re-run immediately; otherwise, the Recompute button will be
      * enabled.
      *
-     * @param {!tr.b.Range} range
+     * @param {!tr.b.math.Range} range
      */
     set rangeOfInterest(range) {
       this.rangeOfInterest_ = range;
diff --git a/tracing/tracing/ui/side_panel/side_panel_container.html b/tracing/tracing/ui/side_panel/side_panel_container.html
index 0661918..47b75be 100644
--- a/tracing/tracing/ui/side_panel/side_panel_container.html
+++ b/tracing/tracing/ui/side_panel/side_panel_container.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/ui/side_panel/side_panel.html">
 <link rel="import" href="/tracing/ui/side_panel/side_panel_registry.html">
 
@@ -90,7 +90,7 @@
     this.dragHandle_ = this.$.side_panel_drag_handle;
     this.dragHandle_.horizontal = false;
     this.dragHandle_.target = this.activePanelContainer_;
-    this.rangeOfInterest_ = new tr.b.Range();
+    this.rangeOfInterest_ = new tr.b.math.Range();
     this.brushingStateController_ = undefined;
     this.onSelectionChanged_ = this.onSelectionChanged_.bind(this);
     this.onModelChanged_ = this.onModelChanged_.bind(this);
diff --git a/tracing/tracing/ui/timeline_display_transform_animations.html b/tracing/tracing/ui/timeline_display_transform_animations.html
index a1f5ecf..db95593 100644
--- a/tracing/tracing/ui/timeline_display_transform_animations.html
+++ b/tracing/tracing/ui/timeline_display_transform_animations.html
@@ -12,6 +12,7 @@
 
 tr.exportTo('tr.ui', function() {
   var kDefaultPanAnimationDurationMs = 100.0;
+  const lerp = tr.b.math.lerp;
 
   /**
    * Pans a TimelineDisplayTransform by a given amount.
@@ -67,11 +68,12 @@
 
     tick: function(timestamp, target) {
       var percentDone = (timestamp - this.startTimeMs) / this.durationMs;
-      percentDone = tr.b.clamp(percentDone, 0, 1);
+      percentDone = tr.b.math.clamp(percentDone, 0, 1);
 
-      target.panX = tr.b.lerp(percentDone, this.startPanX, this.goalPanX);
-      if (this.affectsPanY)
-        target.panY = tr.b.lerp(percentDone, this.startPanY, this.goalPanY);
+      target.panX = lerp(percentDone, this.startPanX, this.goalPanX);
+      if (this.affectsPanY) {
+        target.panY = lerp(percentDone, this.startPanY, this.goalPanY);
+      }
       return timestamp >= this.startTimeMs + this.durationMs;
     },
 
@@ -150,12 +152,11 @@
 
     tick: function(timestamp, target) {
       var percentDone = (timestamp - this.startTimeMs) / this.durationMs;
-      percentDone = tr.b.clamp(percentDone, 0, 1);
+      percentDone = tr.b.math.clamp(percentDone, 0, 1);
 
-      target.scaleX = tr.b.lerp(percentDone, this.startScaleX, this.goalScaleX);
+      target.scaleX = lerp(percentDone, this.startScaleX, this.goalScaleX);
       if (this.affectsPanY) {
-        target.panY = tr.b.lerp(
-            percentDone, this.startPanY, this.goalFocalPointY);
+        target.panY = lerp(percentDone, this.startPanY, this.goalFocalPointY);
       }
 
       target.xPanWorldPosToViewPos(
diff --git a/tracing/tracing/ui/timeline_interest_range.html b/tracing/tracing/ui/timeline_interest_range.html
index 33198d9..f7cf97a 100644
--- a/tracing/tracing/ui/timeline_interest_range.html
+++ b/tracing/tracing/ui/timeline_interest_range.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 
 <script>
 'use strict';
@@ -27,7 +27,7 @@
   function TimelineInterestRange(vp) {
     this.viewport_ = vp;
 
-    this.range_ = new tr.b.Range();
+    this.range_ = new tr.b.math.Range();
 
     this.leftSelected_ = false;
     this.rightSelected_ = false;
@@ -85,7 +85,7 @@
     },
 
     asRangeObject: function() {
-      var range = new tr.b.Range();
+      var range = new tr.b.math.Range();
       range.addRange(this.range_);
       return range;
     },
diff --git a/tracing/tracing/ui/timeline_viewport.html b/tracing/tracing/ui/timeline_viewport.html
index 3e69256..d22bc17 100644
--- a/tracing/tracing/ui/timeline_viewport.html
+++ b/tracing/tracing/ui/timeline_viewport.html
@@ -190,7 +190,7 @@
     onCurentDisplayTransformChange_: function(oldDisplayTransform) {
       // Ensure panY stays clamped in the track container's scroll range.
       if (this.modelTrackContainer_) {
-        this.currentDisplayTransform.panY = tr.b.clamp(
+        this.currentDisplayTransform.panY = tr.b.math.clamp(
             this.currentDisplayTransform.panY,
             0,
             this.modelTrackContainer_.scrollHeight -
@@ -320,7 +320,7 @@
       var idealMajorMarkDistanceWorld =
           dt.xViewVectorToWorld(idealMajorMarkDistancePix);
 
-      var majorMarkDistanceWorld = tr.b.preferredNumberLargerThanMin(
+      var majorMarkDistanceWorld = tr.b.math.preferredNumberLargerThanMin(
           idealMajorMarkDistanceWorld);
 
       var firstMajorMark = Math.floor(
diff --git a/tracing/tracing/ui/tracks/chart_series.html b/tracing/tracing/ui/tracks/chart_series.html
index 218af10..df6898a 100644
--- a/tracing/tracing/ui/tracks/chart_series.html
+++ b/tracing/tracing/ui/tracks/chart_series.html
@@ -6,7 +6,7 @@
 -->
 
 <link rel="import" href="/tracing/base/color_scheme.html">
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/model/proxy_selectable_item.html">
 <link rel="import" href="/tracing/model/selection_state.html">
 <link rel="import" href="/tracing/ui/base/event_presenter.html">
@@ -126,7 +126,7 @@
     },
 
     get range() {
-      var range = new tr.b.Range();
+      var range = new tr.b.math.Range();
       this.points.forEach(function(point) {
         range.addValue(point.y);
       }, this);
@@ -169,11 +169,11 @@
       var rightTimestamp = transform.rightTimestamp + extraPixels;
 
       // Find the index of the first and last (partially) visible points.
-      var firstVisibleIndex = tr.b.findLowIndexInSortedArray(
+      var firstVisibleIndex = tr.b.math.findLowIndexInSortedArray(
           this.points,
           function(point) { return point.x; },
           leftTimestamp);
-      var lastVisibleIndex = tr.b.findLowIndexInSortedArray(
+      var lastVisibleIndex = tr.b.math.findLowIndexInSortedArray(
           this.points,
           function(point) { return point.x; },
           rightTimestamp);
@@ -239,7 +239,7 @@
             break;
           }
           var density = visibleIndexRange / visibleViewXRange;
-          var clampedDensity = tr.b.clamp(density,
+          var clampedDensity = tr.b.math.clamp(density,
               this.unselectedPointDensityOpaque_,
               this.unselectedPointDensityTransparent_);
           var densityRange = this.unselectedPointDensityTransparent_ -
@@ -513,7 +513,7 @@
         point.addToSelection(selection);
       }
 
-      tr.b.iterateOverIntersectingIntervals(
+      tr.b.math.iterateOverIntersectingIntervals(
           this.points,
           function(point) { return point.x; },
           getPointWidth,
@@ -545,7 +545,7 @@
       if (this.points === undefined)
         return;
 
-      var item = tr.b.findClosestElementInSortedArray(
+      var item = tr.b.math.findClosestElementInSortedArray(
           this.points,
           function(point) { return point.x; },
           worldX,
diff --git a/tracing/tracing/ui/tracks/chart_series_y_axis.html b/tracing/tracing/ui/tracks/chart_series_y_axis.html
index 2c8d52d..84d3134 100644
--- a/tracing/tracing/ui/tracks/chart_series_y_axis.html
+++ b/tracing/tracing/ui/tracks/chart_series_y_axis.html
@@ -6,7 +6,7 @@
 -->
 
 <link rel="import" href="/tracing/base/color_scheme.html">
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/base/unit.html">
 
 <script>
@@ -27,7 +27,7 @@
    */
   function ChartSeriesYAxis(opt_min, opt_max) {
     this.guid_ = tr.b.GUID.allocateSimple();
-    this.bounds = new tr.b.Range();
+    this.bounds = new tr.b.math.Range();
     if (opt_min !== undefined)
       this.bounds.addValue(opt_min);
     if (opt_max !== undefined)
@@ -63,7 +63,7 @@
      * argument flags.
      */
     autoSetFromSeries: function(series, opt_config) {
-      var range = new tr.b.Range();
+      var range = new tr.b.math.Range();
       series.forEach(function(s) {
         range.addRange(s.range);
       }, this);
@@ -139,7 +139,7 @@
       var idealMajorMarkHeightWorld =
           transform.vectorToWorldDistance(idealMajorMarkHeightPx);
 
-      return tr.b.preferredNumberLargerThanMin(idealMajorMarkHeightWorld);
+      return tr.b.math.preferredNumberLargerThanMin(idealMajorMarkHeightWorld);
     },
 
     draw: function(ctx, transform, showYAxisLabels, showYGridLines) {
diff --git a/tracing/tracing/ui/tracks/chart_series_y_axis_test.html b/tracing/tracing/ui/tracks/chart_series_y_axis_test.html
index 92f2d56..a49b5e0 100644
--- a/tracing/tracing/ui/tracks/chart_series_y_axis_test.html
+++ b/tracing/tracing/ui/tracks/chart_series_y_axis_test.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/core/test_utils.html">
 <link rel="import" href="/tracing/ui/tracks/chart_point.html">
 <link rel="import" href="/tracing/ui/tracks/chart_series.html">
@@ -18,7 +18,7 @@
   var ChartSeriesYAxis = tr.ui.tracks.ChartSeriesYAxis;
   var ChartPoint = tr.ui.tracks.ChartPoint;
   var ChartSeries = tr.ui.tracks.ChartSeries;
-  var Range = tr.b.Range;
+  var Range = tr.b.math.Range;
 
   function buildRange() {
     var range = new Range();
diff --git a/tracing/tracing/ui/tracks/letter_dot_track.html b/tracing/tracing/ui/tracks/letter_dot_track.html
index db724f0..ef28274 100644
--- a/tracing/tracing/ui/tracks/letter_dot_track.html
+++ b/tracing/tracing/ui/tracks/letter_dot_track.html
@@ -6,7 +6,7 @@
 -->
 
 <link rel="import" href="/tracing/base/color_scheme.html">
-<link rel="import" href="/tracing/base/sorted_array_utils.html">
+<link rel="import" href="/tracing/base/math/sorted_array_utils.html">
 <link rel="import" href="/tracing/model/proxy_selectable_item.html">
 <link rel="import" href="/tracing/ui/base/event_presenter.html">
 <link rel="import" href="/tracing/ui/base/heading.html">
@@ -105,7 +105,7 @@
 
       // Draw the memory dumps.
       var items = this.items_;
-      var loI = tr.b.findLowIndexInSortedArray(
+      var loI = tr.b.math.findLowIndexInSortedArray(
           items,
           function(item) { return item.start; },
           viewLWorld);
@@ -175,7 +175,7 @@
         return;
 
       var itemRadiusWorld = viewPixWidthWorld * this.dumpRadiusView;
-      tr.b.iterateOverIntersectingIntervals(
+      tr.b.math.iterateOverIntersectingIntervals(
           this.items_,
           function(x) { return x.start - itemRadiusWorld; },
           function(x) { return 2 * itemRadiusWorld; },
@@ -222,7 +222,7 @@
       if (this.items_ === undefined)
         return;
 
-      var item = tr.b.findClosestElementInSortedArray(
+      var item = tr.b.math.findClosestElementInSortedArray(
           this.items_,
           function(x) { return x.start; },
           worldX,
diff --git a/tracing/tracing/ui/tracks/model_track.html b/tracing/tracing/ui/tracks/model_track.html
index d76fb8e..6dc7227 100644
--- a/tracing/tracing/ui/tracks/model_track.html
+++ b/tracing/tracing/ui/tracks/model_track.html
@@ -51,7 +51,7 @@
    * @param {number} maxTime the upper bound of time to stop striping at.
    *     of |times|.
    *
-   * @returns {!Array.<tr.b.Range>} An array of ranges where each element
+   * @returns {!Array.<tr.b.math.Range>} An array of ranges where each element
    *     represents the time range that a stripe covers. Each range is a subset
    *     of the interval [minTime, maxTime].
    */
@@ -60,7 +60,7 @@
 
     // Find the lowest and highest index within the viewport.
     var lowIndex =
-        tr.b.findLowIndexInSortedArray(times, tr.b.identity, minTime);
+        tr.b.math.findLowIndexInSortedArray(times, tr.b.identity, minTime);
     var highIndex = lowIndex - 1;
     while (times[highIndex + 1] <= maxTime) {
       highIndex++;
@@ -71,7 +71,7 @@
     for (var i = lowIndex - (lowIndex % 2); i <= highIndex; i += 2) {
       var left = i < lowIndex ? minTime : times[i];
       var right = i + 1 > highIndex ? maxTime : times[i + 1];
-      stripes.push(tr.b.Range.fromExplicitRange(left, right));
+      stripes.push(tr.b.math.Range.fromExplicitRange(left, right));
     }
 
     return stripes;
@@ -461,7 +461,7 @@
       var stripeDensity =
         stripeRange ? stripes.length / (dt.scaleX * stripeRange) : 0;
       var clampedStripeDensity =
-          tr.b.clamp(stripeDensity, ModelTrack.VSYNC_DENSITY_OPAQUE,
+          tr.b.math.clamp(stripeDensity, ModelTrack.VSYNC_DENSITY_OPAQUE,
               ModelTrack.VSYNC_DENSITY_TRANSPARENT);
       var opacity =
           (ModelTrack.VSYNC_DENSITY_TRANSPARENT - clampedStripeDensity) /
@@ -499,7 +499,7 @@
         selection.push(instantEvent);
       }
       var instantEventWidth = 3 * viewPixWidthWorld;
-      tr.b.iterateOverIntersectingIntervals(this.model_.instantEvents,
+      tr.b.math.iterateOverIntersectingIntervals(this.model_.instantEvents,
           function(x) { return x.start; },
           function(x) { return x.duration + instantEventWidth; },
           loWX, hiWX,
diff --git a/tracing/tracing/ui/tracks/model_track_test.html b/tracing/tracing/ui/tracks/model_track_test.html
index 9544fde..fb36462 100644
--- a/tracing/tracing/ui/tracks/model_track_test.html
+++ b/tracing/tracing/ui/tracks/model_track_test.html
@@ -12,8 +12,9 @@
 'use strict';
 
 tr.b.unittest.testSuite(function() {
-  var VIEW_L_WORLD = 100;
-  var VIEW_R_WORLD = 1000;
+  const Range = tr.b.math.Range;
+  const VIEW_L_WORLD = 100;
+  const VIEW_R_WORLD = 1000;
 
   function testGenerateStripes(times, expectedRanges) {
     var ranges = tr.ui.tracks.ModelTrack.generateStripes_(
@@ -23,9 +24,9 @@
   }
 
   test('generateStripesInside', function() {
-    var range200To500 = tr.b.Range.fromExplicitRange(200, 500);
-    var range800To900 = tr.b.Range.fromExplicitRange(800, 900);
-    var range998To999 = tr.b.Range.fromExplicitRange(998, 999);
+    var range200To500 = Range.fromExplicitRange(200, 500);
+    var range800To900 = Range.fromExplicitRange(800, 900);
+    var range998To999 = Range.fromExplicitRange(998, 999);
     testGenerateStripes([], []);
     testGenerateStripes([200, 500], [range200To500]);
     testGenerateStripes([200, 500, 800, 900], [range200To500, range800To900]);
@@ -35,7 +36,7 @@
   });
 
   test('generateStripesOutside', function() {
-    var range101To999 = tr.b.Range.fromExplicitRange(101, 999);
+    var range101To999 = Range.fromExplicitRange(101, 999);
     // Far left.
     testGenerateStripes([0, 99], []);
     testGenerateStripes([0, 10, 50, 99], []);
@@ -56,13 +57,13 @@
   });
 
   test('generateStripesOverlap', function() {
-    var rangeLeftWorldTo101 = tr.b.Range.fromExplicitRange(VIEW_L_WORLD, 101);
-    var range102To103 = tr.b.Range.fromExplicitRange(102, 103);
-    var range200To900 = tr.b.Range.fromExplicitRange(200, 900);
-    var range997To998 = tr.b.Range.fromExplicitRange(997, 998);
-    var range999ToRightWorld = tr.b.Range.fromExplicitRange(999, VIEW_R_WORLD);
+    var rangeLeftWorldTo101 = Range.fromExplicitRange(VIEW_L_WORLD, 101);
+    var range102To103 = Range.fromExplicitRange(102, 103);
+    var range200To900 = Range.fromExplicitRange(200, 900);
+    var range997To998 = Range.fromExplicitRange(997, 998);
+    var range999ToRightWorld = Range.fromExplicitRange(999, VIEW_R_WORLD);
     var rangeLeftWorldToRightWorld =
-        tr.b.Range.fromExplicitRange(VIEW_L_WORLD, VIEW_R_WORLD);
+        Range.fromExplicitRange(VIEW_L_WORLD, VIEW_R_WORLD);
 
 
     // Left overlap.
@@ -108,12 +109,12 @@
   });
 
   test('generateStripesOdd', function() {
-    var range500To900 = tr.b.Range.fromExplicitRange(500, 900);
-    var rangeLeftWorldTo200 = tr.b.Range.fromExplicitRange(VIEW_L_WORLD, 200);
-    var rangeLeftWorldTo500 = tr.b.Range.fromExplicitRange(VIEW_L_WORLD, 500);
-    var range500ToRightWorld = tr.b.Range.fromExplicitRange(500, VIEW_R_WORLD);
+    var range500To900 = Range.fromExplicitRange(500, 900);
+    var rangeLeftWorldTo200 = Range.fromExplicitRange(VIEW_L_WORLD, 200);
+    var rangeLeftWorldTo500 = Range.fromExplicitRange(VIEW_L_WORLD, 500);
+    var range500ToRightWorld = Range.fromExplicitRange(500, VIEW_R_WORLD);
     var rangeLeftWorldToRightWorld =
-        tr.b.Range.fromExplicitRange(VIEW_L_WORLD, VIEW_R_WORLD);
+        Range.fromExplicitRange(VIEW_L_WORLD, VIEW_R_WORLD);
 
     // One VSync.
     testGenerateStripes([0], [rangeLeftWorldToRightWorld]);
@@ -135,14 +136,14 @@
 
   test('generateStripesBorder', function() {
     var rangeLeftWorldToLeftWorld =
-        tr.b.Range.fromExplicitRange(VIEW_L_WORLD, VIEW_L_WORLD);
+        Range.fromExplicitRange(VIEW_L_WORLD, VIEW_L_WORLD);
     var rangeRightWorldToRightWorld =
-        tr.b.Range.fromExplicitRange(VIEW_R_WORLD, VIEW_R_WORLD);
+        Range.fromExplicitRange(VIEW_R_WORLD, VIEW_R_WORLD);
     var rangeLeftWorldToRightWorld =
-        tr.b.Range.fromExplicitRange(VIEW_L_WORLD, VIEW_R_WORLD);
-    var rangeLeftWorldTo200 = tr.b.Range.fromExplicitRange(VIEW_L_WORLD, 200);
-    var range200To500 = tr.b.Range.fromExplicitRange(200, 500);
-    var range500ToRightWorld = tr.b.Range.fromExplicitRange(500, VIEW_R_WORLD);
+        Range.fromExplicitRange(VIEW_L_WORLD, VIEW_R_WORLD);
+    var rangeLeftWorldTo200 = Range.fromExplicitRange(VIEW_L_WORLD, 200);
+    var range200To500 = Range.fromExplicitRange(200, 500);
+    var range500ToRightWorld = Range.fromExplicitRange(500, VIEW_R_WORLD);
     testGenerateStripes([0, VIEW_L_WORLD], [rangeLeftWorldToLeftWorld]);
     testGenerateStripes(
         [VIEW_L_WORLD, VIEW_L_WORLD],
diff --git a/tracing/tracing/ui/tracks/multi_row_track.html b/tracing/tracing/ui/tracks/multi_row_track.html
index bd6bfee..f161396 100644
--- a/tracing/tracing/ui/tracks/multi_row_track.html
+++ b/tracing/tracing/ui/tracks/multi_row_track.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/sorted_array_utils.html">
+<link rel="import" href="/tracing/base/math/sorted_array_utils.html">
 <link rel="import" href="/tracing/model/model_settings.html">
 <link rel="import" href="/tracing/ui/base/ui.html">
 <link rel="import" href="/tracing/ui/tracks/container_track.html">
diff --git a/tracing/tracing/ui/tracks/object_instance_group_track.html b/tracing/tracing/ui/tracks/object_instance_group_track.html
index d61f306..46188cc 100644
--- a/tracing/tracing/ui/tracks/object_instance_group_track.html
+++ b/tracing/tracing/ui/tracks/object_instance_group_track.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/sorted_array_utils.html">
+<link rel="import" href="/tracing/base/math/sorted_array_utils.html">
 <link rel="import" href="/tracing/ui/analysis/object_instance_view.html">
 <link rel="import" href="/tracing/ui/analysis/object_snapshot_view.html">
 <link rel="import" href="/tracing/ui/base/ui.html">
diff --git a/tracing/tracing/ui/tracks/object_instance_track.html b/tracing/tracing/ui/tracks/object_instance_track.html
index c53a77b..df37156 100644
--- a/tracing/tracing/ui/tracks/object_instance_track.html
+++ b/tracing/tracing/ui/tracks/object_instance_track.html
@@ -8,7 +8,7 @@
 <link rel="stylesheet" href="/tracing/ui/tracks/object_instance_track.css">
 
 <link rel="import" href="/tracing/base/extension_registry.html">
-<link rel="import" href="/tracing/base/sorted_array_utils.html">
+<link rel="import" href="/tracing/base/math/sorted_array_utils.html">
 <link rel="import" href="/tracing/model/event.html">
 <link rel="import" href="/tracing/ui/base/event_presenter.html">
 <link rel="import" href="/tracing/ui/base/heading.html">
@@ -119,7 +119,7 @@
 
       // Instances
       var objectInstances = this.objectInstances_;
-      var loI = tr.b.findLowIndexInSortedArray(
+      var loI = tr.b.math.findLowIndexInSortedArray(
           objectInstances,
           function(instance) {
             return instance.deletionTs;
@@ -141,7 +141,7 @@
 
       // Snapshots. Has to run in worldspace because ctx.arc gets transformed.
       var objectSnapshots = this.objectSnapshots_;
-      loI = tr.b.findLowIndexInSortedArray(
+      loI = tr.b.math.findLowIndexInSortedArray(
           objectSnapshots,
           function(snapshot) {
             return snapshot.ts + snapshotRadiusWorld;
@@ -218,7 +218,7 @@
       }
       var snapshotRadiusView = this.snapshotRadiusView;
       var snapshotRadiusWorld = viewPixWidthWorld * snapshotRadiusView;
-      tr.b.iterateOverIntersectingIntervals(
+      tr.b.math.iterateOverIntersectingIntervals(
           this.objectSnapshots_,
           function(x) { return x.ts - snapshotRadiusWorld; },
           function(x) { return 2 * snapshotRadiusWorld; },
@@ -228,7 +228,7 @@
         return;
 
       // Try picking instances.
-      tr.b.iterateOverIntersectingIntervals(
+      tr.b.math.iterateOverIntersectingIntervals(
           this.objectInstances_,
           function(x) { return x.creationTs; },
           function(x) { return x.deletionTs - x.creationTs; },
@@ -269,7 +269,7 @@
 
     addClosestEventToSelection: function(worldX, worldMaxDist, loY, hiY,
         selection) {
-      var snapshot = tr.b.findClosestElementInSortedArray(
+      var snapshot = tr.b.math.findClosestElementInSortedArray(
           this.objectSnapshots_,
           function(x) { return x.ts; },
           worldX,
diff --git a/tracing/tracing/ui/tracks/process_track.html b/tracing/tracing/ui/tracks/process_track.html
index e0588c8..055c1da 100644
--- a/tracing/tracing/ui/tracks/process_track.html
+++ b/tracing/tracing/ui/tracks/process_track.html
@@ -127,7 +127,7 @@
         selection.push(instantEvent);
       }
       var instantEventWidth = 2 * viewPixWidthWorld;
-      tr.b.iterateOverIntersectingIntervals(this.processBase.instantEvents,
+      tr.b.math.iterateOverIntersectingIntervals(this.processBase.instantEvents,
           function(x) { return x.start; },
           function(x) { return x.duration + instantEventWidth; },
           loWX, hiWX,
diff --git a/tracing/tracing/ui/tracks/rect_track.html b/tracing/tracing/ui/tracks/rect_track.html
index 6a2a3c0..f4120a1 100644
--- a/tracing/tracing/ui/tracks/rect_track.html
+++ b/tracing/tracing/ui/tracks/rect_track.html
@@ -7,7 +7,7 @@
 
 <link rel="stylesheet" href="/tracing/ui/tracks/rect_track.css">
 
-<link rel="import" href="/tracing/base/sorted_array_utils.html">
+<link rel="import" href="/tracing/base/math/sorted_array_utils.html">
 <link rel="import" href="/tracing/model/proxy_selectable_item.html">
 <link rel="import" href="/tracing/ui/base/draw_helpers.html">
 <link rel="import" href="/tracing/ui/base/fast_rect_renderer.html">
@@ -161,7 +161,7 @@
       }
       onRect = onRect.bind(this);
       var instantEventWidth = 2 * viewPixWidthWorld;
-      tr.b.iterateOverIntersectingIntervals(this.rects_,
+      tr.b.math.iterateOverIntersectingIntervals(this.rects_,
           function(x) { return x.start; },
           function(x) {
             return x.duration === 0 ?
@@ -212,7 +212,7 @@
 
     addClosestEventToSelection: function(worldX, worldMaxDist, loY, hiY,
         selection) {
-      var rect = tr.b.findClosestIntervalInSortedIntervals(
+      var rect = tr.b.math.findClosestIntervalInSortedIntervals(
           this.rects_,
           function(x) { return x.start; },
           function(x) { return x.end; },
diff --git a/tracing/tracing/ui/tracks/slice_group_track.html b/tracing/tracing/ui/tracks/slice_group_track.html
index 14894bb..6f238af 100644
--- a/tracing/tracing/ui/tracks/slice_group_track.html
+++ b/tracing/tracing/ui/tracks/slice_group_track.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/sorted_array_utils.html">
+<link rel="import" href="/tracing/base/math/sorted_array_utils.html">
 <link rel="import" href="/tracing/ui/base/ui.html">
 <link rel="import" href="/tracing/ui/tracks/multi_row_track.html">
 
diff --git a/tracing/tracing/ui/tracks/stacked_bars_track.html b/tracing/tracing/ui/tracks/stacked_bars_track.html
index 3118bd4..e618bc4 100644
--- a/tracing/tracing/ui/tracks/stacked_bars_track.html
+++ b/tracing/tracing/ui/tracks/stacked_bars_track.html
@@ -65,7 +65,7 @@
       var snapshots = this.objectInstance_.snapshots;
       var maxBounds = this.objectInstance_.parent.model.bounds.max;
 
-      tr.b.iterateOverIntersectingIntervals(
+      tr.b.math.iterateOverIntersectingIntervals(
           snapshots,
           function(x) { return x.ts; },
           function(x, i) {
@@ -110,7 +110,7 @@
 
     addClosestEventToSelection: function(worldX, worldMaxDist, loY, hiY,
         selection) {
-      var snapshot = tr.b.findClosestElementInSortedArray(
+      var snapshot = tr.b.math.findClosestElementInSortedArray(
           this.objectInstance_.snapshots,
           function(x) { return x.ts; },
           worldX,
diff --git a/tracing/tracing/ui/tracks/track.html b/tracing/tracing/ui/tracks/track.html
index 88988a2..62b18a5 100644
--- a/tracing/tracing/ui/tracks/track.html
+++ b/tracing/tracing/ui/tracks/track.html
@@ -146,7 +146,7 @@
 
     addClosestInstantEventToSelection: function(instantEvents, worldX,
         worldMaxDist, selection) {
-      var instantEvent = tr.b.findClosestElementInSortedArray(
+      var instantEvent = tr.b.math.findClosestElementInSortedArray(
           instantEvents,
           function(x) { return x.start; },
           worldX,
diff --git a/tracing/tracing/value/histogram.html b/tracing/tracing/value/histogram.html
index 30979e1..c774b0b 100644
--- a/tracing/tracing/value/histogram.html
+++ b/tracing/tracing/value/histogram.html
@@ -6,11 +6,11 @@
 -->
 
 <link rel="import" href="/tracing/base/iteration_helpers.html">
-<link rel="import" href="/tracing/base/range.html">
-<link rel="import" href="/tracing/base/running_statistics.html">
+<link rel="import" href="/tracing/base/math/range.html">
+<link rel="import" href="/tracing/base/math/running_statistics.html">
+<link rel="import" href="/tracing/base/math/sorted_array_utils.html">
+<link rel="import" href="/tracing/base/math/statistics.html">
 <link rel="import" href="/tracing/base/scalar.html">
-<link rel="import" href="/tracing/base/sorted_array_utils.html">
-<link rel="import" href="/tracing/base/statistics.html">
 <link rel="import" href="/tracing/base/unit.html">
 <link rel="import" href="/tracing/value/diagnostics/diagnostic_map.html">
 
@@ -63,7 +63,7 @@
 
   class HistogramBin {
     /**
-     * @param {!tr.b.Range} range
+     * @param {!tr.b.math.Range} range
      */
     constructor(range) {
       this.range = range;
@@ -82,7 +82,7 @@
      * @param {!tr.v.d.DiagnosticMap} diagnostics
      */
     addDiagnosticMap(diagnostics) {
-      tr.b.Statistics.uniformlySampleStream(
+      tr.b.math.Statistics.uniformlySampleStream(
           this.diagnosticMaps, this.count, diagnostics, MAX_DIAGNOSTIC_MAPS);
     }
 
@@ -90,7 +90,7 @@
       if (!this.range.equals(other.range)) {
         throw new Error('Merging incompatible Histogram bins.');
       }
-      tr.b.Statistics.mergeSampledStreams(this.diagnosticMaps, this.count,
+      tr.b.math.Statistics.mergeSampledStreams(this.diagnosticMaps, this.count,
           other.diagnosticMaps, other.count, MAX_DIAGNOSTIC_MAPS);
       this.count += other.count;
     }
@@ -193,7 +193,7 @@
 
     set maxNumSampleValues(n) {
       this.maxNumSampleValues_ = n;
-      tr.b.Statistics.uniformlySampleArray(
+      tr.b.math.Statistics.uniformlySampleArray(
           this.sampleValues_, this.maxNumSampleValues_);
     }
 
@@ -242,7 +242,7 @@
         }
       }
       if (dict.running) {
-        hist.running_ = tr.b.RunningStatistics.fromDict(dict.running);
+        hist.running_ = tr.b.math.RunningStatistics.fromDict(dict.running);
       }
       if (dict.summaryOptions) {
         hist.customizeSummaryOptions(dict.summaryOptions);
@@ -301,7 +301,7 @@
      *
      * @param {!tr.v.Histogram} other
      * @param {number=} opt_alpha
-     * @return {!tr.b.Statistics.Significance}
+     * @return {!tr.b.math.Statistics.Significance}
      */
     getDifferenceSignificance(other, opt_alpha) {
       if (this.unit !== other.unit) {
@@ -310,14 +310,14 @@
 
       if (this.unit.improvementDirection ===
           tr.b.ImprovementDirection.DONT_CARE) {
-        return tr.b.Statistics.Significance.DONT_CARE;
+        return tr.b.math.Statistics.Significance.DONT_CARE;
       }
 
       if (!(other instanceof Histogram)) {
         throw new Error('Unable to compute a p-value');
       }
 
-      let testResult = tr.b.Statistics.mwu(
+      let testResult = tr.b.math.Statistics.mwu(
           this.sampleValues, other.sampleValues, opt_alpha);
       return testResult.significance;
     }
@@ -363,7 +363,7 @@
 
     getBinForValue(value) {
       // Don't use subtraction to avoid arithmetic overflow.
-      let binIndex = tr.b.findHighIndexInSortedArray(
+      let binIndex = tr.b.math.findHighIndexInSortedArray(
           this.allBins, b => ((value < b.range.max) ? -1 : 1));
       return this.allBins[binIndex] || this.allBins[this.allBins.length - 1];
     }
@@ -381,12 +381,12 @@
       if (typeof(value) !== 'number' || isNaN(value)) {
         this.numNans++;
         if (opt_diagnostics) {
-          tr.b.Statistics.uniformlySampleStream(this.nanDiagnosticMaps,
+          tr.b.math.Statistics.uniformlySampleStream(this.nanDiagnosticMaps,
               this.numNans, opt_diagnostics, MAX_DIAGNOSTIC_MAPS);
         }
       } else {
         if (this.running_ === undefined) {
-          this.running_ = new tr.b.RunningStatistics();
+          this.running_ = new tr.b.math.RunningStatistics();
         }
         this.running_.add(value);
 
@@ -397,7 +397,7 @@
         }
       }
 
-      tr.b.Statistics.uniformlySampleStream(this.sampleValues_,
+      tr.b.math.Statistics.uniformlySampleStream(this.sampleValues_,
           this.numValues + this.numNans, value, this.maxNumSampleValues);
     }
 
@@ -432,7 +432,7 @@
             return false;
           }
           if (slice[0] !== otherSlice[0] ||
-              !tr.b.approximately(slice[1], otherSlice[1]) ||
+              !tr.b.math.approximately(slice[1], otherSlice[1]) ||
               slice[2] !== otherSlice[2]) {
             return false;
           }
@@ -440,7 +440,7 @@
           if (otherSlice instanceof Array) {
             return false;
           }
-          if (!tr.b.approximately(slice, otherSlice)) {
+          if (!tr.b.math.approximately(slice, otherSlice)) {
             return false;
           }
         }
@@ -458,9 +458,10 @@
         throw new Error('Merging incompatible Histograms');
       }
 
-      tr.b.Statistics.mergeSampledStreams(this.nanDiagnosticMaps, this.numNans,
-          other.nanDiagnosticMaps, other.numNans, MAX_DIAGNOSTIC_MAPS);
-      tr.b.Statistics.mergeSampledStreams(
+      tr.b.math.Statistics.mergeSampledStreams(this.nanDiagnosticMaps,
+          this.numNans, other.nanDiagnosticMaps, other.numNans,
+          MAX_DIAGNOSTIC_MAPS);
+      tr.b.math.Statistics.mergeSampledStreams(
           this.sampleValues, this.numValues + this.numNans,
           other.sampleValues, other.numValues + other.numNans,
           (this.maxNumSampleValues + other.maxNumSampleValues) / 2);
@@ -468,7 +469,7 @@
 
       if (other.running_ !== undefined) {
         if (this.running_ === undefined) {
-          this.running_ = new tr.b.RunningStatistics();
+          this.running_ = new tr.b.math.RunningStatistics();
         }
         this.running_ = this.running_.merge(other.running_);
       }
@@ -550,7 +551,7 @@
       }
       if (statName === 'min' || statName === 'max' || statName === 'sum') {
         if (this.running_ === undefined) {
-          this.running_ = new tr.b.RunningStatistics();
+          this.running_ = new tr.b.math.RunningStatistics();
         }
         return new tr.b.Scalar(this.unit, this.running_[statName]);
       }
@@ -601,7 +602,7 @@
             opt_referenceHistogram.standardDeviation);
       }
 
-      let mwu = opt_mwu || tr.b.Statistics.mwu(
+      let mwu = opt_mwu || tr.b.math.Statistics.mwu(
           this.sampleValues, opt_referenceHistogram.sampleValues);
       if (statName === P_VALUE_NAME) {
         return new tr.b.Scalar(tr.b.Unit.byName.unitlessNumber, mwu.p);
@@ -952,7 +953,7 @@
      */
     constructor(minBinBoundary) {
       this.builder_ = [minBinBoundary];
-      this.range_ = new tr.b.Range();
+      this.range_ = new tr.b.math.Range();
       this.range_.addValue(minBinBoundary);
       this.binRanges_ = undefined;
     }
@@ -1016,7 +1017,7 @@
     }
 
     /**
-     * @return {!Array.<!tr.b.Range>}
+     * @return {!Array.<!tr.b.math.Range>}
      */
     get binRanges() {
       if (this.binRanges_ === undefined) {
@@ -1034,14 +1035,14 @@
 
       if (prevBoundary > -Number.MAX_VALUE) {
         // underflow bin
-        this.binRanges_.push(tr.b.Range.fromExplicitRange(-Number.MAX_VALUE,
-            prevBoundary));
+        this.binRanges_.push(tr.b.math.Range.fromExplicitRange(
+            -Number.MAX_VALUE, prevBoundary));
       }
 
       for (let slice of this.builder_.slice(1)) {
         if (!(slice instanceof Array)) {
           this.binRanges_.push(
-              tr.b.Range.fromExplicitRange(prevBoundary, slice));
+              tr.b.math.Range.fromExplicitRange(prevBoundary, slice));
           prevBoundary = slice;
           continue;
         }
@@ -1055,7 +1056,7 @@
               let binWidth = (nextMaxBinBoundary - prevBoundary) / binCount;
               for (let i = 1; i < binCount; i++) {
                 let boundary = sliceMinBinBoundary + i * binWidth;
-                this.binRanges_.push(tr.b.Range.fromExplicitRange(
+                this.binRanges_.push(tr.b.math.Range.fromExplicitRange(
                     prevBoundary, boundary));
                 prevBoundary = boundary;
               }
@@ -1069,7 +1070,7 @@
               for (let i = 1; i < binCount; i++) {
                 let boundary = sliceMinBinBoundary * Math.exp(
                     i * binExponentWidth);
-                this.binRanges_.push(tr.b.Range.fromExplicitRange(
+                this.binRanges_.push(tr.b.math.Range.fromExplicitRange(
                     prevBoundary, boundary));
                 prevBoundary = boundary;
               }
@@ -1079,13 +1080,13 @@
           default:
             throw new Error('Unrecognized HistogramBinBoundaries slice type');
         }
-        this.binRanges_.push(tr.b.Range.fromExplicitRange(
+        this.binRanges_.push(tr.b.math.Range.fromExplicitRange(
             prevBoundary, nextMaxBinBoundary));
         prevBoundary = nextMaxBinBoundary;
       }
       if (prevBoundary < Number.MAX_VALUE) {
         // overflow bin
-        this.binRanges_.push(tr.b.Range.fromExplicitRange(
+        this.binRanges_.push(tr.b.math.Range.fromExplicitRange(
             prevBoundary, Number.MAX_VALUE));
       }
     }
diff --git a/tracing/tracing/value/histogram_set_test.html b/tracing/tracing/value/histogram_set_test.html
index 0f0c919..e8733d7 100644
--- a/tracing/tracing/value/histogram_set_test.html
+++ b/tracing/tracing/value/histogram_set_test.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/base/unit.html">
 <link rel="import" href="/tracing/value/diagnostics/diagnostic_map.html">
 <link rel="import" href="/tracing/value/diagnostics/generic.html">
diff --git a/tracing/tracing/value/histogram_test.html b/tracing/tracing/value/histogram_test.html
index b459ce5..6599ee7 100644
--- a/tracing/tracing/value/histogram_test.html
+++ b/tracing/tracing/value/histogram_test.html
@@ -227,7 +227,7 @@
 
     let dontCare = new tr.v.Histogram('', unitlessNumber, boundaries);
     assert.strictEqual(dontCare.getDifferenceSignificance(dontCare),
-        tr.b.Statistics.Significance.DONT_CARE);
+        tr.b.math.Statistics.Significance.DONT_CARE);
 
     for (let i = 0; i < 100; ++i) {
       histA.addSample(i);
@@ -235,13 +235,13 @@
     }
 
     assert.strictEqual(histA.getDifferenceSignificance(histB),
-        tr.b.Statistics.Significance.INSIGNIFICANT);
+        tr.b.math.Statistics.Significance.INSIGNIFICANT);
     assert.strictEqual(histB.getDifferenceSignificance(histA),
-        tr.b.Statistics.Significance.INSIGNIFICANT);
+        tr.b.math.Statistics.Significance.INSIGNIFICANT);
     assert.strictEqual(histA.getDifferenceSignificance(histB, 0.1),
-        tr.b.Statistics.Significance.SIGNIFICANT);
+        tr.b.math.Statistics.Significance.SIGNIFICANT);
     assert.strictEqual(histB.getDifferenceSignificance(histA, 0.1),
-        tr.b.Statistics.Significance.SIGNIFICANT);
+        tr.b.math.Statistics.Significance.SIGNIFICANT);
   });
 
   test('basic', function() {
@@ -378,7 +378,7 @@
           '', tr.b.Unit.byName.timeDurationInMs, boundaries);
       array.forEach((x) => hist.addSample(x, {foo: new tr.v.d.Generic('x')}));
       [0.25, 0.5, 0.75, 0.8, 0.95, 0.99].forEach(function(percent) {
-        let expected = tr.b.Statistics.percentile(array, percent);
+        let expected = tr.b.math.Statistics.percentile(array, percent);
         let actual = hist.getApproximatePercentile(percent);
         assert.closeTo(expected, actual, precision);
       });
@@ -409,20 +409,20 @@
     b.addBinBoundary(50);
 
     checkBoundaries(b, -100, 50, tr.b.Unit.byName.timeDurationInMs, [
-      tr.b.Range.fromExplicitRange(-Number.MAX_VALUE, -100),
-      tr.b.Range.fromExplicitRange(-100, 50),
-      tr.b.Range.fromExplicitRange(50, Number.MAX_VALUE)
+      tr.b.math.Range.fromExplicitRange(-Number.MAX_VALUE, -100),
+      tr.b.math.Range.fromExplicitRange(-100, 50),
+      tr.b.math.Range.fromExplicitRange(50, Number.MAX_VALUE)
     ]);
 
     b.addBinBoundary(60);
     b.addBinBoundary(75);
 
     checkBoundaries(b, -100, 75, tr.b.Unit.byName.timeDurationInMs, [
-      tr.b.Range.fromExplicitRange(-Number.MAX_VALUE, -100),
-      tr.b.Range.fromExplicitRange(-100, 50),
-      tr.b.Range.fromExplicitRange(50, 60),
-      tr.b.Range.fromExplicitRange(60, 75),
-      tr.b.Range.fromExplicitRange(75, Number.MAX_VALUE)
+      tr.b.math.Range.fromExplicitRange(-Number.MAX_VALUE, -100),
+      tr.b.math.Range.fromExplicitRange(-100, 50),
+      tr.b.math.Range.fromExplicitRange(50, 60),
+      tr.b.math.Range.fromExplicitRange(60, 75),
+      tr.b.math.Range.fromExplicitRange(75, Number.MAX_VALUE)
     ]);
   });
 
@@ -431,13 +431,13 @@
     b.addLinearBins(1200, 5);
 
     checkBoundaries(b, 1000, 1200, tr.b.Unit.byName.powerInWatts, [
-      tr.b.Range.fromExplicitRange(-Number.MAX_VALUE, 1000),
-      tr.b.Range.fromExplicitRange(1000, 1040),
-      tr.b.Range.fromExplicitRange(1040, 1080),
-      tr.b.Range.fromExplicitRange(1080, 1120),
-      tr.b.Range.fromExplicitRange(1120, 1160),
-      tr.b.Range.fromExplicitRange(1160, 1200),
-      tr.b.Range.fromExplicitRange(1200, Number.MAX_VALUE)
+      tr.b.math.Range.fromExplicitRange(-Number.MAX_VALUE, 1000),
+      tr.b.math.Range.fromExplicitRange(1000, 1040),
+      tr.b.math.Range.fromExplicitRange(1040, 1080),
+      tr.b.math.Range.fromExplicitRange(1080, 1120),
+      tr.b.math.Range.fromExplicitRange(1120, 1160),
+      tr.b.math.Range.fromExplicitRange(1160, 1200),
+      tr.b.math.Range.fromExplicitRange(1200, Number.MAX_VALUE)
     ]);
   });
 
@@ -446,12 +446,12 @@
     b.addExponentialBins(8, 4);
 
     checkBoundaries(b, 0.5, 8, tr.b.Unit.byName.energyInJoules, [
-      tr.b.Range.fromExplicitRange(-Number.MAX_VALUE, 0.5),
-      tr.b.Range.fromExplicitRange(0.5, 1),
-      tr.b.Range.fromExplicitRange(1, 2),
-      tr.b.Range.fromExplicitRange(2, 4),
-      tr.b.Range.fromExplicitRange(4, 8),
-      tr.b.Range.fromExplicitRange(8, Number.MAX_VALUE)
+      tr.b.math.Range.fromExplicitRange(-Number.MAX_VALUE, 0.5),
+      tr.b.math.Range.fromExplicitRange(0.5, 1),
+      tr.b.math.Range.fromExplicitRange(1, 2),
+      tr.b.math.Range.fromExplicitRange(2, 4),
+      tr.b.math.Range.fromExplicitRange(4, 8),
+      tr.b.math.Range.fromExplicitRange(8, Number.MAX_VALUE)
     ]);
   });
 
@@ -464,19 +464,19 @@
     b.addBinBoundary(100);
 
     checkBoundaries(b, -273.15, 100, tr.b.Unit.byName.unitlessNumber, [
-      tr.b.Range.fromExplicitRange(-Number.MAX_VALUE, -273.15),
-      tr.b.Range.fromExplicitRange(-273.15, -50),
-      tr.b.Range.fromExplicitRange(-50, -32),
-      tr.b.Range.fromExplicitRange(-32, -14),
-      tr.b.Range.fromExplicitRange(-14, 4),
-      tr.b.Range.fromExplicitRange(4, 8),
-      tr.b.Range.fromExplicitRange(8, 16),
-      tr.b.Range.fromExplicitRange(16, 16.25),
-      tr.b.Range.fromExplicitRange(16.25, 16.5),
-      tr.b.Range.fromExplicitRange(16.5, 16.75),
-      tr.b.Range.fromExplicitRange(16.75, 17),
-      tr.b.Range.fromExplicitRange(17, 100),
-      tr.b.Range.fromExplicitRange(100, Number.MAX_VALUE)
+      tr.b.math.Range.fromExplicitRange(-Number.MAX_VALUE, -273.15),
+      tr.b.math.Range.fromExplicitRange(-273.15, -50),
+      tr.b.math.Range.fromExplicitRange(-50, -32),
+      tr.b.math.Range.fromExplicitRange(-32, -14),
+      tr.b.math.Range.fromExplicitRange(-14, 4),
+      tr.b.math.Range.fromExplicitRange(4, 8),
+      tr.b.math.Range.fromExplicitRange(8, 16),
+      tr.b.math.Range.fromExplicitRange(16, 16.25),
+      tr.b.math.Range.fromExplicitRange(16.25, 16.5),
+      tr.b.math.Range.fromExplicitRange(16.5, 16.75),
+      tr.b.math.Range.fromExplicitRange(16.75, 17),
+      tr.b.math.Range.fromExplicitRange(17, 100),
+      tr.b.math.Range.fromExplicitRange(100, Number.MAX_VALUE)
     ]);
   });
 
diff --git a/tracing/tracing/value/ui/histogram_set_table_row.html b/tracing/tracing/value/ui/histogram_set_table_row.html
index 0fc8d36..67b224e 100644
--- a/tracing/tracing/value/ui/histogram_set_table_row.html
+++ b/tracing/tracing/value/ui/histogram_set_table_row.html
@@ -154,7 +154,7 @@
 
     maybeRebin_() {
       // if all of |this| row's columns are single-bin, then re-bin all of them.
-      const dataRange = new tr.b.Range();
+      const dataRange = new tr.b.math.Range();
       for (const hist of this.columns.values()) {
         if (!(hist instanceof tr.v.Histogram)) continue;
         if (hist.allBins.length > 1) return;  // don't re-bin
@@ -163,8 +163,8 @@
         dataRange.addValue(hist.max);
       }
 
-      dataRange.addValue(tr.b.lesserWholeNumber(dataRange.min));
-      dataRange.addValue(tr.b.greaterWholeNumber(dataRange.max));
+      dataRange.addValue(tr.b.math.lesserWholeNumber(dataRange.min));
+      dataRange.addValue(tr.b.math.greaterWholeNumber(dataRange.max));
 
       if (dataRange.min === dataRange.max) return;  // don't rebin
 
@@ -311,7 +311,7 @@
 
     get overviewDataRange() {
       if (this.overviewDataRange_ === undefined) {
-        this.overviewDataRange_ = new tr.b.Range();
+        this.overviewDataRange_ = new tr.b.math.Range();
         for (let [displayLabel, hist] of this.columns) {
           if (hist.average !== undefined) {
             this.overviewDataRange_.addValue(hist.average);
diff --git a/tracing/tracing/value/ui/histogram_set_table_row_state.html b/tracing/tracing/value/ui/histogram_set_table_row_state.html
index 9d797d2..6c0316b 100644
--- a/tracing/tracing/value/ui/histogram_set_table_row_state.html
+++ b/tracing/tracing/value/ui/histogram_set_table_row_state.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/range.html">
+<link rel="import" href="/tracing/base/math/range.html">
 
 <script>
 'use strict';
@@ -13,7 +13,7 @@
   class HistogramSetTableCellState {
     constructor() {
       this.isOpen_ = false;
-      this.brushedBinRange_ = new tr.b.Range();
+      this.brushedBinRange_ = new tr.b.math.Range();
       this.mergeSampleDiagnostics_ = true;
     }
 
@@ -59,7 +59,7 @@
         cell.mergeSampleDiagnostics = false;
       }
       if (dict.brushedBinRange) {
-        cell.brushedBinRange = tr.b.Range.fromExplicitRange(
+        cell.brushedBinRange = tr.b.math.Range.fromExplicitRange(
             dict.brushedBinRange[0], dict.brushedBinRange[1]);
       }
       return cell;
diff --git a/tracing/tracing/value/ui/histogram_set_table_row_state_test.html b/tracing/tracing/value/ui/histogram_set_table_row_state_test.html
index 8b19a4f..6d1b0d8 100644
--- a/tracing/tracing/value/ui/histogram_set_table_row_state_test.html
+++ b/tracing/tracing/value/ui/histogram_set_table_row_state_test.html
@@ -18,7 +18,7 @@
     const cellState = new tr.v.ui.HistogramSetTableCellState();
     rowState.cells.set('A', cellState);
     cellState.isOpen = true;
-    cellState.brushedBinRange = tr.b.Range.fromExplicitRange(2, 4);
+    cellState.brushedBinRange = tr.b.math.Range.fromExplicitRange(2, 4);
     cellState.mergeSampleDiagnostics = false;
 
     const clone = rowState.clone();
diff --git a/tracing/tracing/value/ui/histogram_set_table_test.html b/tracing/tracing/value/ui/histogram_set_table_test.html
index ed4d21f..eb1d964 100644
--- a/tracing/tracing/value/ui/histogram_set_table_test.html
+++ b/tracing/tracing/value/ui/histogram_set_table_test.html
@@ -198,31 +198,31 @@
 
     assert.deepEqual(charts[0].data, [{x: '0', y: 45}, {x: '1', y: 54}]);
     tr.b.assertRangeEquals(
-        charts[0].dataRange, tr.b.Range.fromExplicitRange(0, 99));
+        charts[0].dataRange, tr.b.math.Range.fromExplicitRange(0, 99));
 
     assert.deepEqual(
         charts[1].data, [{x: 'story0', y: 0}, {x: 'story1', y: 90}]);
     tr.b.assertRangeEquals(
-        charts[1].dataRange, tr.b.Range.fromExplicitRange(0, 99));
+        charts[1].dataRange, tr.b.math.Range.fromExplicitRange(0, 99));
 
     assert.deepEqual(
         charts[2].data, [{x: 'story0', y: 9}, {x: 'story1', y: 99}]);
     tr.b.assertRangeEquals(
-        charts[2].dataRange, tr.b.Range.fromExplicitRange(0, 99));
+        charts[2].dataRange, tr.b.math.Range.fromExplicitRange(0, 99));
 
     assert.deepEqual(charts[3].data, [{x: '0', y: 50}, {x: '1', y: 60}]);
     tr.b.assertRangeEquals(
-        charts[3].dataRange, tr.b.Range.fromExplicitRange(0, 110));
+        charts[3].dataRange, tr.b.math.Range.fromExplicitRange(0, 110));
 
     assert.deepEqual(
         charts[4].data, [{x: 'story0', y: 0}, {x: 'story1', y: 100}]);
     tr.b.assertRangeEquals(
-        charts[4].dataRange, tr.b.Range.fromExplicitRange(0, 110));
+        charts[4].dataRange, tr.b.math.Range.fromExplicitRange(0, 110));
 
     assert.deepEqual(
         charts[5].data, [{x: 'story0', y: 10}, {x: 'story1', y: 110}]);
     tr.b.assertRangeEquals(
-        charts[5].dataRange, tr.b.Range.fromExplicitRange(0, 110));
+        charts[5].dataRange, tr.b.math.Range.fromExplicitRange(0, 110));
 
     let hideOverview = tr.b.findDeepElementMatchingPredicate(
         table, elem => elem.id === 'hide_overview');
diff --git a/tracing/tracing/value/ui/histogram_span.html b/tracing/tracing/value/ui/histogram_span.html
index f9001f4..b6400a7 100644
--- a/tracing/tracing/value/ui/histogram_span.html
+++ b/tracing/tracing/value/ui/histogram_span.html
@@ -5,7 +5,7 @@
 found in the LICENSE file.
 -->
 
-<link rel="import" href="/tracing/base/statistics.html">
+<link rel="import" href="/tracing/base/math/statistics.html">
 <link rel="import" href="/tracing/ui/base/box_chart.html">
 <link rel="import" href="/tracing/ui/base/drag_handle.html">
 <link rel="import" href="/tracing/ui/base/name_bar_chart.html">
@@ -198,7 +198,7 @@
 
     set brushedBins(bins) {
       this.brushedBins_ = bins;
-      let brushedBinIndices = new tr.b.Range();
+      let brushedBinIndices = new tr.b.math.Range();
       for (let bin of bins) {
         brushedBinIndices.addValue(this.histogram.allBins.indexOf(bin));
       }
@@ -207,10 +207,10 @@
     },
 
     updateBrushedRange_(binIndex) {
-      let brushedBinIndices = new tr.b.Range();
-      brushedBinIndices.addValue(tr.b.clamp(
+      let brushedBinIndices = new tr.b.math.Range();
+      brushedBinIndices.addValue(tr.b.math.clamp(
           this.mouseDownBinIndex_, 0, this.histogram.allBins.length - 1));
-      brushedBinIndices.addValue(tr.b.clamp(
+      brushedBinIndices.addValue(tr.b.math.clamp(
           binIndex, 0, this.histogram.allBins.length - 1));
       brushedBinIndices.max += 1;
       this.chart_.brushedRange = brushedBinIndices;
@@ -249,7 +249,7 @@
           this.brushedBins_.length === 1 &&
           this.prevBrushedBins_[0] === this.brushedBins_[0]) {
         this.brushedBins_ = [];
-        this.chart_.brushedRange = new tr.b.Range();
+        this.chart_.brushedRange = new tr.b.math.Range();
       }
       this.updateDiagnostics_();
       this.mouseDownBinIndex_ = undefined;
@@ -306,7 +306,7 @@
     getDeltaScalars_(statNames, scalarMap) {
       if (!this.histogram.canCompare(this.referenceHistogram)) return;
 
-      let mwu = tr.b.Statistics.mwu(
+      let mwu = tr.b.math.Statistics.mwu(
           this.histogram.sampleValues, this.referenceHistogram.sampleValues);
 
       for (let deltaStatName of tr.v.Histogram.getDeltaStatisticsNames(
@@ -414,7 +414,7 @@
       this.chart_.hideLegend = true;
       this.chart_.getDataSeries('y').color = 'blue';
       this.chart_.xAxisLabel = '#';
-      this.chart_.brushedRange = new tr.b.Range();
+      this.chart_.brushedRange = new tr.b.math.Range();
 
       let chartData = [];
       let binCounts = [];
@@ -434,7 +434,7 @@
       // largest bin, then set the dataRange max to TRUNCATE_BIN_MARGIN% more
       // than that next largest bin.
       binCounts.sort((x, y) => y - x);
-      let dataRange = tr.b.Range.fromExplicitRange(0, binCounts[0]);
+      let dataRange = tr.b.math.Range.fromExplicitRange(0, binCounts[0]);
       if (binCounts[1] > 0 && binCounts[0] > (binCounts[1] * 2)) {
         dataRange.max = binCounts[1] * (1 + TRUNCATE_BIN_MARGIN);
       }
diff --git a/tracing/tracing/value/ui/scalar_context_controller.html b/tracing/tracing/value/ui/scalar_context_controller.html
index a3d1f1e..cc167bb 100644
--- a/tracing/tracing/value/ui/scalar_context_controller.html
+++ b/tracing/tracing/value/ui/scalar_context_controller.html
@@ -6,8 +6,8 @@
 -->
 
 <link rel="import" href="/tracing/base/event.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/base/raf.html">
-<link rel="import" href="/tracing/base/range.html">
 
 <dom-module id='tr-v-ui-scalar-context-controller'>
   <template></template>
@@ -112,7 +112,7 @@
       if (context === undefined) {
         context = {
           spans: new Set(),
-          range: new tr.b.Range()
+          range: new tr.b.math.Range()
         };
         this.groupToContext_.set(group, context);
       }
diff --git a/tracing/tracing/value/ui/scalar_context_controller_test.html b/tracing/tracing/value/ui/scalar_context_controller_test.html
index 245b5bc..3f5ead9 100644
--- a/tracing/tracing/value/ui/scalar_context_controller_test.html
+++ b/tracing/tracing/value/ui/scalar_context_controller_test.html
@@ -6,8 +6,8 @@
 -->
 
 <link rel="import" href="/tracing/base/iteration_helpers.html">
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/base/raf.html">
-<link rel="import" href="/tracing/base/range.html">
 <link rel="import" href="/tracing/value/ui/scalar_context_controller.html">
 
 <dom-module id='tr-v-ui-scalar-context-controller-mock-host'>
@@ -203,27 +203,27 @@
     c.onScalarSpanAdded('G', s1);
     c.expectContextUpdatedEventForTesting(['G']);
     assert.isTrue(c.getContext('G').range.equals(
-        tr.b.Range.fromExplicitRange(10, 10)));
+        tr.b.math.Range.fromExplicitRange(10, 10)));
     assert.sameMembers(tr.b.asArray(c.getContext('G').spans), [s1]);
 
     let s2 = {value: 15};
     c.onScalarSpanAdded('G', s2);
     c.expectContextUpdatedEventForTesting(['G']);
     assert.isTrue(c.getContext('G').range.equals(
-        tr.b.Range.fromExplicitRange(10, 15)));
+        tr.b.math.Range.fromExplicitRange(10, 15)));
     assert.sameMembers(tr.b.asArray(c.getContext('G').spans), [s1, s2]);
 
     s1.value = 5;
     c.onScalarSpanUpdated('G', s1);
     c.expectContextUpdatedEventForTesting(['G']);
     assert.isTrue(c.getContext('G').range.equals(
-        tr.b.Range.fromExplicitRange(5, 15)));
+        tr.b.math.Range.fromExplicitRange(5, 15)));
     assert.sameMembers(tr.b.asArray(c.getContext('G').spans), [s1, s2]);
 
     c.onScalarSpanRemoved('G', s2);
     c.expectContextUpdatedEventForTesting(['G']);
     assert.isTrue(c.getContext('G').range.equals(
-        tr.b.Range.fromExplicitRange(5, 5)));
+        tr.b.math.Range.fromExplicitRange(5, 5)));
     assert.sameMembers(tr.b.asArray(c.getContext('G').spans), [s1]);
 
     let s3 = {value: 0};
@@ -232,7 +232,7 @@
     c.onScalarSpanAdded('G', s2);
     c.expectContextUpdatedEventForTesting(['G']);
     assert.isTrue(c.getContext('G').range.equals(
-        tr.b.Range.fromExplicitRange(0, 14)));
+        tr.b.math.Range.fromExplicitRange(0, 14)));
     assert.sameMembers(tr.b.asArray(c.getContext('G').spans), [s1, s2, s3]);
 
     c.onScalarSpanRemoved('G', s1);
@@ -244,7 +244,7 @@
     c.onScalarSpanAdded('G', s2);
     c.expectContextUpdatedEventForTesting(['G']);
     assert.isTrue(c.getContext('G').range.equals(
-        tr.b.Range.fromExplicitRange(14, 14)));
+        tr.b.math.Range.fromExplicitRange(14, 14)));
     assert.sameMembers(tr.b.asArray(c.getContext('G').spans), [s2]);
   });
 
@@ -256,14 +256,14 @@
     c.onScalarSpanAdded('G1', s1);
     c.expectContextUpdatedEventForTesting(['G1']);
     assert.isTrue(c.getContext('G1').range.equals(
-        tr.b.Range.fromExplicitRange(0, 0)));
+        tr.b.math.Range.fromExplicitRange(0, 0)));
     assert.sameMembers(tr.b.asArray(c.getContext('G1').spans), [s1]);
 
     let s2 = {value: 1};
     c.onScalarSpanAdded('G2', s2);
     c.expectContextUpdatedEventForTesting(['G2']);
     assert.isTrue(c.getContext('G2').range.equals(
-        tr.b.Range.fromExplicitRange(1, 1)));
+        tr.b.math.Range.fromExplicitRange(1, 1)));
     assert.sameMembers(tr.b.asArray(c.getContext('G2').spans), [s2]);
 
     let s3 = {value: 2};
@@ -272,20 +272,20 @@
     c.onScalarSpanAdded('G1', s4);
     c.expectContextUpdatedEventForTesting(['G1', 'G2']);
     assert.isTrue(c.getContext('G1').range.equals(
-        tr.b.Range.fromExplicitRange(-1, 0)));
+        tr.b.math.Range.fromExplicitRange(-1, 0)));
     assert.sameMembers(tr.b.asArray(c.getContext('G1').spans), [s1, s4]);
     assert.isTrue(c.getContext('G2').range.equals(
-        tr.b.Range.fromExplicitRange(1, 2)));
+        tr.b.math.Range.fromExplicitRange(1, 2)));
     assert.sameMembers(tr.b.asArray(c.getContext('G2').spans), [s2, s3]);
 
     c.onScalarSpanRemoved('G2', s3);
     c.onScalarSpanAdded('G1', s3);
     c.expectContextUpdatedEventForTesting(['G1', 'G2']);
     assert.isTrue(c.getContext('G1').range.equals(
-        tr.b.Range.fromExplicitRange(-1, 2)));
+        tr.b.math.Range.fromExplicitRange(-1, 2)));
     assert.sameMembers(tr.b.asArray(c.getContext('G1').spans), [s1, s3, s4]);
     assert.isTrue(c.getContext('G2').range.equals(
-        tr.b.Range.fromExplicitRange(1, 1)));
+        tr.b.math.Range.fromExplicitRange(1, 1)));
     assert.sameMembers(tr.b.asArray(c.getContext('G2').spans), [s2]);
 
     s4.value = 3;
@@ -294,16 +294,16 @@
     c.onScalarSpanUpdated('G1', s1);
     c.expectContextUpdatedEventForTesting(['G1']);
     assert.isTrue(c.getContext('G1').range.equals(
-        tr.b.Range.fromExplicitRange(1, 3)));
+        tr.b.math.Range.fromExplicitRange(1, 3)));
     assert.sameMembers(tr.b.asArray(c.getContext('G1').spans), [s1, s3, s4]);
     assert.isTrue(c.getContext('G2').range.equals(
-        tr.b.Range.fromExplicitRange(1, 1)));
+        tr.b.math.Range.fromExplicitRange(1, 1)));
     assert.sameMembers(tr.b.asArray(c.getContext('G2').spans), [s2]);
 
     c.onScalarSpanRemoved('G2', s2);
     c.expectContextUpdatedEventForTesting(['G2']);
     assert.isTrue(c.getContext('G1').range.equals(
-        tr.b.Range.fromExplicitRange(1, 3)));
+        tr.b.math.Range.fromExplicitRange(1, 3)));
     assert.sameMembers(tr.b.asArray(c.getContext('G1').spans), [s1, s3, s4]);
     assert.isUndefined(c.getContext('G2'));
   });
diff --git a/tracing/tracing/value/ui/scalar_map_table.html b/tracing/tracing/value/ui/scalar_map_table.html
index de4bfba..b180071 100644
--- a/tracing/tracing/value/ui/scalar_map_table.html
+++ b/tracing/tracing/value/ui/scalar_map_table.html
@@ -25,7 +25,7 @@
     /** @type {!Map.<string, !tr.b.Scalar>} */
     this.scalarMap_ = new Map();
 
-    /** @type {!Map.<string, !tr.b.Statistics.Significance>} */
+    /** @type {!Map.<string, !tr.b.math.Statistics.Significance>} */
     this.significance_ = new Map();
   },
 
@@ -67,7 +67,7 @@
 
   /**
    * @param {string} key
-   * @param {!tr.b.Statistics.Significance} significance
+   * @param {!tr.b.math.Statistics.Significance} significance
    */
   setSignificanceForKey: function(key, significance) {
     this.significance_.set(key, significance);
diff --git a/tracing/tracing/value/ui/scalar_span.html b/tracing/tracing/value/ui/scalar_span.html
index 97723e4..71d9d0f 100644
--- a/tracing/tracing/value/ui/scalar_span.html
+++ b/tracing/tracing/value/ui/scalar_span.html
@@ -22,11 +22,11 @@
    *
    * @param {undefined|tr.b.Scalar|tr.v.Histogram} value
    * @param {Object=} opt_config
-   * @param {!tr.b.Range=} opt_config.customContextRange
+   * @param {!tr.b.math.Range=} opt_config.customContextRange
    * @param {boolean=} opt_config.leftAlign
    * @param {boolean=} opt_config.inline
    * @param {!tr.b.Unit=} opt_config.unit
-   * @param {tr.b.Statistics.Significance=} opt_config.significance
+   * @param {tr.b.math.Statistics.Significance=} opt_config.significance
    * @param {string=} opt_config.contextGroup
    * @return {(string|!HTMLElement)}
    */
@@ -245,7 +245,7 @@
     this.context_ = undefined;
 
     this.warning_ = undefined;
-    this.significance_ = tr.b.Statistics.Significance.DONT_CARE;
+    this.significance_ = tr.b.math.Statistics.Significance.DONT_CARE;
 
     // To avoid unnecessary DOM traversal, search for the context controller
     // only when necessary (when the span is attached and has a context group).
@@ -527,17 +527,17 @@
     Polymer.dom(this.$.content).classList.add(changeClass);
 
     switch (this.significance) {
-      case tr.b.Statistics.Significance.DONT_CARE:
+      case tr.b.math.Statistics.Significance.DONT_CARE:
         break;
 
-      case tr.b.Statistics.Significance.INSIGNIFICANT:
+      case tr.b.math.Statistics.Significance.INSIGNIFICANT:
         if (changeClass !== 'same')
           title = 'insignificant ' + title;
         this.$.insignificant.style.display = 'inline';
         changeClass = 'same';
         break;
 
-      case tr.b.Statistics.Significance.SIGNIFICANT:
+      case tr.b.math.Statistics.Significance.SIGNIFICANT:
         if (changeClass === 'same')
           throw new Error('How can no change be significant?');
         this.$['significantly_' + changeClass].style.display = 'inline';
diff --git a/tracing/tracing/value/ui/scalar_span_test.html b/tracing/tracing/value/ui/scalar_span_test.html
index 0186d60..6e94a43 100644
--- a/tracing/tracing/value/ui/scalar_span_test.html
+++ b/tracing/tracing/value/ui/scalar_span_test.html
@@ -5,8 +5,8 @@
 found in the LICENSE file.
 -->
 
+<link rel="import" href="/tracing/base/math/range.html">
 <link rel="import" href="/tracing/base/raf.html">
-<link rel="import" href="/tracing/base/range.html">
 <link rel="import" href="/tracing/base/time_display_modes.html">
 <link rel="import" href="/tracing/base/unit.html">
 <link rel="import" href="/tracing/base/unit_scale.html">
@@ -68,46 +68,46 @@
     let zero = String.fromCharCode(177) + '0';
 
     checkScalarSpan(this, 0, countSIBD, zero, {
-      significance: tr.b.Statistics.Significance.DONT_CARE,
+      significance: tr.b.math.Statistics.Significance.DONT_CARE,
       expectedTitle: 'no change',
       expectedEmoji: ''
     });
 
     checkScalarSpan(this, 0, countSIBD, zero, {
       expectedEmoji: 'insignificant',
-      significance: tr.b.Statistics.Significance.INSIGNIFICANT,
+      significance: tr.b.math.Statistics.Significance.INSIGNIFICANT,
       expectedEmojiColor: 'rgb(0, 0, 0)',
       expectedTitle: 'no change'
     });
 
     assert.throws(() => checkScalarSpan(this, 0, countSIBD, zero,
-      {significance: tr.b.Statistics.Significance.SIGNIFICANT}));
+      {significance: tr.b.math.Statistics.Significance.SIGNIFICANT}));
 
     checkScalarSpan(this, 0, countBIBD, zero, {
-      significance: tr.b.Statistics.Significance.DONT_CARE,
+      significance: tr.b.math.Statistics.Significance.DONT_CARE,
       expectedTitle: 'no change',
       expectedEmoji: ''
     });
 
     checkScalarSpan(this, 0, countBIBD, zero, {
       expectedEmoji: 'insignificant',
-      significance: tr.b.Statistics.Significance.INSIGNIFICANT,
+      significance: tr.b.math.Statistics.Significance.INSIGNIFICANT,
       expectedEmojiColor: 'rgb(0, 0, 0)',
       expectedTitle: 'no change'
     });
 
     assert.throws(() => checkScalarSpan(this, 0, countSIBD, zero,
-      {significance: tr.b.Statistics.Significance.SIGNIFICANT}));
+      {significance: tr.b.math.Statistics.Significance.SIGNIFICANT}));
 
     checkScalarSpan(this, 1, countSIBD, '+1', {
-      significance: tr.b.Statistics.Significance.DONT_CARE,
+      significance: tr.b.math.Statistics.Significance.DONT_CARE,
       expectedColor: 'rgb(255, 0, 0)',
       expectedTitle: 'regression',
       expectedEmoji: ''
     });
 
     checkScalarSpan(this, 1, countSIBD, '+1', {
-      significance: tr.b.Statistics.Significance.INSIGNIFICANT,
+      significance: tr.b.math.Statistics.Significance.INSIGNIFICANT,
       expectedColor: 'rgb(255, 0, 0)',
       expectedEmoji: 'insignificant',
       expectedEmojiColor: 'rgb(0, 0, 0)',
@@ -115,7 +115,7 @@
     });
 
     checkScalarSpan(this, 1, countSIBD, '+1', {
-      significance: tr.b.Statistics.Significance.SIGNIFICANT,
+      significance: tr.b.math.Statistics.Significance.SIGNIFICANT,
       expectedColor: 'rgb(255, 0, 0)',
       expectedEmoji: 'significantly_worse',
       expectedEmojiColor: 'rgb(255, 0, 0)',
@@ -123,14 +123,14 @@
     });
 
     checkScalarSpan(this, 1, countBIBD, '+1', {
-      significance: tr.b.Statistics.Significance.DONT_CARE,
+      significance: tr.b.math.Statistics.Significance.DONT_CARE,
       expectedColor: 'rgb(0, 128, 0)',
       expectedTitle: 'improvement',
       expectedEmoji: ''
     });
 
     checkScalarSpan(this, 1, countBIBD, '+1', {
-      significance: tr.b.Statistics.Significance.INSIGNIFICANT,
+      significance: tr.b.math.Statistics.Significance.INSIGNIFICANT,
       expectedColor: 'rgb(0, 128, 0)',
       expectedEmoji: 'insignificant',
       expectedEmojiColor: 'rgb(0, 0, 0)',
@@ -138,7 +138,7 @@
     });
 
     checkScalarSpan(this, 1, countBIBD, '+1', {
-      significance: tr.b.Statistics.Significance.SIGNIFICANT,
+      significance: tr.b.math.Statistics.Significance.SIGNIFICANT,
       expectedColor: 'rgb(0, 128, 0)',
       expectedEmoji: 'significantly_better',
       expectedEmojiColor: 'rgb(0, 128, 0)',
@@ -146,7 +146,7 @@
     });
 
     checkScalarSpan(this, -1, countSIBD, '-1', {
-      significance: tr.b.Statistics.Significance.DONT_CARE,
+      significance: tr.b.math.Statistics.Significance.DONT_CARE,
       expectedColor: 'rgb(0, 128, 0)',
       expectedEmoji: '',
       expectedEmojiColor: '',
@@ -154,7 +154,7 @@
     });
 
     checkScalarSpan(this, -1, countSIBD, '-1', {
-      significance: tr.b.Statistics.Significance.INSIGNIFICANT,
+      significance: tr.b.math.Statistics.Significance.INSIGNIFICANT,
       expectedColor: 'rgb(0, 128, 0)',
       expectedEmoji: 'insignificant',
       expectedEmojiColor: 'rgb(0, 0, 0)',
@@ -162,7 +162,7 @@
     });
 
     checkScalarSpan(this, -1, countSIBD, '-1', {
-      significance: tr.b.Statistics.Significance.SIGNIFICANT,
+      significance: tr.b.math.Statistics.Significance.SIGNIFICANT,
       expectedColor: 'rgb(0, 128, 0)',
       expectedEmoji: 'significantly_better',
       expectedEmojiColor: 'rgb(0, 128, 0)',
@@ -171,12 +171,12 @@
 
     checkScalarSpan(this, -1, countBIBD, '-1', {
       expectedColor: 'rgb(255, 0, 0)',
-      significance: tr.b.Statistics.Significance.DONT_CARE,
+      significance: tr.b.math.Statistics.Significance.DONT_CARE,
       expectedEmoji: ''
     });
 
     checkScalarSpan(this, -1, countBIBD, '-1', {
-      significance: tr.b.Statistics.Significance.INSIGNIFICANT,
+      significance: tr.b.math.Statistics.Significance.INSIGNIFICANT,
       expectedColor: 'rgb(255, 0, 0)',
       expectedEmoji: 'insignificant',
       expectedEmojiColor: 'rgb(0, 0, 0)',
@@ -184,7 +184,7 @@
     });
 
     checkScalarSpan(this, -1, countBIBD, '-1', {
-      significance: tr.b.Statistics.Significance.SIGNIFICANT,
+      significance: tr.b.math.Statistics.Significance.SIGNIFICANT,
       expectedColor: 'rgb(255, 0, 0)',
       expectedEmoji: 'significantly_worse',
       expectedEmojiColor: 'rgb(255, 0, 0)',
@@ -193,37 +193,37 @@
 
     checkScalarSpan(this, 1, countD, '+1', {
       expectedColor: 'rgb(0, 0, 0)',
-      significance: tr.b.Statistics.Significance.DONT_CARE,
+      significance: tr.b.math.Statistics.Significance.DONT_CARE,
       expectedEmoji: ''
     });
 
     checkScalarSpan(this, 1, countD, '+1', {
       expectedColor: 'rgb(0, 0, 0)',
-      significance: tr.b.Statistics.Significance.INSIGNIFICANT,
+      significance: tr.b.math.Statistics.Significance.INSIGNIFICANT,
       expectedEmoji: ''
     });
 
     checkScalarSpan(this, 1, countD, '+1', {
       expectedColor: 'rgb(0, 0, 0)',
-      significance: tr.b.Statistics.Significance.SIGNIFICANT,
+      significance: tr.b.math.Statistics.Significance.SIGNIFICANT,
       expectedEmoji: ''
     });
 
     checkScalarSpan(this, -1, countD, '-1', {
       expectedColor: 'rgb(0, 0, 0)',
-      significance: tr.b.Statistics.Significance.DONT_CARE,
+      significance: tr.b.math.Statistics.Significance.DONT_CARE,
       expectedEmoji: ''
     });
 
     checkScalarSpan(this, -1, countD, '-1', {
       expectedColor: 'rgb(0, 0, 0)',
-      significance: tr.b.Statistics.Significance.INSIGNIFICANT,
+      significance: tr.b.math.Statistics.Significance.INSIGNIFICANT,
       expectedEmoji: ''
     });
 
     checkScalarSpan(this, -1, countD, '-1', {
       expectedColor: 'rgb(0, 0, 0)',
-      significance: tr.b.Statistics.Significance.SIGNIFICANT,
+      significance: tr.b.math.Statistics.Significance.SIGNIFICANT,
       expectedEmoji: ''
     });
   });
@@ -339,7 +339,7 @@
     // Unit and sparkline set via config.
     span = tr.v.ui.createScalarSpan(1.62, {
       unit: Unit.byName.timeStampInMs,
-      customContextRange: tr.b.Range.fromExplicitRange(0, 3.24)
+      customContextRange: tr.b.math.Range.fromExplicitRange(0, 3.24)
     });
     assert.strictEqual(Polymer.dom(span.$.content).textContent, '1.620 ms');
     assert.strictEqual(span.ownerDocument, document);
@@ -347,7 +347,7 @@
     assert.strictEqual(span.value, 1.62);
     assert.strictEqual(span.unit, Unit.byName.timeStampInMs);
     assert.isUndefined(span.context);
-    assert.isTrue(tr.b.Range.fromExplicitRange(0, 3.24).equals(
+    assert.isTrue(tr.b.math.Range.fromExplicitRange(0, 3.24).equals(
         span.customContextRange));
     assert.isUndefined(span.warning);
     assert.isFalse(span.leftAlign);
@@ -387,7 +387,7 @@
   test('instantiate_withCustomContextRange', function() {
     let span = document.createElement('tr-v-ui-scalar-span');
     span.value = new Scalar(Unit.byName.unitlessNumber, 0.99);
-    span.customContextRange = tr.b.Range.fromExplicitRange(0, 3);
+    span.customContextRange = tr.b.math.Range.fromExplicitRange(0, 3);
     this.addHTMLOutput(span);
   });
 
@@ -419,19 +419,19 @@
     let spanC = document.createElement('tr-v-ui-scalar-span');
     spanC.setValueAndUnit(
         400, Unit.byName.timeDurationInMsDelta_smallerIsBetter);
-    spanC.significance = tr.b.Statistics.Significance.SIGNIFICANT;
+    spanC.significance = tr.b.math.Statistics.Significance.SIGNIFICANT;
     checkSignificance(spanC, 'significantly_worse');
 
     let spanD = document.createElement('tr-v-ui-scalar-span');
     spanD.setValueAndUnit(
         400, Unit.byName.timeDurationInMsDelta_biggerIsBetter);
-    spanD.significance = tr.b.Statistics.Significance.SIGNIFICANT;
+    spanD.significance = tr.b.math.Statistics.Significance.SIGNIFICANT;
     checkSignificance(spanD, 'significantly_better');
 
     let spanE = document.createElement('tr-v-ui-scalar-span');
     spanE.setValueAndUnit(
         400, Unit.byName.timeDurationInMsDelta_smallerIsBetter);
-    spanE.significance = tr.b.Statistics.Significance.INSIGNIFICANT;
+    spanE.significance = tr.b.math.Statistics.Significance.INSIGNIFICANT;
     checkSignificance(spanE, 'insignificant');
 
     let overall = document.createElement('div');
@@ -533,12 +533,12 @@
     checkSparkline(span2, {display: 'none'});
     let span3 = tr.v.ui.createScalarSpan(0, {
       unit: Unit.byName.timeStampInMs,
-      customContextRange: new tr.b.Range()  // Empty range.
+      customContextRange: new tr.b.math.Range()  // Empty range.
     });
     Polymer.dom(div).appendChild(span3);
     checkSparkline(span3, {display: 'none'});
 
-    let range = tr.b.Range.fromExplicitRange(-15, 15);
+    let range = tr.b.math.Range.fromExplicitRange(-15, 15);
 
     // Values inside custom context range.
     let span4 = tr.v.ui.createScalarSpan(-15, {
@@ -662,7 +662,7 @@
     checkSparkline(s3, {left: 0, width: 76, classList: ['positive']});
     checkSparkline(s4, {left: 0, width: 101, classList: ['positive']});
 
-    s1.customContextRange = tr.b.Range.fromExplicitRange(0, 150);
+    s1.customContextRange = tr.b.math.Range.fromExplicitRange(0, 150);
     checkSparkline(s1, {left: 0, width: 34.33, classList: ['positive']});
     checkSparkline(s2, {left: 0, width: 41, classList: ['positive']});
     checkSparkline(s3, {left: 0, width: 76, classList: ['positive']});
@@ -708,7 +708,7 @@
     checkSparkline(s4, {display: 'none'});
     checkSparkline(s1, {display: 'none'});
 
-    s1.customContextRange = tr.b.Range.fromExplicitRange(0, 100);
+    s1.customContextRange = tr.b.math.Range.fromExplicitRange(0, 100);
     checkSparkline(s2, {left: 0, width: 101, classList: ['positive']});
     checkSparkline(s3, {left: 0, width: 101, classList: ['positive']});
     checkSparkline(s4, {display: 'none'});
@@ -909,15 +909,15 @@
 
     let span = tr.v.ui.createScalarSpan(10, {
       unit: Unit.byName.energyInJoulesDelta_smallerIsBetter,
-      significance: tr.b.Statistics.Significance.SIGNIFICANT,
-      customContextRange: tr.b.Range.fromExplicitRange(-20, 20)
+      significance: tr.b.math.Statistics.Significance.SIGNIFICANT,
+      customContextRange: tr.b.math.Range.fromExplicitRange(-20, 20)
     });
     Polymer.dom(div).appendChild(span);
 
     assert.sameMembers(tr.b.asArray(span.$.content.classList), ['worse']);
     checkSignificance(span, 'significantly_worse');
 
-    span.significance = tr.b.Statistics.Significance.DONT_CARE;
+    span.significance = tr.b.math.Statistics.Significance.DONT_CARE;
     assert.sameMembers(tr.b.asArray(span.$.sparkline.classList),
         ['positive', 'worse']);
     assert.sameMembers(tr.b.asArray(span.$.content.classList), ['worse']);
@@ -944,7 +944,7 @@
     assert.sameMembers(tr.b.asArray(span.$.content.classList), ['better']);
     checkSignificance(span, '');
 
-    span.significance = tr.b.Statistics.Significance.INSIGNIFICANT;
+    span.significance = tr.b.math.Statistics.Significance.INSIGNIFICANT;
     assert.sameMembers(tr.b.asArray(span.$.sparkline.classList),
         ['positive', 'better']);
     assert.sameMembers(tr.b.asArray(span.$.content.classList), ['better']);
@@ -999,19 +999,19 @@
 
     Polymer.dom(div).appendChild(tr.v.ui.createScalarSpan(-1, {
       unit: Unit.byName.powerInWattsDelta,
-      customContextRange: tr.b.Range.fromExplicitRange(-100, 100)
+      customContextRange: tr.b.math.Range.fromExplicitRange(-100, 100)
     }));
     Polymer.dom(div).appendChild(tr.v.ui.createScalarSpan(100, {
       unit: Unit.byName.powerInWattsDelta,
-      customContextRange: tr.b.Range.fromExplicitRange(-100, 100)
+      customContextRange: tr.b.math.Range.fromExplicitRange(-100, 100)
     }));
     Polymer.dom(div).appendChild(tr.v.ui.createScalarSpan(80, {
       unit: Unit.byName.powerInWattsDelta,
-      customContextRange: tr.b.Range.fromExplicitRange(-100, 100)
+      customContextRange: tr.b.math.Range.fromExplicitRange(-100, 100)
     }));
     Polymer.dom(div).appendChild(tr.v.ui.createScalarSpan(60, {
       unit: Unit.byName.powerInWattsDelta,
-      customContextRange: tr.b.Range.fromExplicitRange(-100, 100)
+      customContextRange: tr.b.math.Range.fromExplicitRange(-100, 100)
     }));
   });