(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.concaveman = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o maxDist) continue; // skip the node if it's farther than we ever need queue.push({ node: child, dist: dist }); } while (queue.length && !queue.peek().node.children) { var item = queue.pop(); var p = item.node; // skip all points that are as close to adjacent edges (a,b) and (c,d), // and points that would introduce self-intersections when connected var d0 = sqSegDist(p, a, b); var d1 = sqSegDist(p, c, d); if (item.dist < d0 && item.dist < d1 && noIntersections(b, p, segTree) && noIntersections(c, p, segTree)) return p; } node = queue.pop(); if (node) node = node.node; } return null; } function compareDist(a, b) { return a.dist - b.dist; } // square distance from a segment bounding box to the given one function sqSegBoxDist(a, b, bbox) { if (inside(a, bbox) || inside(b, bbox)) return 0; var d1 = sqSegSegDist(a[0], a[1], b[0], b[1], bbox[0], bbox[1], bbox[2], bbox[1]); if (d1 === 0) return 0; var d2 = sqSegSegDist(a[0], a[1], b[0], b[1], bbox[0], bbox[1], bbox[0], bbox[3]); if (d2 === 0) return 0; var d3 = sqSegSegDist(a[0], a[1], b[0], b[1], bbox[2], bbox[1], bbox[2], bbox[3]); if (d3 === 0) return 0; var d4 = sqSegSegDist(a[0], a[1], b[0], b[1], bbox[0], bbox[3], bbox[2], bbox[3]); if (d4 === 0) return 0; return Math.min(d1, d2, d3, d4); } function inside(a, bbox) { return a[0] >= bbox[0] && a[0] <= bbox[2] && a[1] >= bbox[1] && a[1] <= bbox[3]; } // check if the edge (a,b) doesn't intersect any other edges function noIntersections(a, b, segTree) { var minX = Math.min(a[0], b[0]); var minY = Math.min(a[1], b[1]); var maxX = Math.max(a[0], b[0]); var maxY = Math.max(a[1], b[1]); var edges = segTree.search([minX, minY, maxX, maxY]); for (var i = 0; i < edges.length; i++) { if (intersects(edges[i].p, edges[i].next.p, a, b)) return false; } return true; } // check if the edges (p1,q1) and (p2,q2) intersect function intersects(p1, q1, p2, q2) { return p1 !== q2 && q1 !== p2 && orient(p1, q1, p2) > 0 !== orient(p1, q1, q2) > 0 && orient(p2, q2, p1) > 0 !== orient(p2, q2, q1) > 0; } // update the bounding box of a node's edge function updateBBox(node) { var p1 = node.p; var p2 = node.next.p; node.minX = Math.min(p1[0], p2[0]); node.minY = Math.min(p1[1], p2[1]); node.maxX = Math.max(p1[0], p2[0]); node.maxY = Math.max(p1[1], p2[1]); return node; } // speed up convex hull by filtering out points inside quadrilateral formed by 4 extreme points function fastConvexHull(points) { var left = points[0]; var top = points[0]; var right = points[0]; var bottom = points[0]; // find the leftmost, rightmost, topmost and bottommost points for (var i = 0; i < points.length; i++) { var p = points[i]; if (p[0] < left[0]) left = p; if (p[0] > right[0]) right = p; if (p[1] < top[1]) top = p; if (p[1] > bottom[1]) bottom = p; } // filter out points that are inside the resulting quadrilateral var cull = [left, top, right, bottom]; var filtered = cull.slice(); for (i = 0; i < points.length; i++) { if (!pointInPolygon(points[i], cull)) filtered.push(points[i]); } // get convex hull around the filtered points var indices = convexHull(filtered); // return the hull as array of points (rather than indices) var hull = []; for (i = 0; i < indices.length; i++) hull.push(filtered[indices[i]]); return hull; } // create a new node in a doubly linked list function insertNode(p, prev) { var node = { p: p, prev: null, next: null, minX: 0, minY: 0, maxX: 0, maxY: 0 }; if (!prev) { node.prev = node; node.next = node; } else { node.next = prev.next; node.prev = prev; prev.next.prev = node; prev.next = node; } return node; } // square distance between 2 points function getSqDist(p1, p2) { var dx = p1[0] - p2[0], dy = p1[1] - p2[1]; return dx * dx + dy * dy; } // square distance from a point to a segment function sqSegDist(p, p1, p2) { var x = p1[0], y = p1[1], dx = p2[0] - x, dy = p2[1] - y; if (dx !== 0 || dy !== 0) { var t = ((p[0] - x) * dx + (p[1] - y) * dy) / (dx * dx + dy * dy); if (t > 1) { x = p2[0]; y = p2[1]; } else if (t > 0) { x += dx * t; y += dy * t; } } dx = p[0] - x; dy = p[1] - y; return dx * dx + dy * dy; } // segment to segment distance, ported from http://geomalgorithms.com/a07-_distance.html by Dan Sunday function sqSegSegDist(x0, y0, x1, y1, x2, y2, x3, y3) { var ux = x1 - x0; var uy = y1 - y0; var vx = x3 - x2; var vy = y3 - y2; var wx = x0 - x2; var wy = y0 - y2; var a = ux * ux + uy * uy; var b = ux * vx + uy * vy; var c = vx * vx + vy * vy; var d = ux * wx + uy * wy; var e = vx * wx + vy * wy; var D = a * c - b * b; var sc, sN, tc, tN; var sD = D; var tD = D; if (D === 0) { sN = 0; sD = 1; tN = e; tD = c; } else { sN = b * e - c * d; tN = a * e - b * d; if (sN < 0) { sN = 0; tN = e; tD = c; } else if (sN > sD) { sN = sD; tN = e + b; tD = c; } } if (tN < 0.0) { tN = 0.0; if (-d < 0.0) sN = 0.0; else if (-d > a) sN = sD; else { sN = -d; sD = a; } } else if (tN > tD) { tN = tD; if ((-d + b) < 0.0) sN = 0; else if (-d + b > a) sN = sD; else { sN = -d + b; sD = a; } } sc = sN === 0 ? 0 : sN / sD; tc = tN === 0 ? 0 : tN / tD; var cx = (1 - sc) * x0 + sc * x1; var cy = (1 - sc) * y0 + sc * y1; var cx2 = (1 - tc) * x2 + tc * x3; var cy2 = (1 - tc) * y2 + tc * y3; var dx = cx2 - cx; var dy = cy2 - cy; return dx * dx + dy * dy; } },{"monotone-convex-hull-2d":2,"point-in-polygon":3,"rbush":4,"robust-orientation":5,"tinyqueue":9}],2:[function(require,module,exports){ 'use strict' module.exports = monotoneConvexHull2D var orient = require('robust-orientation')[3] function monotoneConvexHull2D(points) { var n = points.length if(n < 3) { var result = new Array(n) for(var i=0; i 1 && orient( points[lower[m-2]], points[lower[m-1]], p) <= 0) { m -= 1 lower.pop() } lower.push(idx) //Insert into upper list m = upper.length while(m > 1 && orient( points[upper[m-2]], points[upper[m-1]], p) >= 0) { m -= 1 upper.pop() } upper.push(idx) } //Merge lists together var result = new Array(upper.length + lower.length - 2) var ptr = 0 for(var i=0, nl=lower.length; i0; --j) { result[ptr++] = upper[j] } //Return result return result } },{"robust-orientation":5}],3:[function(require,module,exports){ module.exports = function (point, vs) { // ray-casting algorithm based on // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html var x = point[0], y = point[1]; var inside = false; for (var i = 0, j = vs.length - 1; i < vs.length; j = i++) { var xi = vs[i][0], yi = vs[i][1]; var xj = vs[j][0], yj = vs[j][1]; var intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi); if (intersect) inside = !inside; } return inside; }; },{}],4:[function(require,module,exports){ /* (c) 2015, Vladimir Agafonkin RBush, a JavaScript library for high-performance 2D spatial indexing of points and rectangles. https://github.com/mourner/rbush */ (function () { 'use strict'; function rbush(maxEntries, format) { // jshint newcap: false, validthis: true if (!(this instanceof rbush)) return new rbush(maxEntries, format); // max entries in a node is 9 by default; min node fill is 40% for best performance this._maxEntries = Math.max(4, maxEntries || 9); this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4)); if (format) { this._initFormat(format); } this.clear(); } rbush.prototype = { all: function () { return this._all(this.data, []); }, search: function (bbox) { var node = this.data, result = [], toBBox = this.toBBox; if (!intersects(bbox, node.bbox)) return result; var nodesToSearch = [], i, len, child, childBBox; while (node) { for (i = 0, len = node.children.length; i < len; i++) { child = node.children[i]; childBBox = node.leaf ? toBBox(child) : child.bbox; if (intersects(bbox, childBBox)) { if (node.leaf) result.push(child); else if (contains(bbox, childBBox)) this._all(child, result); else nodesToSearch.push(child); } } node = nodesToSearch.pop(); } return result; }, collides: function (bbox) { var node = this.data, toBBox = this.toBBox; if (!intersects(bbox, node.bbox)) return false; var nodesToSearch = [], i, len, child, childBBox; while (node) { for (i = 0, len = node.children.length; i < len; i++) { child = node.children[i]; childBBox = node.leaf ? toBBox(child) : child.bbox; if (intersects(bbox, childBBox)) { if (node.leaf || contains(bbox, childBBox)) return true; nodesToSearch.push(child); } } node = nodesToSearch.pop(); } return false; }, load: function (data) { if (!(data && data.length)) return this; if (data.length < this._minEntries) { for (var i = 0, len = data.length; i < len; i++) { this.insert(data[i]); } return this; } // recursively build the tree with the given data from stratch using OMT algorithm var node = this._build(data.slice(), 0, data.length - 1, 0); if (!this.data.children.length) { // save as is if tree is empty this.data = node; } else if (this.data.height === node.height) { // split root if trees have the same height this._splitRoot(this.data, node); } else { if (this.data.height < node.height) { // swap trees if inserted one is bigger var tmpNode = this.data; this.data = node; node = tmpNode; } // insert the small tree into the large tree at appropriate level this._insert(node, this.data.height - node.height - 1, true); } return this; }, insert: function (item) { if (item) this._insert(item, this.data.height - 1); return this; }, clear: function () { this.data = { children: [], height: 1, bbox: empty(), leaf: true }; return this; }, remove: function (item) { if (!item) return this; var node = this.data, bbox = this.toBBox(item), path = [], indexes = [], i, parent, index, goingUp; // depth-first iterative tree traversal while (node || path.length) { if (!node) { // go up node = path.pop(); parent = path[path.length - 1]; i = indexes.pop(); goingUp = true; } if (node.leaf) { // check current node index = node.children.indexOf(item); if (index !== -1) { // item found, remove the item and condense tree upwards node.children.splice(index, 1); path.push(node); this._condense(path); return this; } } if (!goingUp && !node.leaf && contains(node.bbox, bbox)) { // go down path.push(node); indexes.push(i); i = 0; parent = node; node = node.children[0]; } else if (parent) { // go right i++; node = parent.children[i]; goingUp = false; } else node = null; // nothing found } return this; }, toBBox: function (item) { return item; }, compareMinX: function (a, b) { return a[0] - b[0]; }, compareMinY: function (a, b) { return a[1] - b[1]; }, toJSON: function () { return this.data; }, fromJSON: function (data) { this.data = data; return this; }, _all: function (node, result) { var nodesToSearch = []; while (node) { if (node.leaf) result.push.apply(result, node.children); else nodesToSearch.push.apply(nodesToSearch, node.children); node = nodesToSearch.pop(); } return result; }, _build: function (items, left, right, height) { var N = right - left + 1, M = this._maxEntries, node; if (N <= M) { // reached leaf level; return leaf node = { children: items.slice(left, right + 1), height: 1, bbox: null, leaf: true }; calcBBox(node, this.toBBox); return node; } if (!height) { // target height of the bulk-loaded tree height = Math.ceil(Math.log(N) / Math.log(M)); // target number of root entries to maximize storage utilization M = Math.ceil(N / Math.pow(M, height - 1)); } node = { children: [], height: height, bbox: null, leaf: false }; // split the items into M mostly square tiles var N2 = Math.ceil(N / M), N1 = N2 * Math.ceil(Math.sqrt(M)), i, j, right2, right3; multiSelect(items, left, right, N1, this.compareMinX); for (i = left; i <= right; i += N1) { right2 = Math.min(i + N1 - 1, right); multiSelect(items, i, right2, N2, this.compareMinY); for (j = i; j <= right2; j += N2) { right3 = Math.min(j + N2 - 1, right2); // pack each entry recursively node.children.push(this._build(items, j, right3, height - 1)); } } calcBBox(node, this.toBBox); return node; }, _chooseSubtree: function (bbox, node, level, path) { var i, len, child, targetNode, area, enlargement, minArea, minEnlargement; while (true) { path.push(node); if (node.leaf || path.length - 1 === level) break; minArea = minEnlargement = Infinity; for (i = 0, len = node.children.length; i < len; i++) { child = node.children[i]; area = bboxArea(child.bbox); enlargement = enlargedArea(bbox, child.bbox) - area; // choose entry with the least area enlargement if (enlargement < minEnlargement) { minEnlargement = enlargement; minArea = area < minArea ? area : minArea; targetNode = child; } else if (enlargement === minEnlargement) { // otherwise choose one with the smallest area if (area < minArea) { minArea = area; targetNode = child; } } } node = targetNode; } return node; }, _insert: function (item, level, isNode) { var toBBox = this.toBBox, bbox = isNode ? item.bbox : toBBox(item), insertPath = []; // find the best node for accommodating the item, saving all nodes along the path too var node = this._chooseSubtree(bbox, this.data, level, insertPath); // put the item into the node node.children.push(item); extend(node.bbox, bbox); // split on node overflow; propagate upwards if necessary while (level >= 0) { if (insertPath[level].children.length > this._maxEntries) { this._split(insertPath, level); level--; } else break; } // adjust bboxes along the insertion path this._adjustParentBBoxes(bbox, insertPath, level); }, // split overflowed node into two _split: function (insertPath, level) { var node = insertPath[level], M = node.children.length, m = this._minEntries; this._chooseSplitAxis(node, m, M); var splitIndex = this._chooseSplitIndex(node, m, M); var newNode = { children: node.children.splice(splitIndex, node.children.length - splitIndex), height: node.height, bbox: null, leaf: false }; if (node.leaf) newNode.leaf = true; calcBBox(node, this.toBBox); calcBBox(newNode, this.toBBox); if (level) insertPath[level - 1].children.push(newNode); else this._splitRoot(node, newNode); }, _splitRoot: function (node, newNode) { // split root node this.data = { children: [node, newNode], height: node.height + 1, bbox: null, leaf: false }; calcBBox(this.data, this.toBBox); }, _chooseSplitIndex: function (node, m, M) { var i, bbox1, bbox2, overlap, area, minOverlap, minArea, index; minOverlap = minArea = Infinity; for (i = m; i <= M - m; i++) { bbox1 = distBBox(node, 0, i, this.toBBox); bbox2 = distBBox(node, i, M, this.toBBox); overlap = intersectionArea(bbox1, bbox2); area = bboxArea(bbox1) + bboxArea(bbox2); // choose distribution with minimum overlap if (overlap < minOverlap) { minOverlap = overlap; index = i; minArea = area < minArea ? area : minArea; } else if (overlap === minOverlap) { // otherwise choose distribution with minimum area if (area < minArea) { minArea = area; index = i; } } } return index; }, // sorts node children by the best axis for split _chooseSplitAxis: function (node, m, M) { var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX, compareMinY = node.leaf ? this.compareMinY : compareNodeMinY, xMargin = this._allDistMargin(node, m, M, compareMinX), yMargin = this._allDistMargin(node, m, M, compareMinY); // if total distributions margin value is minimal for x, sort by minX, // otherwise it's already sorted by minY if (xMargin < yMargin) node.children.sort(compareMinX); }, // total margin of all possible split distributions where each node is at least m full _allDistMargin: function (node, m, M, compare) { node.children.sort(compare); var toBBox = this.toBBox, leftBBox = distBBox(node, 0, m, toBBox), rightBBox = distBBox(node, M - m, M, toBBox), margin = bboxMargin(leftBBox) + bboxMargin(rightBBox), i, child; for (i = m; i < M - m; i++) { child = node.children[i]; extend(leftBBox, node.leaf ? toBBox(child) : child.bbox); margin += bboxMargin(leftBBox); } for (i = M - m - 1; i >= m; i--) { child = node.children[i]; extend(rightBBox, node.leaf ? toBBox(child) : child.bbox); margin += bboxMargin(rightBBox); } return margin; }, _adjustParentBBoxes: function (bbox, path, level) { // adjust bboxes along the given tree path for (var i = level; i >= 0; i--) { extend(path[i].bbox, bbox); } }, _condense: function (path) { // go through the path, removing empty nodes and updating bboxes for (var i = path.length - 1, siblings; i >= 0; i--) { if (path[i].children.length === 0) { if (i > 0) { siblings = path[i - 1].children; siblings.splice(siblings.indexOf(path[i]), 1); } else this.clear(); } else calcBBox(path[i], this.toBBox); } }, _initFormat: function (format) { // data format (minX, minY, maxX, maxY accessors) // uses eval-type function compilation instead of just accepting a toBBox function // because the algorithms are very sensitive to sorting functions performance, // so they should be dead simple and without inner calls // jshint evil: true var compareArr = ['return a', ' - b', ';']; this.compareMinX = new Function('a', 'b', compareArr.join(format[0])); this.compareMinY = new Function('a', 'b', compareArr.join(format[1])); this.toBBox = new Function('a', 'return [a' + format.join(', a') + '];'); } }; // calculate node's bbox from bboxes of its children function calcBBox(node, toBBox) { node.bbox = distBBox(node, 0, node.children.length, toBBox); } // min bounding rectangle of node children from k to p-1 function distBBox(node, k, p, toBBox) { var bbox = empty(); for (var i = k, child; i < p; i++) { child = node.children[i]; extend(bbox, node.leaf ? toBBox(child) : child.bbox); } return bbox; } function empty() { return [Infinity, Infinity, -Infinity, -Infinity]; } function extend(a, b) { a[0] = Math.min(a[0], b[0]); a[1] = Math.min(a[1], b[1]); a[2] = Math.max(a[2], b[2]); a[3] = Math.max(a[3], b[3]); return a; } function compareNodeMinX(a, b) { return a.bbox[0] - b.bbox[0]; } function compareNodeMinY(a, b) { return a.bbox[1] - b.bbox[1]; } function bboxArea(a) { return (a[2] - a[0]) * (a[3] - a[1]); } function bboxMargin(a) { return (a[2] - a[0]) + (a[3] - a[1]); } function enlargedArea(a, b) { return (Math.max(b[2], a[2]) - Math.min(b[0], a[0])) * (Math.max(b[3], a[3]) - Math.min(b[1], a[1])); } function intersectionArea(a, b) { var minX = Math.max(a[0], b[0]), minY = Math.max(a[1], b[1]), maxX = Math.min(a[2], b[2]), maxY = Math.min(a[3], b[3]); return Math.max(0, maxX - minX) * Math.max(0, maxY - minY); } function contains(a, b) { return a[0] <= b[0] && a[1] <= b[1] && b[2] <= a[2] && b[3] <= a[3]; } function intersects(a, b) { return b[0] <= a[2] && b[1] <= a[3] && b[2] >= a[0] && b[3] >= a[1]; } // sort an array so that items come in groups of n unsorted items, with groups sorted between each other; // combines selection algorithm with binary divide & conquer approach function multiSelect(arr, left, right, n, compare) { var stack = [left, right], mid; while (stack.length) { right = stack.pop(); left = stack.pop(); if (right - left <= n) continue; mid = left + Math.ceil((right - left) / n / 2) * n; select(arr, left, right, mid, compare); stack.push(left, mid, mid, right); } } // Floyd-Rivest selection algorithm: // sort an array between left and right (inclusive) so that the smallest k elements come first (unordered) function select(arr, left, right, k, compare) { var n, i, z, s, sd, newLeft, newRight, t, j; while (right > left) { if (right - left > 600) { n = right - left + 1; i = k - left + 1; z = Math.log(n); s = 0.5 * Math.exp(2 * z / 3); sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (i - n / 2 < 0 ? -1 : 1); newLeft = Math.max(left, Math.floor(k - i * s / n + sd)); newRight = Math.min(right, Math.floor(k + (n - i) * s / n + sd)); select(arr, newLeft, newRight, k, compare); } t = arr[k]; i = left; j = right; swap(arr, left, k); if (compare(arr[right], t) > 0) swap(arr, left, right); while (i < j) { swap(arr, i, j); i++; j--; while (compare(arr[i], t) < 0) i++; while (compare(arr[j], t) > 0) j--; } if (compare(arr[left], t) === 0) swap(arr, left, j); else { j++; swap(arr, j, right); } if (j <= k) left = j + 1; if (k <= j) right = j - 1; } } function swap(arr, i, j) { var tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp; } // export as AMD/CommonJS module or global variable if (typeof define === 'function' && define.amd) define('rbush', function () { return rbush; }); else if (typeof module !== 'undefined') module.exports = rbush; else if (typeof self !== 'undefined') self.rbush = rbush; else window.rbush = rbush; })(); },{}],5:[function(require,module,exports){ "use strict" var twoProduct = require("two-product") var robustSum = require("robust-sum") var robustScale = require("robust-scale") var robustSubtract = require("robust-subtract") var NUM_EXPAND = 5 var EPSILON = 1.1102230246251565e-16 var ERRBOUND3 = (3.0 + 16.0 * EPSILON) * EPSILON var ERRBOUND4 = (7.0 + 56.0 * EPSILON) * EPSILON function cofactor(m, c) { var result = new Array(m.length-1) for(var i=1; i>1 return ["sum(", generateSum(expr.slice(0, m)), ",", generateSum(expr.slice(m)), ")"].join("") } } function determinant(m) { if(m.length === 2) { return [["sum(prod(", m[0][0], ",", m[1][1], "),prod(-", m[0][1], ",", m[1][0], "))"].join("")] } else { var expr = [] for(var i=0; i 0) { if(r <= 0) { return det } else { s = l + r } } else if(l < 0) { if(r >= 0) { return det } else { s = -(l + r) } } else { return det } var tol = ERRBOUND3 * s if(det >= tol || det <= -tol) { return det } return orientation3Exact(a, b, c) }, function orientation4(a,b,c,d) { var adx = a[0] - d[0] var bdx = b[0] - d[0] var cdx = c[0] - d[0] var ady = a[1] - d[1] var bdy = b[1] - d[1] var cdy = c[1] - d[1] var adz = a[2] - d[2] var bdz = b[2] - d[2] var cdz = c[2] - d[2] var bdxcdy = bdx * cdy var cdxbdy = cdx * bdy var cdxady = cdx * ady var adxcdy = adx * cdy var adxbdy = adx * bdy var bdxady = bdx * ady var det = adz * (bdxcdy - cdxbdy) + bdz * (cdxady - adxcdy) + cdz * (adxbdy - bdxady) var permanent = (Math.abs(bdxcdy) + Math.abs(cdxbdy)) * Math.abs(adz) + (Math.abs(cdxady) + Math.abs(adxcdy)) * Math.abs(bdz) + (Math.abs(adxbdy) + Math.abs(bdxady)) * Math.abs(cdz) var tol = ERRBOUND4 * permanent if ((det > tol) || (-det > tol)) { return det } return orientation4Exact(a,b,c,d) } ] function slowOrient(args) { var proc = CACHED[args.length] if(!proc) { proc = CACHED[args.length] = orientation(args.length) } return proc.apply(undefined, args) } function generateOrientationProc() { while(CACHED.length <= NUM_EXPAND) { CACHED.push(orientation(CACHED.length)) } var args = [] var procArgs = ["slow"] for(var i=0; i<=NUM_EXPAND; ++i) { args.push("a" + i) procArgs.push("o" + i) } var code = [ "function getOrientation(", args.join(), "){switch(arguments.length){case 0:case 1:return 0;" ] for(var i=2; i<=NUM_EXPAND; ++i) { code.push("case ", i, ":return o", i, "(", args.slice(0, i).join(), ");") } code.push("}var s=new Array(arguments.length);for(var i=0;i= nf)) { a = ei eptr += 1 if(eptr < ne) { ei = e[eptr] ea = abs(ei) } } else { a = fi fptr += 1 if(fptr < nf) { fi = -f[fptr] fa = abs(fi) } } var x = a + b var bv = x - a var y = b - bv var q0 = y var q1 = x var _x, _bv, _av, _br, _ar while(eptr < ne && fptr < nf) { if(ea < fa) { a = ei eptr += 1 if(eptr < ne) { ei = e[eptr] ea = abs(ei) } } else { a = fi fptr += 1 if(fptr < nf) { fi = -f[fptr] fa = abs(fi) } } b = q0 x = a + b bv = x - a y = b - bv if(y) { g[count++] = y } _x = q1 + x _bv = _x - q1 _av = _x - _bv _br = x - _bv _ar = q1 - _av q0 = _ar + _br q1 = _x } while(eptr < ne) { a = ei b = q0 x = a + b bv = x - a y = b - bv if(y) { g[count++] = y } _x = q1 + x _bv = _x - q1 _av = _x - _bv _br = x - _bv _ar = q1 - _av q0 = _ar + _br q1 = _x eptr += 1 if(eptr < ne) { ei = e[eptr] } } while(fptr < nf) { a = fi b = q0 x = a + b bv = x - a y = b - bv if(y) { g[count++] = y } _x = q1 + x _bv = _x - q1 _av = _x - _bv _br = x - _bv _ar = q1 - _av q0 = _ar + _br q1 = _x fptr += 1 if(fptr < nf) { fi = -f[fptr] } } if(q0) { g[count++] = q0 } if(q1) { g[count++] = q1 } if(!count) { g[count++] = 0.0 } g.length = count return g } },{}],8:[function(require,module,exports){ "use strict" module.exports = linearExpansionSum //Easy case: Add two scalars function scalarScalar(a, b) { var x = a + b var bv = x - a var av = x - bv var br = b - bv var ar = a - av var y = ar + br if(y) { return [y, x] } return [x] } function linearExpansionSum(e, f) { var ne = e.length|0 var nf = f.length|0 if(ne === 1 && nf === 1) { return scalarScalar(e[0], f[0]) } var n = ne + nf var g = new Array(n) var count = 0 var eptr = 0 var fptr = 0 var abs = Math.abs var ei = e[eptr] var ea = abs(ei) var fi = f[fptr] var fa = abs(fi) var a, b if(ea < fa) { b = ei eptr += 1 if(eptr < ne) { ei = e[eptr] ea = abs(ei) } } else { b = fi fptr += 1 if(fptr < nf) { fi = f[fptr] fa = abs(fi) } } if((eptr < ne && ea < fa) || (fptr >= nf)) { a = ei eptr += 1 if(eptr < ne) { ei = e[eptr] ea = abs(ei) } } else { a = fi fptr += 1 if(fptr < nf) { fi = f[fptr] fa = abs(fi) } } var x = a + b var bv = x - a var y = b - bv var q0 = y var q1 = x var _x, _bv, _av, _br, _ar while(eptr < ne && fptr < nf) { if(ea < fa) { a = ei eptr += 1 if(eptr < ne) { ei = e[eptr] ea = abs(ei) } } else { a = fi fptr += 1 if(fptr < nf) { fi = f[fptr] fa = abs(fi) } } b = q0 x = a + b bv = x - a y = b - bv if(y) { g[count++] = y } _x = q1 + x _bv = _x - q1 _av = _x - _bv _br = x - _bv _ar = q1 - _av q0 = _ar + _br q1 = _x } while(eptr < ne) { a = ei b = q0 x = a + b bv = x - a y = b - bv if(y) { g[count++] = y } _x = q1 + x _bv = _x - q1 _av = _x - _bv _br = x - _bv _ar = q1 - _av q0 = _ar + _br q1 = _x eptr += 1 if(eptr < ne) { ei = e[eptr] } } while(fptr < nf) { a = fi b = q0 x = a + b bv = x - a y = b - bv if(y) { g[count++] = y } _x = q1 + x _bv = _x - q1 _av = _x - _bv _br = x - _bv _ar = q1 - _av q0 = _ar + _br q1 = _x fptr += 1 if(fptr < nf) { fi = f[fptr] } } if(q0) { g[count++] = q0 } if(q1) { g[count++] = q1 } if(!count) { g[count++] = 0.0 } g.length = count return g } },{}],9:[function(require,module,exports){ 'use strict'; module.exports = TinyQueue; function TinyQueue(data, compare) { if (!(this instanceof TinyQueue)) return new TinyQueue(data, compare); this.data = data || []; this.length = this.data.length; this.compare = compare || defaultCompare; if (data) for (var i = Math.floor(this.length / 2); i >= 0; i--) this._down(i); } function defaultCompare(a, b) { return a < b ? -1 : a > b ? 1 : 0; } TinyQueue.prototype = { push: function (item) { this.data.push(item); this.length++; this._up(this.length - 1); }, pop: function () { var top = this.data[0]; this.data[0] = this.data[this.length - 1]; this.length--; this.data.pop(); this._down(0); return top; }, peek: function () { return this.data[0]; }, _up: function (pos) { var data = this.data, compare = this.compare; while (pos > 0) { var parent = Math.floor((pos - 1) / 2); if (compare(data[pos], data[parent]) < 0) { swap(data, parent, pos); pos = parent; } else break; } }, _down: function (pos) { var data = this.data, compare = this.compare, len = this.length; while (true) { var left = 2 * pos + 1, right = left + 1, min = pos; if (left < len && compare(data[left], data[min]) < 0) min = left; if (right < len && compare(data[right], data[min]) < 0) min = right; if (min === pos) return; swap(data, min, pos); pos = min; } } }; function swap(data, i, j) { var tmp = data[i]; data[i] = data[j]; data[j] = tmp; } },{}],10:[function(require,module,exports){ "use strict" module.exports = twoProduct var SPLITTER = +(Math.pow(2, 27) + 1.0) function twoProduct(a, b, result) { var x = a * b var c = SPLITTER * a var abig = c - a var ahi = c - abig var alo = a - ahi var d = SPLITTER * b var bbig = d - b var bhi = d - bbig var blo = b - bhi var err1 = x - (ahi * bhi) var err2 = err1 - (alo * bhi) var err3 = err2 - (ahi * blo) var y = alo * blo - err3 if(result) { result[0] = y result[1] = x return result } return [ y, x ] } },{}],11:[function(require,module,exports){ "use strict" module.exports = fastTwoSum function fastTwoSum(a, b, result) { var x = a + b var bv = x - a var av = x - bv var br = b - bv var ar = a - av if(result) { result[0] = ar + br result[1] = x return result } return [ar+br, x] } },{}]},{},[1])(1) });