Update wmts-hidpi, add nicer-api-docs
This commit is contained in:
311
nicer-api-docs/closure-library/closure/goog/math/bezier.js
Normal file
311
nicer-api-docs/closure-library/closure/goog/math/bezier.js
Normal file
@@ -0,0 +1,311 @@
|
||||
// Copyright 2007 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
/**
|
||||
* @fileoverview Represents a cubic Bezier curve.
|
||||
*
|
||||
* Uses the deCasteljau algorithm to compute points on the curve.
|
||||
* http://en.wikipedia.org/wiki/De_Casteljau's_algorithm
|
||||
*
|
||||
* Currently it uses an unrolled version of the algorithm for speed. Eventually
|
||||
* it may be useful to use the loop form of the algorithm in order to support
|
||||
* curves of arbitrary degree.
|
||||
*
|
||||
* @author robbyw@google.com (Robby Walker)
|
||||
* @author wcrosby@google.com (Wayne Crosby)
|
||||
*/
|
||||
|
||||
goog.provide('goog.math.Bezier');
|
||||
|
||||
goog.require('goog.math');
|
||||
goog.require('goog.math.Coordinate');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Object representing a cubic bezier curve.
|
||||
* @param {number} x0 X coordinate of the start point.
|
||||
* @param {number} y0 Y coordinate of the start point.
|
||||
* @param {number} x1 X coordinate of the first control point.
|
||||
* @param {number} y1 Y coordinate of the first control point.
|
||||
* @param {number} x2 X coordinate of the second control point.
|
||||
* @param {number} y2 Y coordinate of the second control point.
|
||||
* @param {number} x3 X coordinate of the end point.
|
||||
* @param {number} y3 Y coordinate of the end point.
|
||||
* @constructor
|
||||
*/
|
||||
goog.math.Bezier = function(x0, y0, x1, y1, x2, y2, x3, y3) {
|
||||
/**
|
||||
* X coordinate of the first point.
|
||||
* @type {number}
|
||||
*/
|
||||
this.x0 = x0;
|
||||
|
||||
/**
|
||||
* Y coordinate of the first point.
|
||||
* @type {number}
|
||||
*/
|
||||
this.y0 = y0;
|
||||
|
||||
/**
|
||||
* X coordinate of the first control point.
|
||||
* @type {number}
|
||||
*/
|
||||
this.x1 = x1;
|
||||
|
||||
/**
|
||||
* Y coordinate of the first control point.
|
||||
* @type {number}
|
||||
*/
|
||||
this.y1 = y1;
|
||||
|
||||
/**
|
||||
* X coordinate of the second control point.
|
||||
* @type {number}
|
||||
*/
|
||||
this.x2 = x2;
|
||||
|
||||
/**
|
||||
* Y coordinate of the second control point.
|
||||
* @type {number}
|
||||
*/
|
||||
this.y2 = y2;
|
||||
|
||||
/**
|
||||
* X coordinate of the end point.
|
||||
* @type {number}
|
||||
*/
|
||||
this.x3 = x3;
|
||||
|
||||
/**
|
||||
* Y coordinate of the end point.
|
||||
* @type {number}
|
||||
*/
|
||||
this.y3 = y3;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Constant used to approximate ellipses.
|
||||
* See: http://canvaspaint.org/blog/2006/12/ellipse/
|
||||
* @type {number}
|
||||
*/
|
||||
goog.math.Bezier.KAPPA = 4 * (Math.sqrt(2) - 1) / 3;
|
||||
|
||||
|
||||
/**
|
||||
* @return {!goog.math.Bezier} A copy of this curve.
|
||||
*/
|
||||
goog.math.Bezier.prototype.clone = function() {
|
||||
return new goog.math.Bezier(this.x0, this.y0, this.x1, this.y1, this.x2,
|
||||
this.y2, this.x3, this.y3);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Test if the given curve is exactly the same as this one.
|
||||
* @param {goog.math.Bezier} other The other curve.
|
||||
* @return {boolean} Whether the given curve is the same as this one.
|
||||
*/
|
||||
goog.math.Bezier.prototype.equals = function(other) {
|
||||
return this.x0 == other.x0 && this.y0 == other.y0 && this.x1 == other.x1 &&
|
||||
this.y1 == other.y1 && this.x2 == other.x2 && this.y2 == other.y2 &&
|
||||
this.x3 == other.x3 && this.y3 == other.y3;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Modifies the curve in place to progress in the opposite direction.
|
||||
*/
|
||||
goog.math.Bezier.prototype.flip = function() {
|
||||
var temp = this.x0;
|
||||
this.x0 = this.x3;
|
||||
this.x3 = temp;
|
||||
temp = this.y0;
|
||||
this.y0 = this.y3;
|
||||
this.y3 = temp;
|
||||
|
||||
temp = this.x1;
|
||||
this.x1 = this.x2;
|
||||
this.x2 = temp;
|
||||
temp = this.y1;
|
||||
this.y1 = this.y2;
|
||||
this.y2 = temp;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Computes the curve at a point between 0 and 1.
|
||||
* @param {number} t The point on the curve to find.
|
||||
* @return {!goog.math.Coordinate} The computed coordinate.
|
||||
*/
|
||||
goog.math.Bezier.prototype.getPoint = function(t) {
|
||||
// Special case start and end
|
||||
if (t == 0) {
|
||||
return new goog.math.Coordinate(this.x0, this.y0);
|
||||
} else if (t == 1) {
|
||||
return new goog.math.Coordinate(this.x3, this.y3);
|
||||
}
|
||||
|
||||
// Step one - from 4 points to 3
|
||||
var ix0 = goog.math.lerp(this.x0, this.x1, t);
|
||||
var iy0 = goog.math.lerp(this.y0, this.y1, t);
|
||||
|
||||
var ix1 = goog.math.lerp(this.x1, this.x2, t);
|
||||
var iy1 = goog.math.lerp(this.y1, this.y2, t);
|
||||
|
||||
var ix2 = goog.math.lerp(this.x2, this.x3, t);
|
||||
var iy2 = goog.math.lerp(this.y2, this.y3, t);
|
||||
|
||||
// Step two - from 3 points to 2
|
||||
ix0 = goog.math.lerp(ix0, ix1, t);
|
||||
iy0 = goog.math.lerp(iy0, iy1, t);
|
||||
|
||||
ix1 = goog.math.lerp(ix1, ix2, t);
|
||||
iy1 = goog.math.lerp(iy1, iy2, t);
|
||||
|
||||
// Final step - last point
|
||||
return new goog.math.Coordinate(goog.math.lerp(ix0, ix1, t),
|
||||
goog.math.lerp(iy0, iy1, t));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Changes this curve in place to be the portion of itself from [t, 1].
|
||||
* @param {number} t The start of the desired portion of the curve.
|
||||
*/
|
||||
goog.math.Bezier.prototype.subdivideLeft = function(t) {
|
||||
if (t == 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Step one - from 4 points to 3
|
||||
var ix0 = goog.math.lerp(this.x0, this.x1, t);
|
||||
var iy0 = goog.math.lerp(this.y0, this.y1, t);
|
||||
|
||||
var ix1 = goog.math.lerp(this.x1, this.x2, t);
|
||||
var iy1 = goog.math.lerp(this.y1, this.y2, t);
|
||||
|
||||
var ix2 = goog.math.lerp(this.x2, this.x3, t);
|
||||
var iy2 = goog.math.lerp(this.y2, this.y3, t);
|
||||
|
||||
// Collect our new x1 and y1
|
||||
this.x1 = ix0;
|
||||
this.y1 = iy0;
|
||||
|
||||
// Step two - from 3 points to 2
|
||||
ix0 = goog.math.lerp(ix0, ix1, t);
|
||||
iy0 = goog.math.lerp(iy0, iy1, t);
|
||||
|
||||
ix1 = goog.math.lerp(ix1, ix2, t);
|
||||
iy1 = goog.math.lerp(iy1, iy2, t);
|
||||
|
||||
// Collect our new x2 and y2
|
||||
this.x2 = ix0;
|
||||
this.y2 = iy0;
|
||||
|
||||
// Final step - last point
|
||||
this.x3 = goog.math.lerp(ix0, ix1, t);
|
||||
this.y3 = goog.math.lerp(iy0, iy1, t);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Changes this curve in place to be the portion of itself from [0, t].
|
||||
* @param {number} t The end of the desired portion of the curve.
|
||||
*/
|
||||
goog.math.Bezier.prototype.subdivideRight = function(t) {
|
||||
this.flip();
|
||||
this.subdivideLeft(1 - t);
|
||||
this.flip();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Changes this curve in place to be the portion of itself from [s, t].
|
||||
* @param {number} s The start of the desired portion of the curve.
|
||||
* @param {number} t The end of the desired portion of the curve.
|
||||
*/
|
||||
goog.math.Bezier.prototype.subdivide = function(s, t) {
|
||||
this.subdivideRight(s);
|
||||
this.subdivideLeft((t - s) / (1 - s));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Computes the position t of a point on the curve given its x coordinate.
|
||||
* That is, for an input xVal, finds t s.t. getPoint(t).x = xVal.
|
||||
* As such, the following should always be true up to some small epsilon:
|
||||
* t ~ solvePositionFromXValue(getPoint(t).x) for t in [0, 1].
|
||||
* @param {number} xVal The x coordinate of the point to find on the curve.
|
||||
* @return {number} The position t.
|
||||
*/
|
||||
goog.math.Bezier.prototype.solvePositionFromXValue = function(xVal) {
|
||||
// Desired precision on the computation.
|
||||
var epsilon = 1e-6;
|
||||
|
||||
// Initial estimate of t using linear interpolation.
|
||||
var t = (xVal - this.x0) / (this.x3 - this.x0);
|
||||
if (t <= 0) {
|
||||
return 0;
|
||||
} else if (t >= 1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Try gradient descent to solve for t. If it works, it is very fast.
|
||||
var tMin = 0;
|
||||
var tMax = 1;
|
||||
for (var i = 0; i < 8; i++) {
|
||||
var value = this.getPoint(t).x;
|
||||
var derivative = (this.getPoint(t + epsilon).x - value) / epsilon;
|
||||
if (Math.abs(value - xVal) < epsilon) {
|
||||
return t;
|
||||
} else if (Math.abs(derivative) < epsilon) {
|
||||
break;
|
||||
} else {
|
||||
if (value < xVal) {
|
||||
tMin = t;
|
||||
} else {
|
||||
tMax = t;
|
||||
}
|
||||
t -= (value - xVal) / derivative;
|
||||
}
|
||||
}
|
||||
|
||||
// If the gradient descent got stuck in a local minimum, e.g. because
|
||||
// the derivative was close to 0, use a Dichotomy refinement instead.
|
||||
// We limit the number of interations to 8.
|
||||
for (var i = 0; Math.abs(value - xVal) > epsilon && i < 8; i++) {
|
||||
if (value < xVal) {
|
||||
tMin = t;
|
||||
t = (t + tMax) / 2;
|
||||
} else {
|
||||
tMax = t;
|
||||
t = (t + tMin) / 2;
|
||||
}
|
||||
value = this.getPoint(t).x;
|
||||
}
|
||||
return t;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Computes the y coordinate of a point on the curve given its x coordinate.
|
||||
* @param {number} xVal The x coordinate of the point on the curve.
|
||||
* @return {number} The y coordinate of the point on the curve.
|
||||
*/
|
||||
goog.math.Bezier.prototype.solveYValueFromXValue = function(xVal) {
|
||||
return this.getPoint(this.solvePositionFromXValue(xVal)).y;
|
||||
};
|
||||
369
nicer-api-docs/closure-library/closure/goog/math/box.js
Normal file
369
nicer-api-docs/closure-library/closure/goog/math/box.js
Normal file
@@ -0,0 +1,369 @@
|
||||
// Copyright 2006 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/**
|
||||
* @fileoverview A utility class for representing a numeric box.
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.math.Box');
|
||||
|
||||
goog.require('goog.math.Coordinate');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Class for representing a box. A box is specified as a top, right, bottom,
|
||||
* and left. A box is useful for representing margins and padding.
|
||||
*
|
||||
* @param {number} top Top.
|
||||
* @param {number} right Right.
|
||||
* @param {number} bottom Bottom.
|
||||
* @param {number} left Left.
|
||||
* @constructor
|
||||
*/
|
||||
goog.math.Box = function(top, right, bottom, left) {
|
||||
/**
|
||||
* Top
|
||||
* @type {number}
|
||||
*/
|
||||
this.top = top;
|
||||
|
||||
/**
|
||||
* Right
|
||||
* @type {number}
|
||||
*/
|
||||
this.right = right;
|
||||
|
||||
/**
|
||||
* Bottom
|
||||
* @type {number}
|
||||
*/
|
||||
this.bottom = bottom;
|
||||
|
||||
/**
|
||||
* Left
|
||||
* @type {number}
|
||||
*/
|
||||
this.left = left;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a Box by bounding a collection of goog.math.Coordinate objects
|
||||
* @param {...goog.math.Coordinate} var_args Coordinates to be included inside
|
||||
* the box.
|
||||
* @return {!goog.math.Box} A Box containing all the specified Coordinates.
|
||||
*/
|
||||
goog.math.Box.boundingBox = function(var_args) {
|
||||
var box = new goog.math.Box(arguments[0].y, arguments[0].x,
|
||||
arguments[0].y, arguments[0].x);
|
||||
for (var i = 1; i < arguments.length; i++) {
|
||||
var coord = arguments[i];
|
||||
box.top = Math.min(box.top, coord.y);
|
||||
box.right = Math.max(box.right, coord.x);
|
||||
box.bottom = Math.max(box.bottom, coord.y);
|
||||
box.left = Math.min(box.left, coord.x);
|
||||
}
|
||||
return box;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a copy of the box with the same dimensions.
|
||||
* @return {!goog.math.Box} A clone of this Box.
|
||||
*/
|
||||
goog.math.Box.prototype.clone = function() {
|
||||
return new goog.math.Box(this.top, this.right, this.bottom, this.left);
|
||||
};
|
||||
|
||||
|
||||
if (goog.DEBUG) {
|
||||
/**
|
||||
* Returns a nice string representing the box.
|
||||
* @return {string} In the form (50t, 73r, 24b, 13l).
|
||||
* @override
|
||||
*/
|
||||
goog.math.Box.prototype.toString = function() {
|
||||
return '(' + this.top + 't, ' + this.right + 'r, ' + this.bottom + 'b, ' +
|
||||
this.left + 'l)';
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether the box contains a coordinate or another box.
|
||||
*
|
||||
* @param {goog.math.Coordinate|goog.math.Box} other A Coordinate or a Box.
|
||||
* @return {boolean} Whether the box contains the coordinate or other box.
|
||||
*/
|
||||
goog.math.Box.prototype.contains = function(other) {
|
||||
return goog.math.Box.contains(this, other);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Expands box with the given margins.
|
||||
*
|
||||
* @param {number|goog.math.Box} top Top margin or box with all margins.
|
||||
* @param {number=} opt_right Right margin.
|
||||
* @param {number=} opt_bottom Bottom margin.
|
||||
* @param {number=} opt_left Left margin.
|
||||
* @return {!goog.math.Box} A reference to this Box.
|
||||
*/
|
||||
goog.math.Box.prototype.expand = function(top, opt_right, opt_bottom,
|
||||
opt_left) {
|
||||
if (goog.isObject(top)) {
|
||||
this.top -= top.top;
|
||||
this.right += top.right;
|
||||
this.bottom += top.bottom;
|
||||
this.left -= top.left;
|
||||
} else {
|
||||
this.top -= top;
|
||||
this.right += opt_right;
|
||||
this.bottom += opt_bottom;
|
||||
this.left -= opt_left;
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Expand this box to include another box.
|
||||
* NOTE(user): This is used in code that needs to be very fast, please don't
|
||||
* add functionality to this function at the expense of speed (variable
|
||||
* arguments, accepting multiple argument types, etc).
|
||||
* @param {goog.math.Box} box The box to include in this one.
|
||||
*/
|
||||
goog.math.Box.prototype.expandToInclude = function(box) {
|
||||
this.left = Math.min(this.left, box.left);
|
||||
this.top = Math.min(this.top, box.top);
|
||||
this.right = Math.max(this.right, box.right);
|
||||
this.bottom = Math.max(this.bottom, box.bottom);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Compares boxes for equality.
|
||||
* @param {goog.math.Box} a A Box.
|
||||
* @param {goog.math.Box} b A Box.
|
||||
* @return {boolean} True iff the boxes are equal, or if both are null.
|
||||
*/
|
||||
goog.math.Box.equals = function(a, b) {
|
||||
if (a == b) {
|
||||
return true;
|
||||
}
|
||||
if (!a || !b) {
|
||||
return false;
|
||||
}
|
||||
return a.top == b.top && a.right == b.right &&
|
||||
a.bottom == b.bottom && a.left == b.left;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether a box contains a coordinate or another box.
|
||||
*
|
||||
* @param {goog.math.Box} box A Box.
|
||||
* @param {goog.math.Coordinate|goog.math.Box} other A Coordinate or a Box.
|
||||
* @return {boolean} Whether the box contains the coordinate or other box.
|
||||
*/
|
||||
goog.math.Box.contains = function(box, other) {
|
||||
if (!box || !other) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (other instanceof goog.math.Box) {
|
||||
return other.left >= box.left && other.right <= box.right &&
|
||||
other.top >= box.top && other.bottom <= box.bottom;
|
||||
}
|
||||
|
||||
// other is a Coordinate.
|
||||
return other.x >= box.left && other.x <= box.right &&
|
||||
other.y >= box.top && other.y <= box.bottom;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the relative x position of a coordinate compared to a box. Returns
|
||||
* zero if the coordinate is inside the box.
|
||||
*
|
||||
* @param {goog.math.Box} box A Box.
|
||||
* @param {goog.math.Coordinate} coord A Coordinate.
|
||||
* @return {number} The x position of {@code coord} relative to the nearest
|
||||
* side of {@code box}, or zero if {@code coord} is inside {@code box}.
|
||||
*/
|
||||
goog.math.Box.relativePositionX = function(box, coord) {
|
||||
if (coord.x < box.left) {
|
||||
return coord.x - box.left;
|
||||
} else if (coord.x > box.right) {
|
||||
return coord.x - box.right;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the relative y position of a coordinate compared to a box. Returns
|
||||
* zero if the coordinate is inside the box.
|
||||
*
|
||||
* @param {goog.math.Box} box A Box.
|
||||
* @param {goog.math.Coordinate} coord A Coordinate.
|
||||
* @return {number} The y position of {@code coord} relative to the nearest
|
||||
* side of {@code box}, or zero if {@code coord} is inside {@code box}.
|
||||
*/
|
||||
goog.math.Box.relativePositionY = function(box, coord) {
|
||||
if (coord.y < box.top) {
|
||||
return coord.y - box.top;
|
||||
} else if (coord.y > box.bottom) {
|
||||
return coord.y - box.bottom;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the distance between a coordinate and the nearest corner/side of a
|
||||
* box. Returns zero if the coordinate is inside the box.
|
||||
*
|
||||
* @param {goog.math.Box} box A Box.
|
||||
* @param {goog.math.Coordinate} coord A Coordinate.
|
||||
* @return {number} The distance between {@code coord} and the nearest
|
||||
* corner/side of {@code box}, or zero if {@code coord} is inside
|
||||
* {@code box}.
|
||||
*/
|
||||
goog.math.Box.distance = function(box, coord) {
|
||||
var x = goog.math.Box.relativePositionX(box, coord);
|
||||
var y = goog.math.Box.relativePositionY(box, coord);
|
||||
return Math.sqrt(x * x + y * y);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether two boxes intersect.
|
||||
*
|
||||
* @param {goog.math.Box} a A Box.
|
||||
* @param {goog.math.Box} b A second Box.
|
||||
* @return {boolean} Whether the boxes intersect.
|
||||
*/
|
||||
goog.math.Box.intersects = function(a, b) {
|
||||
return (a.left <= b.right && b.left <= a.right &&
|
||||
a.top <= b.bottom && b.top <= a.bottom);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether two boxes would intersect with additional padding.
|
||||
*
|
||||
* @param {goog.math.Box} a A Box.
|
||||
* @param {goog.math.Box} b A second Box.
|
||||
* @param {number} padding The additional padding.
|
||||
* @return {boolean} Whether the boxes intersect.
|
||||
*/
|
||||
goog.math.Box.intersectsWithPadding = function(a, b, padding) {
|
||||
return (a.left <= b.right + padding && b.left <= a.right + padding &&
|
||||
a.top <= b.bottom + padding && b.top <= a.bottom + padding);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Rounds the fields to the next larger integer values.
|
||||
*
|
||||
* @return {!goog.math.Box} This box with ceil'd fields.
|
||||
*/
|
||||
goog.math.Box.prototype.ceil = function() {
|
||||
this.top = Math.ceil(this.top);
|
||||
this.right = Math.ceil(this.right);
|
||||
this.bottom = Math.ceil(this.bottom);
|
||||
this.left = Math.ceil(this.left);
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Rounds the fields to the next smaller integer values.
|
||||
*
|
||||
* @return {!goog.math.Box} This box with floored fields.
|
||||
*/
|
||||
goog.math.Box.prototype.floor = function() {
|
||||
this.top = Math.floor(this.top);
|
||||
this.right = Math.floor(this.right);
|
||||
this.bottom = Math.floor(this.bottom);
|
||||
this.left = Math.floor(this.left);
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Rounds the fields to nearest integer values.
|
||||
*
|
||||
* @return {!goog.math.Box} This box with rounded fields.
|
||||
*/
|
||||
goog.math.Box.prototype.round = function() {
|
||||
this.top = Math.round(this.top);
|
||||
this.right = Math.round(this.right);
|
||||
this.bottom = Math.round(this.bottom);
|
||||
this.left = Math.round(this.left);
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Translates this box by the given offsets. If a {@code goog.math.Coordinate}
|
||||
* is given, then the left and right values are translated by the coordinate's
|
||||
* x value and the top and bottom values are translated by the coordinate's y
|
||||
* value. Otherwise, {@code tx} and {@code opt_ty} are used to translate the x
|
||||
* and y dimension values.
|
||||
*
|
||||
* @param {number|goog.math.Coordinate} tx The value to translate the x
|
||||
* dimension values by or the the coordinate to translate this box by.
|
||||
* @param {number=} opt_ty The value to translate y dimension values by.
|
||||
* @return {!goog.math.Box} This box after translating.
|
||||
*/
|
||||
goog.math.Box.prototype.translate = function(tx, opt_ty) {
|
||||
if (tx instanceof goog.math.Coordinate) {
|
||||
this.left += tx.x;
|
||||
this.right += tx.x;
|
||||
this.top += tx.y;
|
||||
this.bottom += tx.y;
|
||||
} else {
|
||||
this.left += tx;
|
||||
this.right += tx;
|
||||
if (goog.isNumber(opt_ty)) {
|
||||
this.top += opt_ty;
|
||||
this.bottom += opt_ty;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Scales this coordinate by the given scale factors. The x and y dimension
|
||||
* values are scaled by {@code sx} and {@code opt_sy} respectively.
|
||||
* If {@code opt_sy} is not given, then {@code sx} is used for both x and y.
|
||||
*
|
||||
* @param {number} sx The scale factor to use for the x dimension.
|
||||
* @param {number=} opt_sy The scale factor to use for the y dimension.
|
||||
* @return {!goog.math.Box} This box after scaling.
|
||||
*/
|
||||
goog.math.Box.prototype.scale = function(sx, opt_sy) {
|
||||
var sy = goog.isNumber(opt_sy) ? opt_sy : sx;
|
||||
this.left *= sx;
|
||||
this.right *= sx;
|
||||
this.top *= sy;
|
||||
this.bottom *= sy;
|
||||
return this;
|
||||
};
|
||||
233
nicer-api-docs/closure-library/closure/goog/math/coordinate.js
Normal file
233
nicer-api-docs/closure-library/closure/goog/math/coordinate.js
Normal file
@@ -0,0 +1,233 @@
|
||||
// Copyright 2006 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/**
|
||||
* @fileoverview A utility class for representing two-dimensional positions.
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.math.Coordinate');
|
||||
|
||||
goog.require('goog.math');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Class for representing coordinates and positions.
|
||||
* @param {number=} opt_x Left, defaults to 0.
|
||||
* @param {number=} opt_y Top, defaults to 0.
|
||||
* @constructor
|
||||
*/
|
||||
goog.math.Coordinate = function(opt_x, opt_y) {
|
||||
/**
|
||||
* X-value
|
||||
* @type {number}
|
||||
*/
|
||||
this.x = goog.isDef(opt_x) ? opt_x : 0;
|
||||
|
||||
/**
|
||||
* Y-value
|
||||
* @type {number}
|
||||
*/
|
||||
this.y = goog.isDef(opt_y) ? opt_y : 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a new copy of the coordinate.
|
||||
* @return {!goog.math.Coordinate} A clone of this coordinate.
|
||||
*/
|
||||
goog.math.Coordinate.prototype.clone = function() {
|
||||
return new goog.math.Coordinate(this.x, this.y);
|
||||
};
|
||||
|
||||
|
||||
if (goog.DEBUG) {
|
||||
/**
|
||||
* Returns a nice string representing the coordinate.
|
||||
* @return {string} In the form (50, 73).
|
||||
* @override
|
||||
*/
|
||||
goog.math.Coordinate.prototype.toString = function() {
|
||||
return '(' + this.x + ', ' + this.y + ')';
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compares coordinates for equality.
|
||||
* @param {goog.math.Coordinate} a A Coordinate.
|
||||
* @param {goog.math.Coordinate} b A Coordinate.
|
||||
* @return {boolean} True iff the coordinates are equal, or if both are null.
|
||||
*/
|
||||
goog.math.Coordinate.equals = function(a, b) {
|
||||
if (a == b) {
|
||||
return true;
|
||||
}
|
||||
if (!a || !b) {
|
||||
return false;
|
||||
}
|
||||
return a.x == b.x && a.y == b.y;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the distance between two coordinates.
|
||||
* @param {!goog.math.Coordinate} a A Coordinate.
|
||||
* @param {!goog.math.Coordinate} b A Coordinate.
|
||||
* @return {number} The distance between {@code a} and {@code b}.
|
||||
*/
|
||||
goog.math.Coordinate.distance = function(a, b) {
|
||||
var dx = a.x - b.x;
|
||||
var dy = a.y - b.y;
|
||||
return Math.sqrt(dx * dx + dy * dy);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the magnitude of a coordinate.
|
||||
* @param {!goog.math.Coordinate} a A Coordinate.
|
||||
* @return {number} The distance between the origin and {@code a}.
|
||||
*/
|
||||
goog.math.Coordinate.magnitude = function(a) {
|
||||
return Math.sqrt(a.x * a.x + a.y * a.y);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the angle from the origin to a coordinate.
|
||||
* @param {!goog.math.Coordinate} a A Coordinate.
|
||||
* @return {number} The angle, in degrees, clockwise from the positive X
|
||||
* axis to {@code a}.
|
||||
*/
|
||||
goog.math.Coordinate.azimuth = function(a) {
|
||||
return goog.math.angle(0, 0, a.x, a.y);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the squared distance between two coordinates. Squared distances can
|
||||
* be used for comparisons when the actual value is not required.
|
||||
*
|
||||
* Performance note: eliminating the square root is an optimization often used
|
||||
* in lower-level languages, but the speed difference is not nearly as
|
||||
* pronounced in JavaScript (only a few percent.)
|
||||
*
|
||||
* @param {!goog.math.Coordinate} a A Coordinate.
|
||||
* @param {!goog.math.Coordinate} b A Coordinate.
|
||||
* @return {number} The squared distance between {@code a} and {@code b}.
|
||||
*/
|
||||
goog.math.Coordinate.squaredDistance = function(a, b) {
|
||||
var dx = a.x - b.x;
|
||||
var dy = a.y - b.y;
|
||||
return dx * dx + dy * dy;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the difference between two coordinates as a new
|
||||
* goog.math.Coordinate.
|
||||
* @param {!goog.math.Coordinate} a A Coordinate.
|
||||
* @param {!goog.math.Coordinate} b A Coordinate.
|
||||
* @return {!goog.math.Coordinate} A Coordinate representing the difference
|
||||
* between {@code a} and {@code b}.
|
||||
*/
|
||||
goog.math.Coordinate.difference = function(a, b) {
|
||||
return new goog.math.Coordinate(a.x - b.x, a.y - b.y);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the sum of two coordinates as a new goog.math.Coordinate.
|
||||
* @param {!goog.math.Coordinate} a A Coordinate.
|
||||
* @param {!goog.math.Coordinate} b A Coordinate.
|
||||
* @return {!goog.math.Coordinate} A Coordinate representing the sum of the two
|
||||
* coordinates.
|
||||
*/
|
||||
goog.math.Coordinate.sum = function(a, b) {
|
||||
return new goog.math.Coordinate(a.x + b.x, a.y + b.y);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Rounds the x and y fields to the next larger integer values.
|
||||
* @return {!goog.math.Coordinate} This coordinate with ceil'd fields.
|
||||
*/
|
||||
goog.math.Coordinate.prototype.ceil = function() {
|
||||
this.x = Math.ceil(this.x);
|
||||
this.y = Math.ceil(this.y);
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Rounds the x and y fields to the next smaller integer values.
|
||||
* @return {!goog.math.Coordinate} This coordinate with floored fields.
|
||||
*/
|
||||
goog.math.Coordinate.prototype.floor = function() {
|
||||
this.x = Math.floor(this.x);
|
||||
this.y = Math.floor(this.y);
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Rounds the x and y fields to the nearest integer values.
|
||||
* @return {!goog.math.Coordinate} This coordinate with rounded fields.
|
||||
*/
|
||||
goog.math.Coordinate.prototype.round = function() {
|
||||
this.x = Math.round(this.x);
|
||||
this.y = Math.round(this.y);
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Translates this box by the given offsets. If a {@code goog.math.Coordinate}
|
||||
* is given, then the x and y values are translated by the coordinate's x and y.
|
||||
* Otherwise, x and y are translated by {@code tx} and {@code opt_ty}
|
||||
* respectively.
|
||||
* @param {number|goog.math.Coordinate} tx The value to translate x by or the
|
||||
* the coordinate to translate this coordinate by.
|
||||
* @param {number=} opt_ty The value to translate y by.
|
||||
* @return {!goog.math.Coordinate} This coordinate after translating.
|
||||
*/
|
||||
goog.math.Coordinate.prototype.translate = function(tx, opt_ty) {
|
||||
if (tx instanceof goog.math.Coordinate) {
|
||||
this.x += tx.x;
|
||||
this.y += tx.y;
|
||||
} else {
|
||||
this.x += tx;
|
||||
if (goog.isNumber(opt_ty)) {
|
||||
this.y += opt_ty;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Scales this coordinate by the given scale factors. The x and y values are
|
||||
* scaled by {@code sx} and {@code opt_sy} respectively. If {@code opt_sy}
|
||||
* is not given, then {@code sx} is used for both x and y.
|
||||
* @param {number} sx The scale factor to use for the x dimension.
|
||||
* @param {number=} opt_sy The scale factor to use for the y dimension.
|
||||
* @return {!goog.math.Coordinate} This coordinate after scaling.
|
||||
*/
|
||||
goog.math.Coordinate.prototype.scale = function(sx, opt_sy) {
|
||||
var sy = goog.isNumber(opt_sy) ? opt_sy : sx;
|
||||
this.x *= sx;
|
||||
this.y *= sy;
|
||||
return this;
|
||||
};
|
||||
169
nicer-api-docs/closure-library/closure/goog/math/coordinate3.js
Normal file
169
nicer-api-docs/closure-library/closure/goog/math/coordinate3.js
Normal file
@@ -0,0 +1,169 @@
|
||||
// Copyright 2008 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/**
|
||||
* @fileoverview A utility class for representing three-dimensional points.
|
||||
*
|
||||
* Based heavily on coordinate.js by:
|
||||
*/
|
||||
|
||||
goog.provide('goog.math.Coordinate3');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Class for representing coordinates and positions in 3 dimensions.
|
||||
*
|
||||
* @param {number=} opt_x X coordinate, defaults to 0.
|
||||
* @param {number=} opt_y Y coordinate, defaults to 0.
|
||||
* @param {number=} opt_z Z coordinate, defaults to 0.
|
||||
* @constructor
|
||||
*/
|
||||
goog.math.Coordinate3 = function(opt_x, opt_y, opt_z) {
|
||||
/**
|
||||
* X-value
|
||||
* @type {number}
|
||||
*/
|
||||
this.x = goog.isDef(opt_x) ? opt_x : 0;
|
||||
|
||||
/**
|
||||
* Y-value
|
||||
* @type {number}
|
||||
*/
|
||||
this.y = goog.isDef(opt_y) ? opt_y : 0;
|
||||
|
||||
/**
|
||||
* Z-value
|
||||
* @type {number}
|
||||
*/
|
||||
this.z = goog.isDef(opt_z) ? opt_z : 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a new copy of the coordinate.
|
||||
*
|
||||
* @return {!goog.math.Coordinate3} A clone of this coordinate.
|
||||
*/
|
||||
goog.math.Coordinate3.prototype.clone = function() {
|
||||
return new goog.math.Coordinate3(this.x, this.y, this.z);
|
||||
};
|
||||
|
||||
|
||||
if (goog.DEBUG) {
|
||||
/**
|
||||
* Returns a nice string representing the coordinate.
|
||||
*
|
||||
* @return {string} In the form (50, 73, 31).
|
||||
* @override
|
||||
*/
|
||||
goog.math.Coordinate3.prototype.toString = function() {
|
||||
return '(' + this.x + ', ' + this.y + ', ' + this.z + ')';
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compares coordinates for equality.
|
||||
*
|
||||
* @param {goog.math.Coordinate3} a A Coordinate3.
|
||||
* @param {goog.math.Coordinate3} b A Coordinate3.
|
||||
* @return {boolean} True iff the coordinates are equal, or if both are null.
|
||||
*/
|
||||
goog.math.Coordinate3.equals = function(a, b) {
|
||||
if (a == b) {
|
||||
return true;
|
||||
}
|
||||
if (!a || !b) {
|
||||
return false;
|
||||
}
|
||||
return a.x == b.x && a.y == b.y && a.z == b.z;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the distance between two coordinates.
|
||||
*
|
||||
* @param {goog.math.Coordinate3} a A Coordinate3.
|
||||
* @param {goog.math.Coordinate3} b A Coordinate3.
|
||||
* @return {number} The distance between {@code a} and {@code b}.
|
||||
*/
|
||||
goog.math.Coordinate3.distance = function(a, b) {
|
||||
var dx = a.x - b.x;
|
||||
var dy = a.y - b.y;
|
||||
var dz = a.z - b.z;
|
||||
return Math.sqrt(dx * dx + dy * dy + dz * dz);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the squared distance between two coordinates. Squared distances can
|
||||
* be used for comparisons when the actual value is not required.
|
||||
*
|
||||
* Performance note: eliminating the square root is an optimization often used
|
||||
* in lower-level languages, but the speed difference is not nearly as
|
||||
* pronounced in JavaScript (only a few percent.)
|
||||
*
|
||||
* @param {goog.math.Coordinate3} a A Coordinate3.
|
||||
* @param {goog.math.Coordinate3} b A Coordinate3.
|
||||
* @return {number} The squared distance between {@code a} and {@code b}.
|
||||
*/
|
||||
goog.math.Coordinate3.squaredDistance = function(a, b) {
|
||||
var dx = a.x - b.x;
|
||||
var dy = a.y - b.y;
|
||||
var dz = a.z - b.z;
|
||||
return dx * dx + dy * dy + dz * dz;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the difference between two coordinates as a new
|
||||
* goog.math.Coordinate3.
|
||||
*
|
||||
* @param {goog.math.Coordinate3} a A Coordinate3.
|
||||
* @param {goog.math.Coordinate3} b A Coordinate3.
|
||||
* @return {!goog.math.Coordinate3} A Coordinate3 representing the difference
|
||||
* between {@code a} and {@code b}.
|
||||
*/
|
||||
goog.math.Coordinate3.difference = function(a, b) {
|
||||
return new goog.math.Coordinate3(a.x - b.x, a.y - b.y, a.z - b.z);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the contents of this coordinate as a 3 value Array.
|
||||
*
|
||||
* @return {!Array.<number>} A new array.
|
||||
*/
|
||||
goog.math.Coordinate3.prototype.toArray = function() {
|
||||
return [this.x, this.y, this.z];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts a three element array into a Coordinate3 object. If the value
|
||||
* passed in is not an array, not array-like, or not of the right length, an
|
||||
* error is thrown.
|
||||
*
|
||||
* @param {Array.<number>} a Array of numbers to become a coordinate.
|
||||
* @return {!goog.math.Coordinate3} A new coordinate from the array values.
|
||||
* @throws {Error} When the oject passed in is not valid.
|
||||
*/
|
||||
goog.math.Coordinate3.fromArray = function(a) {
|
||||
if (a.length <= 3) {
|
||||
return new goog.math.Coordinate3(a[0], a[1], a[2]);
|
||||
}
|
||||
|
||||
throw Error('Conversion from an array requires an array of length 3');
|
||||
};
|
||||
@@ -0,0 +1,103 @@
|
||||
// Copyright 2011 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
/**
|
||||
* @fileoverview Utility class to manage the mathematics behind computing an
|
||||
* exponential backoff model. Given an initial backoff value and a maximum
|
||||
* backoff value, every call to backoff() will double the value until maximum
|
||||
* backoff value is reached.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.math.ExponentialBackoff');
|
||||
|
||||
goog.require('goog.asserts');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*
|
||||
* @param {number} initialValue The initial backoff value.
|
||||
* @param {number} maxValue The maximum backoff value.
|
||||
*/
|
||||
goog.math.ExponentialBackoff = function(initialValue, maxValue) {
|
||||
goog.asserts.assert(initialValue > 0,
|
||||
'Initial value must be greater than zero.');
|
||||
goog.asserts.assert(maxValue >= initialValue,
|
||||
'Max value should be at least as large as initial value.');
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.initialValue_ = initialValue;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.maxValue_ = maxValue;
|
||||
|
||||
/**
|
||||
* The current backoff value.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.currValue_ = initialValue;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The number of backoffs that have happened.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.math.ExponentialBackoff.prototype.currCount_ = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Resets the backoff value to its initial value.
|
||||
*/
|
||||
goog.math.ExponentialBackoff.prototype.reset = function() {
|
||||
this.currValue_ = this.initialValue_;
|
||||
this.currCount_ = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} The current backoff value.
|
||||
*/
|
||||
goog.math.ExponentialBackoff.prototype.getValue = function() {
|
||||
return this.currValue_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} The number of times this class has backed off.
|
||||
*/
|
||||
goog.math.ExponentialBackoff.prototype.getBackoffCount = function() {
|
||||
return this.currCount_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Initiates a backoff.
|
||||
*/
|
||||
goog.math.ExponentialBackoff.prototype.backoff = function() {
|
||||
this.currValue_ = Math.min(this.maxValue_, this.currValue_ * 2);
|
||||
this.currCount_++;
|
||||
};
|
||||
737
nicer-api-docs/closure-library/closure/goog/math/integer.js
Normal file
737
nicer-api-docs/closure-library/closure/goog/math/integer.js
Normal file
@@ -0,0 +1,737 @@
|
||||
// Copyright 2009 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/**
|
||||
* @fileoverview Defines an Integer class for representing (potentially)
|
||||
* infinite length two's-complement integer values.
|
||||
*
|
||||
* For the specific case of 64-bit integers, use goog.math.Long, which is more
|
||||
* efficient.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.math.Integer');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a two's-complement integer an array containing bits of the
|
||||
* integer in 32-bit (signed) pieces, given in little-endian order (i.e.,
|
||||
* lowest-order bits in the first piece), and the sign of -1 or 0.
|
||||
*
|
||||
* See the from* functions below for other convenient ways of constructing
|
||||
* Integers.
|
||||
*
|
||||
* The internal representation of an integer is an array of 32-bit signed
|
||||
* pieces, along with a sign (0 or -1) that indicates the contents of all the
|
||||
* other 32-bit pieces out to infinity. We use 32-bit pieces because these are
|
||||
* the size of integers on which Javascript performs bit-operations. For
|
||||
* operations like addition and multiplication, we split each number into 16-bit
|
||||
* pieces, which can easily be multiplied within Javascript's floating-point
|
||||
* representation without overflow or change in sign.
|
||||
*
|
||||
* @constructor
|
||||
* @param {Array.<number>} bits Array containing the bits of the number.
|
||||
* @param {number} sign The sign of the number: -1 for negative and 0 positive.
|
||||
*/
|
||||
goog.math.Integer = function(bits, sign) {
|
||||
/**
|
||||
* @type {!Array.<number>}
|
||||
* @private
|
||||
*/
|
||||
this.bits_ = [];
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.sign_ = sign;
|
||||
|
||||
// Copy the 32-bit signed integer values passed in. We prune out those at the
|
||||
// top that equal the sign since they are redundant.
|
||||
var top = true;
|
||||
for (var i = bits.length - 1; i >= 0; i--) {
|
||||
var val = bits[i] | 0;
|
||||
if (!top || val != sign) {
|
||||
this.bits_[i] = val;
|
||||
top = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the
|
||||
// from* methods on which they depend.
|
||||
|
||||
|
||||
/**
|
||||
* A cache of the Integer representations of small integer values.
|
||||
* @type {!Object}
|
||||
* @private
|
||||
*/
|
||||
goog.math.Integer.IntCache_ = {};
|
||||
|
||||
|
||||
/**
|
||||
* Returns an Integer representing the given (32-bit) integer value.
|
||||
* @param {number} value A 32-bit integer value.
|
||||
* @return {!goog.math.Integer} The corresponding Integer value.
|
||||
*/
|
||||
goog.math.Integer.fromInt = function(value) {
|
||||
if (-128 <= value && value < 128) {
|
||||
var cachedObj = goog.math.Integer.IntCache_[value];
|
||||
if (cachedObj) {
|
||||
return cachedObj;
|
||||
}
|
||||
}
|
||||
|
||||
var obj = new goog.math.Integer([value | 0], value < 0 ? -1 : 0);
|
||||
if (-128 <= value && value < 128) {
|
||||
goog.math.Integer.IntCache_[value] = obj;
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns an Integer representing the given value, provided that it is a finite
|
||||
* number. Otherwise, zero is returned.
|
||||
* @param {number} value The value in question.
|
||||
* @return {!goog.math.Integer} The corresponding Integer value.
|
||||
*/
|
||||
goog.math.Integer.fromNumber = function(value) {
|
||||
if (isNaN(value) || !isFinite(value)) {
|
||||
return goog.math.Integer.ZERO;
|
||||
} else if (value < 0) {
|
||||
return goog.math.Integer.fromNumber(-value).negate();
|
||||
} else {
|
||||
var bits = [];
|
||||
var pow = 1;
|
||||
for (var i = 0; value >= pow; i++) {
|
||||
bits[i] = (value / pow) | 0;
|
||||
pow *= goog.math.Integer.TWO_PWR_32_DBL_;
|
||||
}
|
||||
return new goog.math.Integer(bits, 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a Integer representing the value that comes by concatenating the
|
||||
* given entries, each is assumed to be 32 signed bits, given in little-endian
|
||||
* order (lowest order bits in the lowest index), and sign-extending the highest
|
||||
* order 32-bit value.
|
||||
* @param {Array.<number>} bits The bits of the number, in 32-bit signed pieces,
|
||||
* in little-endian order.
|
||||
* @return {!goog.math.Integer} The corresponding Integer value.
|
||||
*/
|
||||
goog.math.Integer.fromBits = function(bits) {
|
||||
var high = bits[bits.length - 1];
|
||||
return new goog.math.Integer(bits, high & (1 << 31) ? -1 : 0);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns an Integer representation of the given string, written using the
|
||||
* given radix.
|
||||
* @param {string} str The textual representation of the Integer.
|
||||
* @param {number=} opt_radix The radix in which the text is written.
|
||||
* @return {!goog.math.Integer} The corresponding Integer value.
|
||||
*/
|
||||
goog.math.Integer.fromString = function(str, opt_radix) {
|
||||
if (str.length == 0) {
|
||||
throw Error('number format error: empty string');
|
||||
}
|
||||
|
||||
var radix = opt_radix || 10;
|
||||
if (radix < 2 || 36 < radix) {
|
||||
throw Error('radix out of range: ' + radix);
|
||||
}
|
||||
|
||||
if (str.charAt(0) == '-') {
|
||||
return goog.math.Integer.fromString(str.substring(1), radix).negate();
|
||||
} else if (str.indexOf('-') >= 0) {
|
||||
throw Error('number format error: interior "-" character');
|
||||
}
|
||||
|
||||
// Do several (8) digits each time through the loop, so as to
|
||||
// minimize the calls to the very expensive emulated div.
|
||||
var radixToPower = goog.math.Integer.fromNumber(Math.pow(radix, 8));
|
||||
|
||||
var result = goog.math.Integer.ZERO;
|
||||
for (var i = 0; i < str.length; i += 8) {
|
||||
var size = Math.min(8, str.length - i);
|
||||
var value = parseInt(str.substring(i, i + size), radix);
|
||||
if (size < 8) {
|
||||
var power = goog.math.Integer.fromNumber(Math.pow(radix, size));
|
||||
result = result.multiply(power).add(goog.math.Integer.fromNumber(value));
|
||||
} else {
|
||||
result = result.multiply(radixToPower);
|
||||
result = result.add(goog.math.Integer.fromNumber(value));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A number used repeatedly in calculations. This must appear before the first
|
||||
* call to the from* functions below.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.math.Integer.TWO_PWR_32_DBL_ = (1 << 16) * (1 << 16);
|
||||
|
||||
|
||||
/** @type {!goog.math.Integer} */
|
||||
goog.math.Integer.ZERO = goog.math.Integer.fromInt(0);
|
||||
|
||||
|
||||
/** @type {!goog.math.Integer} */
|
||||
goog.math.Integer.ONE = goog.math.Integer.fromInt(1);
|
||||
|
||||
|
||||
/**
|
||||
* @type {!goog.math.Integer}
|
||||
* @private
|
||||
*/
|
||||
goog.math.Integer.TWO_PWR_24_ = goog.math.Integer.fromInt(1 << 24);
|
||||
|
||||
|
||||
/**
|
||||
* Returns the value, assuming it is a 32-bit integer.
|
||||
* @return {number} The corresponding int value.
|
||||
*/
|
||||
goog.math.Integer.prototype.toInt = function() {
|
||||
return this.bits_.length > 0 ? this.bits_[0] : this.sign_;
|
||||
};
|
||||
|
||||
|
||||
/** @return {number} The closest floating-point representation to this value. */
|
||||
goog.math.Integer.prototype.toNumber = function() {
|
||||
if (this.isNegative()) {
|
||||
return -this.negate().toNumber();
|
||||
} else {
|
||||
var val = 0;
|
||||
var pow = 1;
|
||||
for (var i = 0; i < this.bits_.length; i++) {
|
||||
val += this.getBitsUnsigned(i) * pow;
|
||||
pow *= goog.math.Integer.TWO_PWR_32_DBL_;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number=} opt_radix The radix in which the text should be written.
|
||||
* @return {string} The textual representation of this value.
|
||||
* @override
|
||||
*/
|
||||
goog.math.Integer.prototype.toString = function(opt_radix) {
|
||||
var radix = opt_radix || 10;
|
||||
if (radix < 2 || 36 < radix) {
|
||||
throw Error('radix out of range: ' + radix);
|
||||
}
|
||||
|
||||
if (this.isZero()) {
|
||||
return '0';
|
||||
} else if (this.isNegative()) {
|
||||
return '-' + this.negate().toString(radix);
|
||||
}
|
||||
|
||||
// Do several (6) digits each time through the loop, so as to
|
||||
// minimize the calls to the very expensive emulated div.
|
||||
var radixToPower = goog.math.Integer.fromNumber(Math.pow(radix, 6));
|
||||
|
||||
var rem = this;
|
||||
var result = '';
|
||||
while (true) {
|
||||
var remDiv = rem.divide(radixToPower);
|
||||
var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt();
|
||||
var digits = intval.toString(radix);
|
||||
|
||||
rem = remDiv;
|
||||
if (rem.isZero()) {
|
||||
return digits + result;
|
||||
} else {
|
||||
while (digits.length < 6) {
|
||||
digits = '0' + digits;
|
||||
}
|
||||
result = '' + digits + result;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the index-th 32-bit (signed) piece of the Integer according to
|
||||
* little-endian order (i.e., index 0 contains the smallest bits).
|
||||
* @param {number} index The index in question.
|
||||
* @return {number} The requested 32-bits as a signed number.
|
||||
*/
|
||||
goog.math.Integer.prototype.getBits = function(index) {
|
||||
if (index < 0) {
|
||||
return 0; // Allowing this simplifies bit shifting operations below...
|
||||
} else if (index < this.bits_.length) {
|
||||
return this.bits_[index];
|
||||
} else {
|
||||
return this.sign_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the index-th 32-bit piece as an unsigned number.
|
||||
* @param {number} index The index in question.
|
||||
* @return {number} The requested 32-bits as an unsigned number.
|
||||
*/
|
||||
goog.math.Integer.prototype.getBitsUnsigned = function(index) {
|
||||
var val = this.getBits(index);
|
||||
return val >= 0 ? val : goog.math.Integer.TWO_PWR_32_DBL_ + val;
|
||||
};
|
||||
|
||||
|
||||
/** @return {number} The sign bit of this number, -1 or 0. */
|
||||
goog.math.Integer.prototype.getSign = function() {
|
||||
return this.sign_;
|
||||
};
|
||||
|
||||
|
||||
/** @return {boolean} Whether this value is zero. */
|
||||
goog.math.Integer.prototype.isZero = function() {
|
||||
if (this.sign_ != 0) {
|
||||
return false;
|
||||
}
|
||||
for (var i = 0; i < this.bits_.length; i++) {
|
||||
if (this.bits_[i] != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
/** @return {boolean} Whether this value is negative. */
|
||||
goog.math.Integer.prototype.isNegative = function() {
|
||||
return this.sign_ == -1;
|
||||
};
|
||||
|
||||
|
||||
/** @return {boolean} Whether this value is odd. */
|
||||
goog.math.Integer.prototype.isOdd = function() {
|
||||
return (this.bits_.length == 0) && (this.sign_ == -1) ||
|
||||
(this.bits_.length > 0) && ((this.bits_[0] & 1) != 0);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.math.Integer} other Integer to compare against.
|
||||
* @return {boolean} Whether this Integer equals the other.
|
||||
*/
|
||||
goog.math.Integer.prototype.equals = function(other) {
|
||||
if (this.sign_ != other.sign_) {
|
||||
return false;
|
||||
}
|
||||
var len = Math.max(this.bits_.length, other.bits_.length);
|
||||
for (var i = 0; i < len; i++) {
|
||||
if (this.getBits(i) != other.getBits(i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.math.Integer} other Integer to compare against.
|
||||
* @return {boolean} Whether this Integer does not equal the other.
|
||||
*/
|
||||
goog.math.Integer.prototype.notEquals = function(other) {
|
||||
return !this.equals(other);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.math.Integer} other Integer to compare against.
|
||||
* @return {boolean} Whether this Integer is greater than the other.
|
||||
*/
|
||||
goog.math.Integer.prototype.greaterThan = function(other) {
|
||||
return this.compare(other) > 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.math.Integer} other Integer to compare against.
|
||||
* @return {boolean} Whether this Integer is greater than or equal to the other.
|
||||
*/
|
||||
goog.math.Integer.prototype.greaterThanOrEqual = function(other) {
|
||||
return this.compare(other) >= 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.math.Integer} other Integer to compare against.
|
||||
* @return {boolean} Whether this Integer is less than the other.
|
||||
*/
|
||||
goog.math.Integer.prototype.lessThan = function(other) {
|
||||
return this.compare(other) < 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.math.Integer} other Integer to compare against.
|
||||
* @return {boolean} Whether this Integer is less than or equal to the other.
|
||||
*/
|
||||
goog.math.Integer.prototype.lessThanOrEqual = function(other) {
|
||||
return this.compare(other) <= 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Compares this Integer with the given one.
|
||||
* @param {goog.math.Integer} other Integer to compare against.
|
||||
* @return {number} 0 if they are the same, 1 if the this is greater, and -1
|
||||
* if the given one is greater.
|
||||
*/
|
||||
goog.math.Integer.prototype.compare = function(other) {
|
||||
var diff = this.subtract(other);
|
||||
if (diff.isNegative()) {
|
||||
return -1;
|
||||
} else if (diff.isZero()) {
|
||||
return 0;
|
||||
} else {
|
||||
return +1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns an integer with only the first numBits bits of this value, sign
|
||||
* extended from the final bit.
|
||||
* @param {number} numBits The number of bits by which to shift.
|
||||
* @return {!goog.math.Integer} The shorted integer value.
|
||||
*/
|
||||
goog.math.Integer.prototype.shorten = function(numBits) {
|
||||
var arr_index = (numBits - 1) >> 5;
|
||||
var bit_index = (numBits - 1) % 32;
|
||||
var bits = [];
|
||||
for (var i = 0; i < arr_index; i++) {
|
||||
bits[i] = this.getBits(i);
|
||||
}
|
||||
var sigBits = bit_index == 31 ? 0xFFFFFFFF : (1 << (bit_index + 1)) - 1;
|
||||
var val = this.getBits(arr_index) & sigBits;
|
||||
if (val & (1 << bit_index)) {
|
||||
val |= 0xFFFFFFFF - sigBits;
|
||||
bits[arr_index] = val;
|
||||
return new goog.math.Integer(bits, -1);
|
||||
} else {
|
||||
bits[arr_index] = val;
|
||||
return new goog.math.Integer(bits, 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** @return {!goog.math.Integer} The negation of this value. */
|
||||
goog.math.Integer.prototype.negate = function() {
|
||||
return this.not().add(goog.math.Integer.ONE);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the sum of this and the given Integer.
|
||||
* @param {goog.math.Integer} other The Integer to add to this.
|
||||
* @return {!goog.math.Integer} The Integer result.
|
||||
*/
|
||||
goog.math.Integer.prototype.add = function(other) {
|
||||
var len = Math.max(this.bits_.length, other.bits_.length);
|
||||
var arr = [];
|
||||
var carry = 0;
|
||||
|
||||
for (var i = 0; i <= len; i++) {
|
||||
var a1 = this.getBits(i) >>> 16;
|
||||
var a0 = this.getBits(i) & 0xFFFF;
|
||||
|
||||
var b1 = other.getBits(i) >>> 16;
|
||||
var b0 = other.getBits(i) & 0xFFFF;
|
||||
|
||||
var c0 = carry + a0 + b0;
|
||||
var c1 = (c0 >>> 16) + a1 + b1;
|
||||
carry = c1 >>> 16;
|
||||
c0 &= 0xFFFF;
|
||||
c1 &= 0xFFFF;
|
||||
arr[i] = (c1 << 16) | c0;
|
||||
}
|
||||
return goog.math.Integer.fromBits(arr);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the difference of this and the given Integer.
|
||||
* @param {goog.math.Integer} other The Integer to subtract from this.
|
||||
* @return {!goog.math.Integer} The Integer result.
|
||||
*/
|
||||
goog.math.Integer.prototype.subtract = function(other) {
|
||||
return this.add(other.negate());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the product of this and the given Integer.
|
||||
* @param {goog.math.Integer} other The Integer to multiply against this.
|
||||
* @return {!goog.math.Integer} The product of this and the other.
|
||||
*/
|
||||
goog.math.Integer.prototype.multiply = function(other) {
|
||||
if (this.isZero()) {
|
||||
return goog.math.Integer.ZERO;
|
||||
} else if (other.isZero()) {
|
||||
return goog.math.Integer.ZERO;
|
||||
}
|
||||
|
||||
if (this.isNegative()) {
|
||||
if (other.isNegative()) {
|
||||
return this.negate().multiply(other.negate());
|
||||
} else {
|
||||
return this.negate().multiply(other).negate();
|
||||
}
|
||||
} else if (other.isNegative()) {
|
||||
return this.multiply(other.negate()).negate();
|
||||
}
|
||||
|
||||
// If both numbers are small, use float multiplication
|
||||
if (this.lessThan(goog.math.Integer.TWO_PWR_24_) &&
|
||||
other.lessThan(goog.math.Integer.TWO_PWR_24_)) {
|
||||
return goog.math.Integer.fromNumber(this.toNumber() * other.toNumber());
|
||||
}
|
||||
|
||||
// Fill in an array of 16-bit products.
|
||||
var len = this.bits_.length + other.bits_.length;
|
||||
var arr = [];
|
||||
for (var i = 0; i < 2 * len; i++) {
|
||||
arr[i] = 0;
|
||||
}
|
||||
for (var i = 0; i < this.bits_.length; i++) {
|
||||
for (var j = 0; j < other.bits_.length; j++) {
|
||||
var a1 = this.getBits(i) >>> 16;
|
||||
var a0 = this.getBits(i) & 0xFFFF;
|
||||
|
||||
var b1 = other.getBits(j) >>> 16;
|
||||
var b0 = other.getBits(j) & 0xFFFF;
|
||||
|
||||
arr[2 * i + 2 * j] += a0 * b0;
|
||||
goog.math.Integer.carry16_(arr, 2 * i + 2 * j);
|
||||
arr[2 * i + 2 * j + 1] += a1 * b0;
|
||||
goog.math.Integer.carry16_(arr, 2 * i + 2 * j + 1);
|
||||
arr[2 * i + 2 * j + 1] += a0 * b1;
|
||||
goog.math.Integer.carry16_(arr, 2 * i + 2 * j + 1);
|
||||
arr[2 * i + 2 * j + 2] += a1 * b1;
|
||||
goog.math.Integer.carry16_(arr, 2 * i + 2 * j + 2);
|
||||
}
|
||||
}
|
||||
|
||||
// Combine the 16-bit values into 32-bit values.
|
||||
for (var i = 0; i < len; i++) {
|
||||
arr[i] = (arr[2 * i + 1] << 16) | arr[2 * i];
|
||||
}
|
||||
for (var i = len; i < 2 * len; i++) {
|
||||
arr[i] = 0;
|
||||
}
|
||||
return new goog.math.Integer(arr, 0);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Carries any overflow from the given index into later entries.
|
||||
* @param {Array.<number>} bits Array of 16-bit values in little-endian order.
|
||||
* @param {number} index The index in question.
|
||||
* @private
|
||||
*/
|
||||
goog.math.Integer.carry16_ = function(bits, index) {
|
||||
while ((bits[index] & 0xFFFF) != bits[index]) {
|
||||
bits[index + 1] += bits[index] >>> 16;
|
||||
bits[index] &= 0xFFFF;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns this Integer divided by the given one.
|
||||
* @param {goog.math.Integer} other Th Integer to divide this by.
|
||||
* @return {!goog.math.Integer} This value divided by the given one.
|
||||
*/
|
||||
goog.math.Integer.prototype.divide = function(other) {
|
||||
if (other.isZero()) {
|
||||
throw Error('division by zero');
|
||||
} else if (this.isZero()) {
|
||||
return goog.math.Integer.ZERO;
|
||||
}
|
||||
|
||||
if (this.isNegative()) {
|
||||
if (other.isNegative()) {
|
||||
return this.negate().divide(other.negate());
|
||||
} else {
|
||||
return this.negate().divide(other).negate();
|
||||
}
|
||||
} else if (other.isNegative()) {
|
||||
return this.divide(other.negate()).negate();
|
||||
}
|
||||
|
||||
// Repeat the following until the remainder is less than other: find a
|
||||
// floating-point that approximates remainder / other *from below*, add this
|
||||
// into the result, and subtract it from the remainder. It is critical that
|
||||
// the approximate value is less than or equal to the real value so that the
|
||||
// remainder never becomes negative.
|
||||
var res = goog.math.Integer.ZERO;
|
||||
var rem = this;
|
||||
while (rem.greaterThanOrEqual(other)) {
|
||||
// Approximate the result of division. This may be a little greater or
|
||||
// smaller than the actual value.
|
||||
var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber()));
|
||||
|
||||
// We will tweak the approximate result by changing it in the 48-th digit or
|
||||
// the smallest non-fractional digit, whichever is larger.
|
||||
var log2 = Math.ceil(Math.log(approx) / Math.LN2);
|
||||
var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48);
|
||||
|
||||
// Decrease the approximation until it is smaller than the remainder. Note
|
||||
// that if it is too large, the product overflows and is negative.
|
||||
var approxRes = goog.math.Integer.fromNumber(approx);
|
||||
var approxRem = approxRes.multiply(other);
|
||||
while (approxRem.isNegative() || approxRem.greaterThan(rem)) {
|
||||
approx -= delta;
|
||||
approxRes = goog.math.Integer.fromNumber(approx);
|
||||
approxRem = approxRes.multiply(other);
|
||||
}
|
||||
|
||||
// We know the answer can't be zero... and actually, zero would cause
|
||||
// infinite recursion since we would make no progress.
|
||||
if (approxRes.isZero()) {
|
||||
approxRes = goog.math.Integer.ONE;
|
||||
}
|
||||
|
||||
res = res.add(approxRes);
|
||||
rem = rem.subtract(approxRem);
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns this Integer modulo the given one.
|
||||
* @param {goog.math.Integer} other The Integer by which to mod.
|
||||
* @return {!goog.math.Integer} This value modulo the given one.
|
||||
*/
|
||||
goog.math.Integer.prototype.modulo = function(other) {
|
||||
return this.subtract(this.divide(other).multiply(other));
|
||||
};
|
||||
|
||||
|
||||
/** @return {!goog.math.Integer} The bitwise-NOT of this value. */
|
||||
goog.math.Integer.prototype.not = function() {
|
||||
var len = this.bits_.length;
|
||||
var arr = [];
|
||||
for (var i = 0; i < len; i++) {
|
||||
arr[i] = ~this.bits_[i];
|
||||
}
|
||||
return new goog.math.Integer(arr, ~this.sign_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the bitwise-AND of this Integer and the given one.
|
||||
* @param {goog.math.Integer} other The Integer to AND with this.
|
||||
* @return {!goog.math.Integer} The bitwise-AND of this and the other.
|
||||
*/
|
||||
goog.math.Integer.prototype.and = function(other) {
|
||||
var len = Math.max(this.bits_.length, other.bits_.length);
|
||||
var arr = [];
|
||||
for (var i = 0; i < len; i++) {
|
||||
arr[i] = this.getBits(i) & other.getBits(i);
|
||||
}
|
||||
return new goog.math.Integer(arr, this.sign_ & other.sign_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the bitwise-OR of this Integer and the given one.
|
||||
* @param {goog.math.Integer} other The Integer to OR with this.
|
||||
* @return {!goog.math.Integer} The bitwise-OR of this and the other.
|
||||
*/
|
||||
goog.math.Integer.prototype.or = function(other) {
|
||||
var len = Math.max(this.bits_.length, other.bits_.length);
|
||||
var arr = [];
|
||||
for (var i = 0; i < len; i++) {
|
||||
arr[i] = this.getBits(i) | other.getBits(i);
|
||||
}
|
||||
return new goog.math.Integer(arr, this.sign_ | other.sign_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the bitwise-XOR of this Integer and the given one.
|
||||
* @param {goog.math.Integer} other The Integer to XOR with this.
|
||||
* @return {!goog.math.Integer} The bitwise-XOR of this and the other.
|
||||
*/
|
||||
goog.math.Integer.prototype.xor = function(other) {
|
||||
var len = Math.max(this.bits_.length, other.bits_.length);
|
||||
var arr = [];
|
||||
for (var i = 0; i < len; i++) {
|
||||
arr[i] = this.getBits(i) ^ other.getBits(i);
|
||||
}
|
||||
return new goog.math.Integer(arr, this.sign_ ^ other.sign_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns this value with bits shifted to the left by the given amount.
|
||||
* @param {number} numBits The number of bits by which to shift.
|
||||
* @return {!goog.math.Integer} This shifted to the left by the given amount.
|
||||
*/
|
||||
goog.math.Integer.prototype.shiftLeft = function(numBits) {
|
||||
var arr_delta = numBits >> 5;
|
||||
var bit_delta = numBits % 32;
|
||||
var len = this.bits_.length + arr_delta + (bit_delta > 0 ? 1 : 0);
|
||||
var arr = [];
|
||||
for (var i = 0; i < len; i++) {
|
||||
if (bit_delta > 0) {
|
||||
arr[i] = (this.getBits(i - arr_delta) << bit_delta) |
|
||||
(this.getBits(i - arr_delta - 1) >>> (32 - bit_delta));
|
||||
} else {
|
||||
arr[i] = this.getBits(i - arr_delta);
|
||||
}
|
||||
}
|
||||
return new goog.math.Integer(arr, this.sign_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns this value with bits shifted to the right by the given amount.
|
||||
* @param {number} numBits The number of bits by which to shift.
|
||||
* @return {!goog.math.Integer} This shifted to the right by the given amount.
|
||||
*/
|
||||
goog.math.Integer.prototype.shiftRight = function(numBits) {
|
||||
var arr_delta = numBits >> 5;
|
||||
var bit_delta = numBits % 32;
|
||||
var len = this.bits_.length - arr_delta;
|
||||
var arr = [];
|
||||
for (var i = 0; i < len; i++) {
|
||||
if (bit_delta > 0) {
|
||||
arr[i] = (this.getBits(i + arr_delta) >>> bit_delta) |
|
||||
(this.getBits(i + arr_delta + 1) << (32 - bit_delta));
|
||||
} else {
|
||||
arr[i] = this.getBits(i + arr_delta);
|
||||
}
|
||||
}
|
||||
return new goog.math.Integer(arr, this.sign_);
|
||||
};
|
||||
@@ -0,0 +1,64 @@
|
||||
// Copyright 2012 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/**
|
||||
* @fileoverview The base interface for one-dimensional data interpolation.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.math.interpolator.Interpolator1');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* An interface for one dimensional data interpolation.
|
||||
* @interface
|
||||
*/
|
||||
goog.math.interpolator.Interpolator1 = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the data to be interpolated. Note that the data points are expected
|
||||
* to be sorted according to their abscissa values and not have duplicate
|
||||
* values. E.g. calling setData([0, 0, 1], [1, 1, 3]) may give undefined
|
||||
* results, the correct call should be setData([0, 1], [1, 3]).
|
||||
* Calling setData multiple times does not merge the data samples. The last
|
||||
* call to setData is the one used when computing the interpolation.
|
||||
* @param {!Array.<number>} x The abscissa of the data points.
|
||||
* @param {!Array.<number>} y The ordinate of the data points.
|
||||
*/
|
||||
goog.math.interpolator.Interpolator1.prototype.setData;
|
||||
|
||||
|
||||
/**
|
||||
* Computes the interpolated value at abscissa x. If x is outside the range
|
||||
* of the data points passed in setData, the value is extrapolated.
|
||||
* @param {number} x The abscissa to sample at.
|
||||
* @return {number} The interpolated value at abscissa x.
|
||||
*/
|
||||
goog.math.interpolator.Interpolator1.prototype.interpolate;
|
||||
|
||||
|
||||
/**
|
||||
* Computes the inverse interpolator. That is, it returns invInterp s.t.
|
||||
* this.interpolate(invInterp.interpolate(t))) = t. Note that the inverse
|
||||
* interpolator is only well defined if the data being interpolated is
|
||||
* 'invertible', i.e. it represents a bijective function.
|
||||
* In addition, the returned interpolator is only guaranteed to give the exact
|
||||
* inverse at the input data passed in getData.
|
||||
* If 'this' has no data, the returned Interpolator will be empty as well.
|
||||
* @return {!goog.math.interpolator.Interpolator1} The inverse interpolator.
|
||||
*/
|
||||
goog.math.interpolator.Interpolator1.prototype.getInverse;
|
||||
@@ -0,0 +1,82 @@
|
||||
// Copyright 2012 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/**
|
||||
* @fileoverview A one dimensional linear interpolator.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.math.interpolator.Linear1');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.math');
|
||||
goog.require('goog.math.interpolator.Interpolator1');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A one dimensional linear interpolator.
|
||||
* @implements {goog.math.interpolator.Interpolator1}
|
||||
* @constructor
|
||||
*/
|
||||
goog.math.interpolator.Linear1 = function() {
|
||||
/**
|
||||
* The abscissa of the data points.
|
||||
* @type {!Array.<number>}
|
||||
* @private
|
||||
*/
|
||||
this.x_ = [];
|
||||
|
||||
/**
|
||||
* The ordinate of the data points.
|
||||
* @type {!Array.<number>}
|
||||
* @private
|
||||
*/
|
||||
this.y_ = [];
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.math.interpolator.Linear1.prototype.setData = function(x, y) {
|
||||
goog.asserts.assert(x.length == y.length,
|
||||
'input arrays to setData should have the same length');
|
||||
if (x.length == 1) {
|
||||
this.x_ = [x[0], x[0] + 1];
|
||||
this.y_ = [y[0], y[0]];
|
||||
} else {
|
||||
this.x_ = x.slice();
|
||||
this.y_ = y.slice();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.math.interpolator.Linear1.prototype.interpolate = function(x) {
|
||||
var pos = goog.array.binarySearch(this.x_, x);
|
||||
if (pos < 0) {
|
||||
pos = -pos - 2;
|
||||
}
|
||||
pos = goog.math.clamp(pos, 0, this.x_.length - 2);
|
||||
|
||||
var progress = (x - this.x_[pos]) / (this.x_[pos + 1] - this.x_[pos]);
|
||||
return goog.math.lerp(this.y_[pos], this.y_[pos + 1], progress);
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.math.interpolator.Linear1.prototype.getInverse = function() {
|
||||
var interpolator = new goog.math.interpolator.Linear1();
|
||||
interpolator.setData(this.y_, this.x_);
|
||||
return interpolator;
|
||||
};
|
||||
@@ -0,0 +1,81 @@
|
||||
// Copyright 2012 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/**
|
||||
* @fileoverview A one dimensional monotone cubic spline interpolator.
|
||||
*
|
||||
* See http://en.wikipedia.org/wiki/Monotone_cubic_interpolation.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.math.interpolator.Pchip1');
|
||||
|
||||
goog.require('goog.math');
|
||||
goog.require('goog.math.interpolator.Spline1');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A one dimensional monotone cubic spline interpolator.
|
||||
* @extends {goog.math.interpolator.Spline1}
|
||||
* @constructor
|
||||
*/
|
||||
goog.math.interpolator.Pchip1 = function() {
|
||||
goog.base(this);
|
||||
};
|
||||
goog.inherits(goog.math.interpolator.Pchip1, goog.math.interpolator.Spline1);
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.math.interpolator.Pchip1.prototype.computeDerivatives = function(
|
||||
dx, slope) {
|
||||
var len = dx.length;
|
||||
var deriv = new Array(len + 1);
|
||||
for (var i = 1; i < len; ++i) {
|
||||
if (goog.math.sign(slope[i - 1]) * goog.math.sign(slope[i]) <= 0) {
|
||||
deriv[i] = 0;
|
||||
} else {
|
||||
var w1 = 2 * dx[i] + dx[i - 1];
|
||||
var w2 = dx[i] + 2 * dx[i - 1];
|
||||
deriv[i] = (w1 + w2) / (w1 / slope[i - 1] + w2 / slope[i]);
|
||||
}
|
||||
}
|
||||
deriv[0] = this.computeDerivativeAtBoundary_(
|
||||
dx[0], dx[1], slope[0], slope[1]);
|
||||
deriv[len] = this.computeDerivativeAtBoundary_(
|
||||
dx[len - 1], dx[len - 2], slope[len - 1], slope[len - 2]);
|
||||
return deriv;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Computes the derivative of a data point at a boundary.
|
||||
* @param {number} dx0 The spacing of the 1st data point.
|
||||
* @param {number} dx1 The spacing of the 2nd data point.
|
||||
* @param {number} slope0 The slope of the 1st data point.
|
||||
* @param {number} slope1 The slope of the 2nd data point.
|
||||
* @return {number} The derivative at the 1st data point.
|
||||
* @private
|
||||
*/
|
||||
goog.math.interpolator.Pchip1.prototype.computeDerivativeAtBoundary_ = function(
|
||||
dx0, dx1, slope0, slope1) {
|
||||
var deriv = ((2 * dx0 + dx1) * slope0 - dx0 * slope1) / (dx0 + dx1);
|
||||
if (goog.math.sign(deriv) != goog.math.sign(slope0)) {
|
||||
deriv = 0;
|
||||
} else if (goog.math.sign(slope0) != goog.math.sign(slope1) &&
|
||||
Math.abs(deriv) > Math.abs(3 * slope0)) {
|
||||
deriv = 3 * slope0;
|
||||
}
|
||||
return deriv;
|
||||
};
|
||||
@@ -0,0 +1,202 @@
|
||||
// Copyright 2012 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/**
|
||||
* @fileoverview A one dimensional cubic spline interpolator with not-a-knot
|
||||
* boundary conditions.
|
||||
*
|
||||
* See http://en.wikipedia.org/wiki/Spline_interpolation.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.math.interpolator.Spline1');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.math');
|
||||
goog.require('goog.math.interpolator.Interpolator1');
|
||||
goog.require('goog.math.tdma');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A one dimensional cubic spline interpolator with natural boundary conditions.
|
||||
* @implements {goog.math.interpolator.Interpolator1}
|
||||
* @constructor
|
||||
*/
|
||||
goog.math.interpolator.Spline1 = function() {
|
||||
/**
|
||||
* The abscissa of the data points.
|
||||
* @type {!Array.<number>}
|
||||
* @private
|
||||
*/
|
||||
this.x_ = [];
|
||||
|
||||
/**
|
||||
* The spline interval coefficients.
|
||||
* Note that, in general, the length of coeffs and x is not the same.
|
||||
* @type {!Array.<!Array.<number>>}
|
||||
* @private
|
||||
*/
|
||||
this.coeffs_ = [[0, 0, 0, Number.NaN]];
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.math.interpolator.Spline1.prototype.setData = function(x, y) {
|
||||
goog.asserts.assert(x.length == y.length,
|
||||
'input arrays to setData should have the same length');
|
||||
if (x.length > 0) {
|
||||
this.coeffs_ = this.computeSplineCoeffs_(x, y);
|
||||
this.x_ = x.slice();
|
||||
} else {
|
||||
this.coeffs_ = [[0, 0, 0, Number.NaN]];
|
||||
this.x_ = [];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** @override */
|
||||
goog.math.interpolator.Spline1.prototype.interpolate = function(x) {
|
||||
var pos = goog.array.binarySearch(this.x_, x);
|
||||
if (pos < 0) {
|
||||
pos = -pos - 2;
|
||||
}
|
||||
pos = goog.math.clamp(pos, 0, this.coeffs_.length - 1);
|
||||
|
||||
var d = x - this.x_[pos];
|
||||
var d2 = d * d;
|
||||
var d3 = d2 * d;
|
||||
var coeffs = this.coeffs_[pos];
|
||||
return coeffs[0] * d3 + coeffs[1] * d2 + coeffs[2] * d + coeffs[3];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Solve for the spline coefficients such that the spline precisely interpolates
|
||||
* the data points.
|
||||
* @param {Array.<number>} x The abscissa of the spline data points.
|
||||
* @param {Array.<number>} y The ordinate of the spline data points.
|
||||
* @return {!Array.<!Array.<number>>} The spline interval coefficients.
|
||||
* @private
|
||||
*/
|
||||
goog.math.interpolator.Spline1.prototype.computeSplineCoeffs_ = function(x, y) {
|
||||
var nIntervals = x.length - 1;
|
||||
var dx = new Array(nIntervals);
|
||||
var delta = new Array(nIntervals);
|
||||
for (var i = 0; i < nIntervals; ++i) {
|
||||
dx[i] = x[i + 1] - x[i];
|
||||
delta[i] = (y[i + 1] - y[i]) / dx[i];
|
||||
}
|
||||
|
||||
// Compute the spline coefficients from the 1st order derivatives.
|
||||
var coeffs = [];
|
||||
if (nIntervals == 0) {
|
||||
// Nearest neighbor interpolation.
|
||||
coeffs[0] = [0, 0, 0, y[0]];
|
||||
} else if (nIntervals == 1) {
|
||||
// Straight line interpolation.
|
||||
coeffs[0] = [0, 0, delta[0], y[0]];
|
||||
} else if (nIntervals == 2) {
|
||||
// Parabola interpolation.
|
||||
var c3 = 0;
|
||||
var c2 = (delta[1] - delta[0]) / (dx[0] + dx[1]);
|
||||
var c1 = delta[0] - c2 * dx[0];
|
||||
var c0 = y[0];
|
||||
coeffs[0] = [c3, c2, c1, c0];
|
||||
} else {
|
||||
// General Spline interpolation. Compute the 1st order derivatives from
|
||||
// the Spline equations.
|
||||
var deriv = this.computeDerivatives(dx, delta);
|
||||
for (var i = 0; i < nIntervals; ++i) {
|
||||
var c3 = (deriv[i] - 2 * delta[i] + deriv[i + 1]) / (dx[i] * dx[i]);
|
||||
var c2 = (3 * delta[i] - 2 * deriv[i] - deriv[i + 1]) / dx[i];
|
||||
var c1 = deriv[i];
|
||||
var c0 = y[i];
|
||||
coeffs[i] = [c3, c2, c1, c0];
|
||||
}
|
||||
}
|
||||
return coeffs;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Computes the derivative at each point of the spline such that
|
||||
* the curve is C2. It uses not-a-knot boundary conditions.
|
||||
* @param {Array.<number>} dx The spacing between consecutive data points.
|
||||
* @param {Array.<number>} slope The slopes between consecutive data points.
|
||||
* @return {Array.<number>} The Spline derivative at each data point.
|
||||
* @protected
|
||||
*/
|
||||
goog.math.interpolator.Spline1.prototype.computeDerivatives = function(
|
||||
dx, slope) {
|
||||
var nIntervals = dx.length;
|
||||
|
||||
// Compute the main diagonal of the system of equations.
|
||||
var mainDiag = new Array(nIntervals + 1);
|
||||
mainDiag[0] = dx[1];
|
||||
for (var i = 1; i < nIntervals; ++i) {
|
||||
mainDiag[i] = 2 * (dx[i] + dx[i - 1]);
|
||||
}
|
||||
mainDiag[nIntervals] = dx[nIntervals - 2];
|
||||
|
||||
// Compute the sub diagonal of the system of equations.
|
||||
var subDiag = new Array(nIntervals);
|
||||
for (var i = 0; i < nIntervals; ++i) {
|
||||
subDiag[i] = dx[i + 1];
|
||||
}
|
||||
subDiag[nIntervals - 1] = dx[nIntervals - 2] + dx[nIntervals - 1];
|
||||
|
||||
// Compute the super diagonal of the system of equations.
|
||||
var supDiag = new Array(nIntervals);
|
||||
supDiag[0] = dx[0] + dx[1];
|
||||
for (var i = 1; i < nIntervals; ++i) {
|
||||
supDiag[i] = dx[i - 1];
|
||||
}
|
||||
|
||||
// Compute the right vector of the system of equations.
|
||||
var vecRight = new Array(nIntervals + 1);
|
||||
vecRight[0] = ((dx[0] + 2 * supDiag[0]) * dx[1] * slope[0] +
|
||||
dx[0] * dx[0] * slope[1]) / supDiag[0];
|
||||
for (var i = 1; i < nIntervals; ++i) {
|
||||
vecRight[i] = 3 * (dx[i] * slope[i - 1] + dx[i - 1] * slope[i]);
|
||||
}
|
||||
vecRight[nIntervals] = (dx[nIntervals - 1] * dx[nIntervals - 1] *
|
||||
slope[nIntervals - 2] + (2 * subDiag[nIntervals - 1] +
|
||||
dx[nIntervals - 1]) * dx[nIntervals - 2] * slope[nIntervals - 1]) /
|
||||
subDiag[nIntervals - 1];
|
||||
|
||||
// Solve the system of equations.
|
||||
var deriv = goog.math.tdma.solve(
|
||||
subDiag, mainDiag, supDiag, vecRight);
|
||||
|
||||
return deriv;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Note that the inverse of a cubic spline is not a cubic spline in general.
|
||||
* As a result the inverse implementation is only approximate. In
|
||||
* particular, it only guarantees the exact inverse at the original input data
|
||||
* points passed to setData.
|
||||
* @override
|
||||
*/
|
||||
goog.math.interpolator.Spline1.prototype.getInverse = function() {
|
||||
var interpolator = new goog.math.interpolator.Spline1();
|
||||
var y = [];
|
||||
for (var i = 0; i < this.x_.length; i++) {
|
||||
y[i] = this.interpolate(this.x_[i]);
|
||||
}
|
||||
interpolator.setData(y, this.x_);
|
||||
return interpolator;
|
||||
};
|
||||
177
nicer-api-docs/closure-library/closure/goog/math/line.js
Normal file
177
nicer-api-docs/closure-library/closure/goog/math/line.js
Normal file
@@ -0,0 +1,177 @@
|
||||
// Copyright 2008 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
/**
|
||||
* @fileoverview Represents a line in 2D space.
|
||||
*
|
||||
* @author robbyw@google.com (Robby Walker)
|
||||
*/
|
||||
|
||||
goog.provide('goog.math.Line');
|
||||
|
||||
goog.require('goog.math');
|
||||
goog.require('goog.math.Coordinate');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Object representing a line.
|
||||
* @param {number} x0 X coordinate of the start point.
|
||||
* @param {number} y0 Y coordinate of the start point.
|
||||
* @param {number} x1 X coordinate of the end point.
|
||||
* @param {number} y1 Y coordinate of the end point.
|
||||
* @constructor
|
||||
*/
|
||||
goog.math.Line = function(x0, y0, x1, y1) {
|
||||
/**
|
||||
* X coordinate of the first point.
|
||||
* @type {number}
|
||||
*/
|
||||
this.x0 = x0;
|
||||
|
||||
/**
|
||||
* Y coordinate of the first point.
|
||||
* @type {number}
|
||||
*/
|
||||
this.y0 = y0;
|
||||
|
||||
/**
|
||||
* X coordinate of the first control point.
|
||||
* @type {number}
|
||||
*/
|
||||
this.x1 = x1;
|
||||
|
||||
/**
|
||||
* Y coordinate of the first control point.
|
||||
* @type {number}
|
||||
*/
|
||||
this.y1 = y1;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!goog.math.Line} A copy of this line.
|
||||
*/
|
||||
goog.math.Line.prototype.clone = function() {
|
||||
return new goog.math.Line(this.x0, this.y0, this.x1, this.y1);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Tests whether the given line is exactly the same as this one.
|
||||
* @param {goog.math.Line} other The other line.
|
||||
* @return {boolean} Whether the given line is the same as this one.
|
||||
*/
|
||||
goog.math.Line.prototype.equals = function(other) {
|
||||
return this.x0 == other.x0 && this.y0 == other.y0 &&
|
||||
this.x1 == other.x1 && this.y1 == other.y1;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} The squared length of the line segment used to define the
|
||||
* line.
|
||||
*/
|
||||
goog.math.Line.prototype.getSegmentLengthSquared = function() {
|
||||
var xdist = this.x1 - this.x0;
|
||||
var ydist = this.y1 - this.y0;
|
||||
return xdist * xdist + ydist * ydist;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} The length of the line segment used to define the line.
|
||||
*/
|
||||
goog.math.Line.prototype.getSegmentLength = function() {
|
||||
return Math.sqrt(this.getSegmentLengthSquared());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Computes the interpolation parameter for the point on the line closest to
|
||||
* a given point.
|
||||
* @param {number|goog.math.Coordinate} x The x coordinate of the point, or
|
||||
* a coordinate object.
|
||||
* @param {number=} opt_y The y coordinate of the point - required if x is a
|
||||
* number, ignored if x is a goog.math.Coordinate.
|
||||
* @return {number} The interpolation parameter of the point on the line
|
||||
* closest to the given point.
|
||||
* @private
|
||||
*/
|
||||
goog.math.Line.prototype.getClosestLinearInterpolation_ = function(x, opt_y) {
|
||||
var y;
|
||||
if (x instanceof goog.math.Coordinate) {
|
||||
y = x.y;
|
||||
x = x.x;
|
||||
} else {
|
||||
y = opt_y;
|
||||
}
|
||||
|
||||
var x0 = this.x0;
|
||||
var y0 = this.y0;
|
||||
|
||||
var xChange = this.x1 - x0;
|
||||
var yChange = this.y1 - y0;
|
||||
|
||||
return ((x - x0) * xChange + (y - y0) * yChange) /
|
||||
this.getSegmentLengthSquared();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the point on the line segment proportional to t, where for t = 0 we
|
||||
* return the starting point and for t = 1 we return the end point. For t < 0
|
||||
* or t > 1 we extrapolate along the line defined by the line segment.
|
||||
* @param {number} t The interpolation parameter along the line segment.
|
||||
* @return {!goog.math.Coordinate} The point on the line segment at t.
|
||||
*/
|
||||
goog.math.Line.prototype.getInterpolatedPoint = function(t) {
|
||||
return new goog.math.Coordinate(
|
||||
goog.math.lerp(this.x0, this.x1, t),
|
||||
goog.math.lerp(this.y0, this.y1, t));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Computes the point on the line closest to a given point. Note that a line
|
||||
* in this case is defined as the infinite line going through the start and end
|
||||
* points. To find the closest point on the line segment itself see
|
||||
* {@see #getClosestSegmentPoint}.
|
||||
* @param {number|goog.math.Coordinate} x The x coordinate of the point, or
|
||||
* a coordinate object.
|
||||
* @param {number=} opt_y The y coordinate of the point - required if x is a
|
||||
* number, ignored if x is a goog.math.Coordinate.
|
||||
* @return {!goog.math.Coordinate} The point on the line closest to the given
|
||||
* point.
|
||||
*/
|
||||
goog.math.Line.prototype.getClosestPoint = function(x, opt_y) {
|
||||
return this.getInterpolatedPoint(
|
||||
this.getClosestLinearInterpolation_(x, opt_y));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Computes the point on the line segment closest to a given point.
|
||||
* @param {number|goog.math.Coordinate} x The x coordinate of the point, or
|
||||
* a coordinate object.
|
||||
* @param {number=} opt_y The y coordinate of the point - required if x is a
|
||||
* number, ignored if x is a goog.math.Coordinate.
|
||||
* @return {!goog.math.Coordinate} The point on the line segment closest to the
|
||||
* given point.
|
||||
*/
|
||||
goog.math.Line.prototype.getClosestSegmentPoint = function(x, opt_y) {
|
||||
return this.getInterpolatedPoint(
|
||||
goog.math.clamp(this.getClosestLinearInterpolation_(x, opt_y), 0, 1));
|
||||
};
|
||||
802
nicer-api-docs/closure-library/closure/goog/math/long.js
Normal file
802
nicer-api-docs/closure-library/closure/goog/math/long.js
Normal file
@@ -0,0 +1,802 @@
|
||||
// Copyright 2009 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/**
|
||||
* @fileoverview Defines a Long class for representing a 64-bit two's-complement
|
||||
* integer value, which faithfully simulates the behavior of a Java "long". This
|
||||
* implementation is derived from LongLib in GWT.
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.math.Long');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a 64-bit two's-complement integer, given its low and high 32-bit
|
||||
* values as *signed* integers. See the from* functions below for more
|
||||
* convenient ways of constructing Longs.
|
||||
*
|
||||
* The internal representation of a long is the two given signed, 32-bit values.
|
||||
* We use 32-bit pieces because these are the size of integers on which
|
||||
* Javascript performs bit-operations. For operations like addition and
|
||||
* multiplication, we split each number into 16-bit pieces, which can easily be
|
||||
* multiplied within Javascript's floating-point representation without overflow
|
||||
* or change in sign.
|
||||
*
|
||||
* In the algorithms below, we frequently reduce the negative case to the
|
||||
* positive case by negating the input(s) and then post-processing the result.
|
||||
* Note that we must ALWAYS check specially whether those values are MIN_VALUE
|
||||
* (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as
|
||||
* a positive number, it overflows back into a negative). Not handling this
|
||||
* case would often result in infinite recursion.
|
||||
*
|
||||
* @param {number} low The low (signed) 32 bits of the long.
|
||||
* @param {number} high The high (signed) 32 bits of the long.
|
||||
* @constructor
|
||||
*/
|
||||
goog.math.Long = function(low, high) {
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.low_ = low | 0; // force into 32 signed bits.
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this.high_ = high | 0; // force into 32 signed bits.
|
||||
};
|
||||
|
||||
|
||||
// NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the
|
||||
// from* methods on which they depend.
|
||||
|
||||
|
||||
/**
|
||||
* A cache of the Long representations of small integer values.
|
||||
* @type {!Object}
|
||||
* @private
|
||||
*/
|
||||
goog.math.Long.IntCache_ = {};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a Long representing the given (32-bit) integer value.
|
||||
* @param {number} value The 32-bit integer in question.
|
||||
* @return {!goog.math.Long} The corresponding Long value.
|
||||
*/
|
||||
goog.math.Long.fromInt = function(value) {
|
||||
if (-128 <= value && value < 128) {
|
||||
var cachedObj = goog.math.Long.IntCache_[value];
|
||||
if (cachedObj) {
|
||||
return cachedObj;
|
||||
}
|
||||
}
|
||||
|
||||
var obj = new goog.math.Long(value | 0, value < 0 ? -1 : 0);
|
||||
if (-128 <= value && value < 128) {
|
||||
goog.math.Long.IntCache_[value] = obj;
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a Long representing the given value, provided that it is a finite
|
||||
* number. Otherwise, zero is returned.
|
||||
* @param {number} value The number in question.
|
||||
* @return {!goog.math.Long} The corresponding Long value.
|
||||
*/
|
||||
goog.math.Long.fromNumber = function(value) {
|
||||
if (isNaN(value) || !isFinite(value)) {
|
||||
return goog.math.Long.ZERO;
|
||||
} else if (value <= -goog.math.Long.TWO_PWR_63_DBL_) {
|
||||
return goog.math.Long.MIN_VALUE;
|
||||
} else if (value + 1 >= goog.math.Long.TWO_PWR_63_DBL_) {
|
||||
return goog.math.Long.MAX_VALUE;
|
||||
} else if (value < 0) {
|
||||
return goog.math.Long.fromNumber(-value).negate();
|
||||
} else {
|
||||
return new goog.math.Long(
|
||||
(value % goog.math.Long.TWO_PWR_32_DBL_) | 0,
|
||||
(value / goog.math.Long.TWO_PWR_32_DBL_) | 0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a Long representing the 64-bit integer that comes by concatenating
|
||||
* the given high and low bits. Each is assumed to use 32 bits.
|
||||
* @param {number} lowBits The low 32-bits.
|
||||
* @param {number} highBits The high 32-bits.
|
||||
* @return {!goog.math.Long} The corresponding Long value.
|
||||
*/
|
||||
goog.math.Long.fromBits = function(lowBits, highBits) {
|
||||
return new goog.math.Long(lowBits, highBits);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a Long representation of the given string, written using the given
|
||||
* radix.
|
||||
* @param {string} str The textual representation of the Long.
|
||||
* @param {number=} opt_radix The radix in which the text is written.
|
||||
* @return {!goog.math.Long} The corresponding Long value.
|
||||
*/
|
||||
goog.math.Long.fromString = function(str, opt_radix) {
|
||||
if (str.length == 0) {
|
||||
throw Error('number format error: empty string');
|
||||
}
|
||||
|
||||
var radix = opt_radix || 10;
|
||||
if (radix < 2 || 36 < radix) {
|
||||
throw Error('radix out of range: ' + radix);
|
||||
}
|
||||
|
||||
if (str.charAt(0) == '-') {
|
||||
return goog.math.Long.fromString(str.substring(1), radix).negate();
|
||||
} else if (str.indexOf('-') >= 0) {
|
||||
throw Error('number format error: interior "-" character: ' + str);
|
||||
}
|
||||
|
||||
// Do several (8) digits each time through the loop, so as to
|
||||
// minimize the calls to the very expensive emulated div.
|
||||
var radixToPower = goog.math.Long.fromNumber(Math.pow(radix, 8));
|
||||
|
||||
var result = goog.math.Long.ZERO;
|
||||
for (var i = 0; i < str.length; i += 8) {
|
||||
var size = Math.min(8, str.length - i);
|
||||
var value = parseInt(str.substring(i, i + size), radix);
|
||||
if (size < 8) {
|
||||
var power = goog.math.Long.fromNumber(Math.pow(radix, size));
|
||||
result = result.multiply(power).add(goog.math.Long.fromNumber(value));
|
||||
} else {
|
||||
result = result.multiply(radixToPower);
|
||||
result = result.add(goog.math.Long.fromNumber(value));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
// NOTE: the compiler should inline these constant values below and then remove
|
||||
// these variables, so there should be no runtime penalty for these.
|
||||
|
||||
|
||||
/**
|
||||
* Number used repeated below in calculations. This must appear before the
|
||||
* first call to any from* function below.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.math.Long.TWO_PWR_16_DBL_ = 1 << 16;
|
||||
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.math.Long.TWO_PWR_24_DBL_ = 1 << 24;
|
||||
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.math.Long.TWO_PWR_32_DBL_ =
|
||||
goog.math.Long.TWO_PWR_16_DBL_ * goog.math.Long.TWO_PWR_16_DBL_;
|
||||
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.math.Long.TWO_PWR_31_DBL_ =
|
||||
goog.math.Long.TWO_PWR_32_DBL_ / 2;
|
||||
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.math.Long.TWO_PWR_48_DBL_ =
|
||||
goog.math.Long.TWO_PWR_32_DBL_ * goog.math.Long.TWO_PWR_16_DBL_;
|
||||
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.math.Long.TWO_PWR_64_DBL_ =
|
||||
goog.math.Long.TWO_PWR_32_DBL_ * goog.math.Long.TWO_PWR_32_DBL_;
|
||||
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
goog.math.Long.TWO_PWR_63_DBL_ =
|
||||
goog.math.Long.TWO_PWR_64_DBL_ / 2;
|
||||
|
||||
|
||||
/** @type {!goog.math.Long} */
|
||||
goog.math.Long.ZERO = goog.math.Long.fromInt(0);
|
||||
|
||||
|
||||
/** @type {!goog.math.Long} */
|
||||
goog.math.Long.ONE = goog.math.Long.fromInt(1);
|
||||
|
||||
|
||||
/** @type {!goog.math.Long} */
|
||||
goog.math.Long.NEG_ONE = goog.math.Long.fromInt(-1);
|
||||
|
||||
|
||||
/** @type {!goog.math.Long} */
|
||||
goog.math.Long.MAX_VALUE =
|
||||
goog.math.Long.fromBits(0xFFFFFFFF | 0, 0x7FFFFFFF | 0);
|
||||
|
||||
|
||||
/** @type {!goog.math.Long} */
|
||||
goog.math.Long.MIN_VALUE = goog.math.Long.fromBits(0, 0x80000000 | 0);
|
||||
|
||||
|
||||
/**
|
||||
* @type {!goog.math.Long}
|
||||
* @private
|
||||
*/
|
||||
goog.math.Long.TWO_PWR_24_ = goog.math.Long.fromInt(1 << 24);
|
||||
|
||||
|
||||
/** @return {number} The value, assuming it is a 32-bit integer. */
|
||||
goog.math.Long.prototype.toInt = function() {
|
||||
return this.low_;
|
||||
};
|
||||
|
||||
|
||||
/** @return {number} The closest floating-point representation to this value. */
|
||||
goog.math.Long.prototype.toNumber = function() {
|
||||
return this.high_ * goog.math.Long.TWO_PWR_32_DBL_ +
|
||||
this.getLowBitsUnsigned();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {number=} opt_radix The radix in which the text should be written.
|
||||
* @return {string} The textual representation of this value.
|
||||
* @override
|
||||
*/
|
||||
goog.math.Long.prototype.toString = function(opt_radix) {
|
||||
var radix = opt_radix || 10;
|
||||
if (radix < 2 || 36 < radix) {
|
||||
throw Error('radix out of range: ' + radix);
|
||||
}
|
||||
|
||||
if (this.isZero()) {
|
||||
return '0';
|
||||
}
|
||||
|
||||
if (this.isNegative()) {
|
||||
if (this.equals(goog.math.Long.MIN_VALUE)) {
|
||||
// We need to change the Long value before it can be negated, so we remove
|
||||
// the bottom-most digit in this base and then recurse to do the rest.
|
||||
var radixLong = goog.math.Long.fromNumber(radix);
|
||||
var div = this.div(radixLong);
|
||||
var rem = div.multiply(radixLong).subtract(this);
|
||||
return div.toString(radix) + rem.toInt().toString(radix);
|
||||
} else {
|
||||
return '-' + this.negate().toString(radix);
|
||||
}
|
||||
}
|
||||
|
||||
// Do several (6) digits each time through the loop, so as to
|
||||
// minimize the calls to the very expensive emulated div.
|
||||
var radixToPower = goog.math.Long.fromNumber(Math.pow(radix, 6));
|
||||
|
||||
var rem = this;
|
||||
var result = '';
|
||||
while (true) {
|
||||
var remDiv = rem.div(radixToPower);
|
||||
var intval = rem.subtract(remDiv.multiply(radixToPower)).toInt();
|
||||
var digits = intval.toString(radix);
|
||||
|
||||
rem = remDiv;
|
||||
if (rem.isZero()) {
|
||||
return digits + result;
|
||||
} else {
|
||||
while (digits.length < 6) {
|
||||
digits = '0' + digits;
|
||||
}
|
||||
result = '' + digits + result;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** @return {number} The high 32-bits as a signed value. */
|
||||
goog.math.Long.prototype.getHighBits = function() {
|
||||
return this.high_;
|
||||
};
|
||||
|
||||
|
||||
/** @return {number} The low 32-bits as a signed value. */
|
||||
goog.math.Long.prototype.getLowBits = function() {
|
||||
return this.low_;
|
||||
};
|
||||
|
||||
|
||||
/** @return {number} The low 32-bits as an unsigned value. */
|
||||
goog.math.Long.prototype.getLowBitsUnsigned = function() {
|
||||
return (this.low_ >= 0) ?
|
||||
this.low_ : goog.math.Long.TWO_PWR_32_DBL_ + this.low_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} Returns the number of bits needed to represent the absolute
|
||||
* value of this Long.
|
||||
*/
|
||||
goog.math.Long.prototype.getNumBitsAbs = function() {
|
||||
if (this.isNegative()) {
|
||||
if (this.equals(goog.math.Long.MIN_VALUE)) {
|
||||
return 64;
|
||||
} else {
|
||||
return this.negate().getNumBitsAbs();
|
||||
}
|
||||
} else {
|
||||
var val = this.high_ != 0 ? this.high_ : this.low_;
|
||||
for (var bit = 31; bit > 0; bit--) {
|
||||
if ((val & (1 << bit)) != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return this.high_ != 0 ? bit + 33 : bit + 1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** @return {boolean} Whether this value is zero. */
|
||||
goog.math.Long.prototype.isZero = function() {
|
||||
return this.high_ == 0 && this.low_ == 0;
|
||||
};
|
||||
|
||||
|
||||
/** @return {boolean} Whether this value is negative. */
|
||||
goog.math.Long.prototype.isNegative = function() {
|
||||
return this.high_ < 0;
|
||||
};
|
||||
|
||||
|
||||
/** @return {boolean} Whether this value is odd. */
|
||||
goog.math.Long.prototype.isOdd = function() {
|
||||
return (this.low_ & 1) == 1;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.math.Long} other Long to compare against.
|
||||
* @return {boolean} Whether this Long equals the other.
|
||||
*/
|
||||
goog.math.Long.prototype.equals = function(other) {
|
||||
return (this.high_ == other.high_) && (this.low_ == other.low_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.math.Long} other Long to compare against.
|
||||
* @return {boolean} Whether this Long does not equal the other.
|
||||
*/
|
||||
goog.math.Long.prototype.notEquals = function(other) {
|
||||
return (this.high_ != other.high_) || (this.low_ != other.low_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.math.Long} other Long to compare against.
|
||||
* @return {boolean} Whether this Long is less than the other.
|
||||
*/
|
||||
goog.math.Long.prototype.lessThan = function(other) {
|
||||
return this.compare(other) < 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.math.Long} other Long to compare against.
|
||||
* @return {boolean} Whether this Long is less than or equal to the other.
|
||||
*/
|
||||
goog.math.Long.prototype.lessThanOrEqual = function(other) {
|
||||
return this.compare(other) <= 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.math.Long} other Long to compare against.
|
||||
* @return {boolean} Whether this Long is greater than the other.
|
||||
*/
|
||||
goog.math.Long.prototype.greaterThan = function(other) {
|
||||
return this.compare(other) > 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {goog.math.Long} other Long to compare against.
|
||||
* @return {boolean} Whether this Long is greater than or equal to the other.
|
||||
*/
|
||||
goog.math.Long.prototype.greaterThanOrEqual = function(other) {
|
||||
return this.compare(other) >= 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Compares this Long with the given one.
|
||||
* @param {goog.math.Long} other Long to compare against.
|
||||
* @return {number} 0 if they are the same, 1 if the this is greater, and -1
|
||||
* if the given one is greater.
|
||||
*/
|
||||
goog.math.Long.prototype.compare = function(other) {
|
||||
if (this.equals(other)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var thisNeg = this.isNegative();
|
||||
var otherNeg = other.isNegative();
|
||||
if (thisNeg && !otherNeg) {
|
||||
return -1;
|
||||
}
|
||||
if (!thisNeg && otherNeg) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// at this point, the signs are the same, so subtraction will not overflow
|
||||
if (this.subtract(other).isNegative()) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** @return {!goog.math.Long} The negation of this value. */
|
||||
goog.math.Long.prototype.negate = function() {
|
||||
if (this.equals(goog.math.Long.MIN_VALUE)) {
|
||||
return goog.math.Long.MIN_VALUE;
|
||||
} else {
|
||||
return this.not().add(goog.math.Long.ONE);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the sum of this and the given Long.
|
||||
* @param {goog.math.Long} other Long to add to this one.
|
||||
* @return {!goog.math.Long} The sum of this and the given Long.
|
||||
*/
|
||||
goog.math.Long.prototype.add = function(other) {
|
||||
// Divide each number into 4 chunks of 16 bits, and then sum the chunks.
|
||||
|
||||
var a48 = this.high_ >>> 16;
|
||||
var a32 = this.high_ & 0xFFFF;
|
||||
var a16 = this.low_ >>> 16;
|
||||
var a00 = this.low_ & 0xFFFF;
|
||||
|
||||
var b48 = other.high_ >>> 16;
|
||||
var b32 = other.high_ & 0xFFFF;
|
||||
var b16 = other.low_ >>> 16;
|
||||
var b00 = other.low_ & 0xFFFF;
|
||||
|
||||
var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
|
||||
c00 += a00 + b00;
|
||||
c16 += c00 >>> 16;
|
||||
c00 &= 0xFFFF;
|
||||
c16 += a16 + b16;
|
||||
c32 += c16 >>> 16;
|
||||
c16 &= 0xFFFF;
|
||||
c32 += a32 + b32;
|
||||
c48 += c32 >>> 16;
|
||||
c32 &= 0xFFFF;
|
||||
c48 += a48 + b48;
|
||||
c48 &= 0xFFFF;
|
||||
return goog.math.Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the difference of this and the given Long.
|
||||
* @param {goog.math.Long} other Long to subtract from this.
|
||||
* @return {!goog.math.Long} The difference of this and the given Long.
|
||||
*/
|
||||
goog.math.Long.prototype.subtract = function(other) {
|
||||
return this.add(other.negate());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the product of this and the given long.
|
||||
* @param {goog.math.Long} other Long to multiply with this.
|
||||
* @return {!goog.math.Long} The product of this and the other.
|
||||
*/
|
||||
goog.math.Long.prototype.multiply = function(other) {
|
||||
if (this.isZero()) {
|
||||
return goog.math.Long.ZERO;
|
||||
} else if (other.isZero()) {
|
||||
return goog.math.Long.ZERO;
|
||||
}
|
||||
|
||||
if (this.equals(goog.math.Long.MIN_VALUE)) {
|
||||
return other.isOdd() ? goog.math.Long.MIN_VALUE : goog.math.Long.ZERO;
|
||||
} else if (other.equals(goog.math.Long.MIN_VALUE)) {
|
||||
return this.isOdd() ? goog.math.Long.MIN_VALUE : goog.math.Long.ZERO;
|
||||
}
|
||||
|
||||
if (this.isNegative()) {
|
||||
if (other.isNegative()) {
|
||||
return this.negate().multiply(other.negate());
|
||||
} else {
|
||||
return this.negate().multiply(other).negate();
|
||||
}
|
||||
} else if (other.isNegative()) {
|
||||
return this.multiply(other.negate()).negate();
|
||||
}
|
||||
|
||||
// If both longs are small, use float multiplication
|
||||
if (this.lessThan(goog.math.Long.TWO_PWR_24_) &&
|
||||
other.lessThan(goog.math.Long.TWO_PWR_24_)) {
|
||||
return goog.math.Long.fromNumber(this.toNumber() * other.toNumber());
|
||||
}
|
||||
|
||||
// Divide each long into 4 chunks of 16 bits, and then add up 4x4 products.
|
||||
// We can skip products that would overflow.
|
||||
|
||||
var a48 = this.high_ >>> 16;
|
||||
var a32 = this.high_ & 0xFFFF;
|
||||
var a16 = this.low_ >>> 16;
|
||||
var a00 = this.low_ & 0xFFFF;
|
||||
|
||||
var b48 = other.high_ >>> 16;
|
||||
var b32 = other.high_ & 0xFFFF;
|
||||
var b16 = other.low_ >>> 16;
|
||||
var b00 = other.low_ & 0xFFFF;
|
||||
|
||||
var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
|
||||
c00 += a00 * b00;
|
||||
c16 += c00 >>> 16;
|
||||
c00 &= 0xFFFF;
|
||||
c16 += a16 * b00;
|
||||
c32 += c16 >>> 16;
|
||||
c16 &= 0xFFFF;
|
||||
c16 += a00 * b16;
|
||||
c32 += c16 >>> 16;
|
||||
c16 &= 0xFFFF;
|
||||
c32 += a32 * b00;
|
||||
c48 += c32 >>> 16;
|
||||
c32 &= 0xFFFF;
|
||||
c32 += a16 * b16;
|
||||
c48 += c32 >>> 16;
|
||||
c32 &= 0xFFFF;
|
||||
c32 += a00 * b32;
|
||||
c48 += c32 >>> 16;
|
||||
c32 &= 0xFFFF;
|
||||
c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48;
|
||||
c48 &= 0xFFFF;
|
||||
return goog.math.Long.fromBits((c16 << 16) | c00, (c48 << 16) | c32);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns this Long divided by the given one.
|
||||
* @param {goog.math.Long} other Long by which to divide.
|
||||
* @return {!goog.math.Long} This Long divided by the given one.
|
||||
*/
|
||||
goog.math.Long.prototype.div = function(other) {
|
||||
if (other.isZero()) {
|
||||
throw Error('division by zero');
|
||||
} else if (this.isZero()) {
|
||||
return goog.math.Long.ZERO;
|
||||
}
|
||||
|
||||
if (this.equals(goog.math.Long.MIN_VALUE)) {
|
||||
if (other.equals(goog.math.Long.ONE) ||
|
||||
other.equals(goog.math.Long.NEG_ONE)) {
|
||||
return goog.math.Long.MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE
|
||||
} else if (other.equals(goog.math.Long.MIN_VALUE)) {
|
||||
return goog.math.Long.ONE;
|
||||
} else {
|
||||
// At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|.
|
||||
var halfThis = this.shiftRight(1);
|
||||
var approx = halfThis.div(other).shiftLeft(1);
|
||||
if (approx.equals(goog.math.Long.ZERO)) {
|
||||
return other.isNegative() ? goog.math.Long.ONE : goog.math.Long.NEG_ONE;
|
||||
} else {
|
||||
var rem = this.subtract(other.multiply(approx));
|
||||
var result = approx.add(rem.div(other));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
} else if (other.equals(goog.math.Long.MIN_VALUE)) {
|
||||
return goog.math.Long.ZERO;
|
||||
}
|
||||
|
||||
if (this.isNegative()) {
|
||||
if (other.isNegative()) {
|
||||
return this.negate().div(other.negate());
|
||||
} else {
|
||||
return this.negate().div(other).negate();
|
||||
}
|
||||
} else if (other.isNegative()) {
|
||||
return this.div(other.negate()).negate();
|
||||
}
|
||||
|
||||
// Repeat the following until the remainder is less than other: find a
|
||||
// floating-point that approximates remainder / other *from below*, add this
|
||||
// into the result, and subtract it from the remainder. It is critical that
|
||||
// the approximate value is less than or equal to the real value so that the
|
||||
// remainder never becomes negative.
|
||||
var res = goog.math.Long.ZERO;
|
||||
var rem = this;
|
||||
while (rem.greaterThanOrEqual(other)) {
|
||||
// Approximate the result of division. This may be a little greater or
|
||||
// smaller than the actual value.
|
||||
var approx = Math.max(1, Math.floor(rem.toNumber() / other.toNumber()));
|
||||
|
||||
// We will tweak the approximate result by changing it in the 48-th digit or
|
||||
// the smallest non-fractional digit, whichever is larger.
|
||||
var log2 = Math.ceil(Math.log(approx) / Math.LN2);
|
||||
var delta = (log2 <= 48) ? 1 : Math.pow(2, log2 - 48);
|
||||
|
||||
// Decrease the approximation until it is smaller than the remainder. Note
|
||||
// that if it is too large, the product overflows and is negative.
|
||||
var approxRes = goog.math.Long.fromNumber(approx);
|
||||
var approxRem = approxRes.multiply(other);
|
||||
while (approxRem.isNegative() || approxRem.greaterThan(rem)) {
|
||||
approx -= delta;
|
||||
approxRes = goog.math.Long.fromNumber(approx);
|
||||
approxRem = approxRes.multiply(other);
|
||||
}
|
||||
|
||||
// We know the answer can't be zero... and actually, zero would cause
|
||||
// infinite recursion since we would make no progress.
|
||||
if (approxRes.isZero()) {
|
||||
approxRes = goog.math.Long.ONE;
|
||||
}
|
||||
|
||||
res = res.add(approxRes);
|
||||
rem = rem.subtract(approxRem);
|
||||
}
|
||||
return res;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns this Long modulo the given one.
|
||||
* @param {goog.math.Long} other Long by which to mod.
|
||||
* @return {!goog.math.Long} This Long modulo the given one.
|
||||
*/
|
||||
goog.math.Long.prototype.modulo = function(other) {
|
||||
return this.subtract(this.div(other).multiply(other));
|
||||
};
|
||||
|
||||
|
||||
/** @return {!goog.math.Long} The bitwise-NOT of this value. */
|
||||
goog.math.Long.prototype.not = function() {
|
||||
return goog.math.Long.fromBits(~this.low_, ~this.high_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the bitwise-AND of this Long and the given one.
|
||||
* @param {goog.math.Long} other The Long with which to AND.
|
||||
* @return {!goog.math.Long} The bitwise-AND of this and the other.
|
||||
*/
|
||||
goog.math.Long.prototype.and = function(other) {
|
||||
return goog.math.Long.fromBits(this.low_ & other.low_,
|
||||
this.high_ & other.high_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the bitwise-OR of this Long and the given one.
|
||||
* @param {goog.math.Long} other The Long with which to OR.
|
||||
* @return {!goog.math.Long} The bitwise-OR of this and the other.
|
||||
*/
|
||||
goog.math.Long.prototype.or = function(other) {
|
||||
return goog.math.Long.fromBits(this.low_ | other.low_,
|
||||
this.high_ | other.high_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the bitwise-XOR of this Long and the given one.
|
||||
* @param {goog.math.Long} other The Long with which to XOR.
|
||||
* @return {!goog.math.Long} The bitwise-XOR of this and the other.
|
||||
*/
|
||||
goog.math.Long.prototype.xor = function(other) {
|
||||
return goog.math.Long.fromBits(this.low_ ^ other.low_,
|
||||
this.high_ ^ other.high_);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns this Long with bits shifted to the left by the given amount.
|
||||
* @param {number} numBits The number of bits by which to shift.
|
||||
* @return {!goog.math.Long} This shifted to the left by the given amount.
|
||||
*/
|
||||
goog.math.Long.prototype.shiftLeft = function(numBits) {
|
||||
numBits &= 63;
|
||||
if (numBits == 0) {
|
||||
return this;
|
||||
} else {
|
||||
var low = this.low_;
|
||||
if (numBits < 32) {
|
||||
var high = this.high_;
|
||||
return goog.math.Long.fromBits(
|
||||
low << numBits,
|
||||
(high << numBits) | (low >>> (32 - numBits)));
|
||||
} else {
|
||||
return goog.math.Long.fromBits(0, low << (numBits - 32));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns this Long with bits shifted to the right by the given amount.
|
||||
* @param {number} numBits The number of bits by which to shift.
|
||||
* @return {!goog.math.Long} This shifted to the right by the given amount.
|
||||
*/
|
||||
goog.math.Long.prototype.shiftRight = function(numBits) {
|
||||
numBits &= 63;
|
||||
if (numBits == 0) {
|
||||
return this;
|
||||
} else {
|
||||
var high = this.high_;
|
||||
if (numBits < 32) {
|
||||
var low = this.low_;
|
||||
return goog.math.Long.fromBits(
|
||||
(low >>> numBits) | (high << (32 - numBits)),
|
||||
high >> numBits);
|
||||
} else {
|
||||
return goog.math.Long.fromBits(
|
||||
high >> (numBits - 32),
|
||||
high >= 0 ? 0 : -1);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns this Long with bits shifted to the right by the given amount, with
|
||||
* zeros placed into the new leading bits.
|
||||
* @param {number} numBits The number of bits by which to shift.
|
||||
* @return {!goog.math.Long} This shifted to the right by the given amount, with
|
||||
* zeros placed into the new leading bits.
|
||||
*/
|
||||
goog.math.Long.prototype.shiftRightUnsigned = function(numBits) {
|
||||
numBits &= 63;
|
||||
if (numBits == 0) {
|
||||
return this;
|
||||
} else {
|
||||
var high = this.high_;
|
||||
if (numBits < 32) {
|
||||
var low = this.low_;
|
||||
return goog.math.Long.fromBits(
|
||||
(low >>> numBits) | (high << (32 - numBits)),
|
||||
high >>> numBits);
|
||||
} else if (numBits == 32) {
|
||||
return goog.math.Long.fromBits(high, 0);
|
||||
} else {
|
||||
return goog.math.Long.fromBits(high >>> (numBits - 32), 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
387
nicer-api-docs/closure-library/closure/goog/math/math.js
Normal file
387
nicer-api-docs/closure-library/closure/goog/math/math.js
Normal file
@@ -0,0 +1,387 @@
|
||||
// Copyright 2006 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/**
|
||||
* @fileoverview Additional mathematical functions.
|
||||
*/
|
||||
|
||||
goog.provide('goog.math');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.asserts');
|
||||
|
||||
|
||||
/**
|
||||
* Returns a random integer greater than or equal to 0 and less than {@code a}.
|
||||
* @param {number} a The upper bound for the random integer (exclusive).
|
||||
* @return {number} A random integer N such that 0 <= N < a.
|
||||
*/
|
||||
goog.math.randomInt = function(a) {
|
||||
return Math.floor(Math.random() * a);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a random number greater than or equal to {@code a} and less than
|
||||
* {@code b}.
|
||||
* @param {number} a The lower bound for the random number (inclusive).
|
||||
* @param {number} b The upper bound for the random number (exclusive).
|
||||
* @return {number} A random number N such that a <= N < b.
|
||||
*/
|
||||
goog.math.uniformRandom = function(a, b) {
|
||||
return a + Math.random() * (b - a);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Takes a number and clamps it to within the provided bounds.
|
||||
* @param {number} value The input number.
|
||||
* @param {number} min The minimum value to return.
|
||||
* @param {number} max The maximum value to return.
|
||||
* @return {number} The input number if it is within bounds, or the nearest
|
||||
* number within the bounds.
|
||||
*/
|
||||
goog.math.clamp = function(value, min, max) {
|
||||
return Math.min(Math.max(value, min), max);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* The % operator in JavaScript returns the remainder of a / b, but differs from
|
||||
* some other languages in that the result will have the same sign as the
|
||||
* dividend. For example, -1 % 8 == -1, whereas in some other languages
|
||||
* (such as Python) the result would be 7. This function emulates the more
|
||||
* correct modulo behavior, which is useful for certain applications such as
|
||||
* calculating an offset index in a circular list.
|
||||
*
|
||||
* @param {number} a The dividend.
|
||||
* @param {number} b The divisor.
|
||||
* @return {number} a % b where the result is between 0 and b (either 0 <= x < b
|
||||
* or b < x <= 0, depending on the sign of b).
|
||||
*/
|
||||
goog.math.modulo = function(a, b) {
|
||||
var r = a % b;
|
||||
// If r and b differ in sign, add b to wrap the result to the correct sign.
|
||||
return (r * b < 0) ? r + b : r;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Performs linear interpolation between values a and b. Returns the value
|
||||
* between a and b proportional to x (when x is between 0 and 1. When x is
|
||||
* outside this range, the return value is a linear extrapolation).
|
||||
* @param {number} a A number.
|
||||
* @param {number} b A number.
|
||||
* @param {number} x The proportion between a and b.
|
||||
* @return {number} The interpolated value between a and b.
|
||||
*/
|
||||
goog.math.lerp = function(a, b, x) {
|
||||
return a + x * (b - a);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Tests whether the two values are equal to each other, within a certain
|
||||
* tolerance to adjust for floating pount errors.
|
||||
* @param {number} a A number.
|
||||
* @param {number} b A number.
|
||||
* @param {number=} opt_tolerance Optional tolerance range. Defaults
|
||||
* to 0.000001. If specified, should be greater than 0.
|
||||
* @return {boolean} Whether {@code a} and {@code b} are nearly equal.
|
||||
*/
|
||||
goog.math.nearlyEquals = function(a, b, opt_tolerance) {
|
||||
return Math.abs(a - b) <= (opt_tolerance || 0.000001);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Standardizes an angle to be in range [0-360). Negative angles become
|
||||
* positive, and values greater than 360 are returned modulo 360.
|
||||
* @param {number} angle Angle in degrees.
|
||||
* @return {number} Standardized angle.
|
||||
*/
|
||||
goog.math.standardAngle = function(angle) {
|
||||
return goog.math.modulo(angle, 360);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts degrees to radians.
|
||||
* @param {number} angleDegrees Angle in degrees.
|
||||
* @return {number} Angle in radians.
|
||||
*/
|
||||
goog.math.toRadians = function(angleDegrees) {
|
||||
return angleDegrees * Math.PI / 180;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Converts radians to degrees.
|
||||
* @param {number} angleRadians Angle in radians.
|
||||
* @return {number} Angle in degrees.
|
||||
*/
|
||||
goog.math.toDegrees = function(angleRadians) {
|
||||
return angleRadians * 180 / Math.PI;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* For a given angle and radius, finds the X portion of the offset.
|
||||
* @param {number} degrees Angle in degrees (zero points in +X direction).
|
||||
* @param {number} radius Radius.
|
||||
* @return {number} The x-distance for the angle and radius.
|
||||
*/
|
||||
goog.math.angleDx = function(degrees, radius) {
|
||||
return radius * Math.cos(goog.math.toRadians(degrees));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* For a given angle and radius, finds the Y portion of the offset.
|
||||
* @param {number} degrees Angle in degrees (zero points in +X direction).
|
||||
* @param {number} radius Radius.
|
||||
* @return {number} The y-distance for the angle and radius.
|
||||
*/
|
||||
goog.math.angleDy = function(degrees, radius) {
|
||||
return radius * Math.sin(goog.math.toRadians(degrees));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Computes the angle between two points (x1,y1) and (x2,y2).
|
||||
* Angle zero points in the +X direction, 90 degrees points in the +Y
|
||||
* direction (down) and from there we grow clockwise towards 360 degrees.
|
||||
* @param {number} x1 x of first point.
|
||||
* @param {number} y1 y of first point.
|
||||
* @param {number} x2 x of second point.
|
||||
* @param {number} y2 y of second point.
|
||||
* @return {number} Standardized angle in degrees of the vector from
|
||||
* x1,y1 to x2,y2.
|
||||
*/
|
||||
goog.math.angle = function(x1, y1, x2, y2) {
|
||||
return goog.math.standardAngle(goog.math.toDegrees(Math.atan2(y2 - y1,
|
||||
x2 - x1)));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Computes the difference between startAngle and endAngle (angles in degrees).
|
||||
* @param {number} startAngle Start angle in degrees.
|
||||
* @param {number} endAngle End angle in degrees.
|
||||
* @return {number} The number of degrees that when added to
|
||||
* startAngle will result in endAngle. Positive numbers mean that the
|
||||
* direction is clockwise. Negative numbers indicate a counter-clockwise
|
||||
* direction.
|
||||
* The shortest route (clockwise vs counter-clockwise) between the angles
|
||||
* is used.
|
||||
* When the difference is 180 degrees, the function returns 180 (not -180)
|
||||
* angleDifference(30, 40) is 10, and angleDifference(40, 30) is -10.
|
||||
* angleDifference(350, 10) is 20, and angleDifference(10, 350) is -20.
|
||||
*/
|
||||
goog.math.angleDifference = function(startAngle, endAngle) {
|
||||
var d = goog.math.standardAngle(endAngle) -
|
||||
goog.math.standardAngle(startAngle);
|
||||
if (d > 180) {
|
||||
d = d - 360;
|
||||
} else if (d <= -180) {
|
||||
d = 360 + d;
|
||||
}
|
||||
return d;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the sign of a number as per the "sign" or "signum" function.
|
||||
* @param {number} x The number to take the sign of.
|
||||
* @return {number} -1 when negative, 1 when positive, 0 when 0.
|
||||
*/
|
||||
goog.math.sign = function(x) {
|
||||
return x == 0 ? 0 : (x < 0 ? -1 : 1);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* JavaScript implementation of Longest Common Subsequence problem.
|
||||
* http://en.wikipedia.org/wiki/Longest_common_subsequence
|
||||
*
|
||||
* Returns the longest possible array that is subarray of both of given arrays.
|
||||
*
|
||||
* @param {Array.<Object>} array1 First array of objects.
|
||||
* @param {Array.<Object>} array2 Second array of objects.
|
||||
* @param {Function=} opt_compareFn Function that acts as a custom comparator
|
||||
* for the array ojects. Function should return true if objects are equal,
|
||||
* otherwise false.
|
||||
* @param {Function=} opt_collectorFn Function used to decide what to return
|
||||
* as a result subsequence. It accepts 2 arguments: index of common element
|
||||
* in the first array and index in the second. The default function returns
|
||||
* element from the first array.
|
||||
* @return {Array.<Object>} A list of objects that are common to both arrays
|
||||
* such that there is no common subsequence with size greater than the
|
||||
* length of the list.
|
||||
*/
|
||||
goog.math.longestCommonSubsequence = function(
|
||||
array1, array2, opt_compareFn, opt_collectorFn) {
|
||||
|
||||
var compare = opt_compareFn || function(a, b) {
|
||||
return a == b;
|
||||
};
|
||||
|
||||
var collect = opt_collectorFn || function(i1, i2) {
|
||||
return array1[i1];
|
||||
};
|
||||
|
||||
var length1 = array1.length;
|
||||
var length2 = array2.length;
|
||||
|
||||
var arr = [];
|
||||
for (var i = 0; i < length1 + 1; i++) {
|
||||
arr[i] = [];
|
||||
arr[i][0] = 0;
|
||||
}
|
||||
|
||||
for (var j = 0; j < length2 + 1; j++) {
|
||||
arr[0][j] = 0;
|
||||
}
|
||||
|
||||
for (i = 1; i <= length1; i++) {
|
||||
for (j = 1; j <= length2; j++) {
|
||||
if (compare(array1[i - 1], array2[j - 1])) {
|
||||
arr[i][j] = arr[i - 1][j - 1] + 1;
|
||||
} else {
|
||||
arr[i][j] = Math.max(arr[i - 1][j], arr[i][j - 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Backtracking
|
||||
var result = [];
|
||||
var i = length1, j = length2;
|
||||
while (i > 0 && j > 0) {
|
||||
if (compare(array1[i - 1], array2[j - 1])) {
|
||||
result.unshift(collect(i - 1, j - 1));
|
||||
i--;
|
||||
j--;
|
||||
} else {
|
||||
if (arr[i - 1][j] > arr[i][j - 1]) {
|
||||
i--;
|
||||
} else {
|
||||
j--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the sum of the arguments.
|
||||
* @param {...number} var_args Numbers to add.
|
||||
* @return {number} The sum of the arguments (0 if no arguments were provided,
|
||||
* {@code NaN} if any of the arguments is not a valid number).
|
||||
*/
|
||||
goog.math.sum = function(var_args) {
|
||||
return /** @type {number} */ (goog.array.reduce(arguments,
|
||||
function(sum, value) {
|
||||
return sum + value;
|
||||
}, 0));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the arithmetic mean of the arguments.
|
||||
* @param {...number} var_args Numbers to average.
|
||||
* @return {number} The average of the arguments ({@code NaN} if no arguments
|
||||
* were provided or any of the arguments is not a valid number).
|
||||
*/
|
||||
goog.math.average = function(var_args) {
|
||||
return goog.math.sum.apply(null, arguments) / arguments.length;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the sample standard deviation of the arguments. For a definition of
|
||||
* sample standard deviation, see e.g.
|
||||
* http://en.wikipedia.org/wiki/Standard_deviation
|
||||
* @param {...number} var_args Number samples to analyze.
|
||||
* @return {number} The sample standard deviation of the arguments (0 if fewer
|
||||
* than two samples were provided, or {@code NaN} if any of the samples is
|
||||
* not a valid number).
|
||||
*/
|
||||
goog.math.standardDeviation = function(var_args) {
|
||||
var sampleSize = arguments.length;
|
||||
if (sampleSize < 2) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var mean = goog.math.average.apply(null, arguments);
|
||||
var variance = goog.math.sum.apply(null, goog.array.map(arguments,
|
||||
function(val) {
|
||||
return Math.pow(val - mean, 2);
|
||||
})) / (sampleSize - 1);
|
||||
|
||||
return Math.sqrt(variance);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether the supplied number represents an integer, i.e. that is has
|
||||
* no fractional component. No range-checking is performed on the number.
|
||||
* @param {number} num The number to test.
|
||||
* @return {boolean} Whether {@code num} is an integer.
|
||||
*/
|
||||
goog.math.isInt = function(num) {
|
||||
return isFinite(num) && num % 1 == 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether the supplied number is finite and not NaN.
|
||||
* @param {number} num The number to test.
|
||||
* @return {boolean} Whether {@code num} is a finite number.
|
||||
*/
|
||||
goog.math.isFiniteNumber = function(num) {
|
||||
return isFinite(num) && !isNaN(num);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A tweaked variant of {@code Math.floor} which tolerates if the passed number
|
||||
* is infinitesimally smaller than the closest integer. It often happens with
|
||||
* the results of floating point calculations because of the finite precision
|
||||
* of the intermediate results. For example {@code Math.floor(Math.log(1000) /
|
||||
* Math.LN10) == 2}, not 3 as one would expect.
|
||||
* @param {number} num A number.
|
||||
* @param {number=} opt_epsilon An infinitesimally small positive number, the
|
||||
* rounding error to tolerate.
|
||||
* @return {number} The largest integer less than or equal to {@code num}.
|
||||
*/
|
||||
goog.math.safeFloor = function(num, opt_epsilon) {
|
||||
goog.asserts.assert(!goog.isDef(opt_epsilon) || opt_epsilon > 0);
|
||||
return Math.floor(num + (opt_epsilon || 2e-15));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A tweaked variant of {@code Math.ceil}. See {@code goog.math.safeFloor} for
|
||||
* details.
|
||||
* @param {number} num A number.
|
||||
* @param {number=} opt_epsilon An infinitesimally small positive number, the
|
||||
* rounding error to tolerate.
|
||||
* @return {number} The smallest integer greater than or equal to {@code num}.
|
||||
*/
|
||||
goog.math.safeCeil = function(num, opt_epsilon) {
|
||||
goog.asserts.assert(!goog.isDef(opt_epsilon) || opt_epsilon > 0);
|
||||
return Math.ceil(num - (opt_epsilon || 2e-15));
|
||||
};
|
||||
675
nicer-api-docs/closure-library/closure/goog/math/matrix.js
Normal file
675
nicer-api-docs/closure-library/closure/goog/math/matrix.js
Normal file
@@ -0,0 +1,675 @@
|
||||
// Copyright 2007 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/**
|
||||
* @fileoverview Class for representing matrices and static helper functions.
|
||||
*/
|
||||
|
||||
goog.provide('goog.math.Matrix');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.math');
|
||||
goog.require('goog.math.Size');
|
||||
goog.require('goog.string');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Class for representing and manipulating matrices.
|
||||
*
|
||||
* The entry that lies in the i-th row and the j-th column of a matrix is
|
||||
* typically referred to as the i,j entry of the matrix.
|
||||
*
|
||||
* The m-by-n matrix A would have its entries referred to as:
|
||||
* [ a0,0 a0,1 a0,2 ... a0,j ... a0,n ]
|
||||
* [ a1,0 a1,1 a1,2 ... a1,j ... a1,n ]
|
||||
* [ a2,0 a2,1 a2,2 ... a2,j ... a2,n ]
|
||||
* [ . . . . . ]
|
||||
* [ . . . . . ]
|
||||
* [ . . . . . ]
|
||||
* [ ai,0 ai,1 ai,2 ... ai,j ... ai,n ]
|
||||
* [ . . . . . ]
|
||||
* [ . . . . . ]
|
||||
* [ . . . . . ]
|
||||
* [ am,0 am,1 am,2 ... am,j ... am,n ]
|
||||
*
|
||||
* @param {goog.math.Matrix|Array.<Array.<number>>|goog.math.Size|number} m
|
||||
* A matrix to copy, a 2D-array to take as a template, a size object for
|
||||
* dimensions, or the number of rows.
|
||||
* @param {number=} opt_n Number of columns of the matrix (only applicable if
|
||||
* the first argument is also numeric).
|
||||
* @constructor
|
||||
*/
|
||||
goog.math.Matrix = function(m, opt_n) {
|
||||
if (m instanceof goog.math.Matrix) {
|
||||
this.array_ = m.toArray();
|
||||
} else if (goog.isArrayLike(m) &&
|
||||
goog.math.Matrix.isValidArray(/** @type {!Array} */ (m))) {
|
||||
this.array_ = goog.array.clone(/** @type {!Array.<!Array.<number>>} */ (m));
|
||||
} else if (m instanceof goog.math.Size) {
|
||||
this.array_ = goog.math.Matrix.createZeroPaddedArray_(m.height, m.width);
|
||||
} else if (goog.isNumber(m) && goog.isNumber(opt_n) && m > 0 && opt_n > 0) {
|
||||
this.array_ = goog.math.Matrix.createZeroPaddedArray_(
|
||||
/** @type {number} */ (m), opt_n);
|
||||
} else {
|
||||
throw Error('Invalid argument(s) for Matrix contructor');
|
||||
}
|
||||
|
||||
this.size_ = new goog.math.Size(this.array_[0].length, this.array_.length);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a square identity matrix. i.e. for n = 3:
|
||||
* <pre>
|
||||
* [ 1 0 0 ]
|
||||
* [ 0 1 0 ]
|
||||
* [ 0 0 1 ]
|
||||
* </pre>
|
||||
* @param {number} n The size of the square identity matrix.
|
||||
* @return {!goog.math.Matrix} Identity matrix of width and height {@code n}.
|
||||
*/
|
||||
goog.math.Matrix.createIdentityMatrix = function(n) {
|
||||
var rv = [];
|
||||
for (var i = 0; i < n; i++) {
|
||||
rv[i] = [];
|
||||
for (var j = 0; j < n; j++) {
|
||||
rv[i][j] = i == j ? 1 : 0;
|
||||
}
|
||||
}
|
||||
return new goog.math.Matrix(rv);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calls a function for each cell in a matrix.
|
||||
* @param {goog.math.Matrix} matrix The matrix to iterate over.
|
||||
* @param {Function} fn The function to call for every element. This function
|
||||
* takes 4 arguments (value, i, j, and the matrix)
|
||||
* and the return value is irrelevant.
|
||||
* @param {Object=} opt_obj The object to be used as the value of 'this'
|
||||
* within {@code fn}.
|
||||
*/
|
||||
goog.math.Matrix.forEach = function(matrix, fn, opt_obj) {
|
||||
for (var i = 0; i < matrix.getSize().height; i++) {
|
||||
for (var j = 0; j < matrix.getSize().width; j++) {
|
||||
fn.call(opt_obj, matrix.array_[i][j], i, j, matrix);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Tests whether an array is a valid matrix. A valid array is an array of
|
||||
* arrays where all arrays are of the same length and all elements are numbers.
|
||||
* @param {Array} arr An array to test.
|
||||
* @return {boolean} Whether the array is a valid matrix.
|
||||
*/
|
||||
goog.math.Matrix.isValidArray = function(arr) {
|
||||
var len = 0;
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
if (!goog.isArrayLike(arr[i]) || len > 0 && arr[i].length != len) {
|
||||
return false;
|
||||
}
|
||||
for (var j = 0; j < arr[i].length; j++) {
|
||||
if (!goog.isNumber(arr[i][j])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (len == 0) {
|
||||
len = arr[i].length;
|
||||
}
|
||||
}
|
||||
return len != 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Calls a function for every cell in a matrix and inserts the result into a
|
||||
* new matrix of equal dimensions.
|
||||
* @param {goog.math.Matrix} matrix The matrix to iterate over.
|
||||
* @param {Function} fn The function to call for every element. This function
|
||||
* takes 4 arguments (value, i, j and the matrix)
|
||||
* and should return something. The result will be inserted
|
||||
* into a new matrix.
|
||||
* @param {Object=} opt_obj The object to be used as the value of 'this'
|
||||
* within {@code fn}.
|
||||
* @return {!goog.math.Matrix} A new matrix with the results from {@code fn}.
|
||||
*/
|
||||
goog.math.Matrix.map = function(matrix, fn, opt_obj) {
|
||||
var m = new goog.math.Matrix(matrix.getSize());
|
||||
goog.math.Matrix.forEach(matrix, function(value, i, j) {
|
||||
m.array_[i][j] = fn.call(opt_obj, value, i, j, matrix);
|
||||
});
|
||||
return m;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new zero padded matix.
|
||||
* @param {number} m Height of matrix.
|
||||
* @param {number} n Width of matrix.
|
||||
* @return {!Array.<!Array.<number>>} The new zero padded matrix.
|
||||
* @private
|
||||
*/
|
||||
goog.math.Matrix.createZeroPaddedArray_ = function(m, n) {
|
||||
var rv = [];
|
||||
for (var i = 0; i < m; i++) {
|
||||
rv[i] = [];
|
||||
for (var j = 0; j < n; j++) {
|
||||
rv[i][j] = 0;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Internal array representing the matrix.
|
||||
* @type {!Array.<!Array.<number>>}
|
||||
* @private
|
||||
*/
|
||||
goog.math.Matrix.prototype.array_;
|
||||
|
||||
|
||||
/**
|
||||
* After construction the Matrix's size is constant and stored in this object.
|
||||
* @type {!goog.math.Size}
|
||||
* @private
|
||||
*/
|
||||
goog.math.Matrix.prototype.size_;
|
||||
|
||||
|
||||
/**
|
||||
* Returns a new matrix that is the sum of this and the provided matrix.
|
||||
* @param {goog.math.Matrix} m The matrix to add to this one.
|
||||
* @return {!goog.math.Matrix} Resultant sum.
|
||||
*/
|
||||
goog.math.Matrix.prototype.add = function(m) {
|
||||
if (!goog.math.Size.equals(this.size_, m.getSize())) {
|
||||
throw Error('Matrix summation is only supported on arrays of equal size');
|
||||
}
|
||||
return goog.math.Matrix.map(this, function(val, i, j) {
|
||||
return val + m.array_[i][j];
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Appends the given matrix to the right side of this matrix.
|
||||
* @param {goog.math.Matrix} m The matrix to augment this matrix with.
|
||||
* @return {!goog.math.Matrix} A new matrix with additional columns on the
|
||||
* right.
|
||||
*/
|
||||
goog.math.Matrix.prototype.appendColumns = function(m) {
|
||||
if (this.size_.height != m.getSize().height) {
|
||||
throw Error('The given matrix has height ' + m.size_.height + ', but ' +
|
||||
' needs to have height ' + this.size_.height + '.');
|
||||
}
|
||||
var result = new goog.math.Matrix(this.size_.height,
|
||||
this.size_.width + m.size_.width);
|
||||
goog.math.Matrix.forEach(this, function(value, i, j) {
|
||||
result.array_[i][j] = value;
|
||||
});
|
||||
goog.math.Matrix.forEach(m, function(value, i, j) {
|
||||
result.array_[i][this.size_.width + j] = value;
|
||||
}, this);
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Appends the given matrix to the bottom of this matrix.
|
||||
* @param {goog.math.Matrix} m The matrix to augment this matrix with.
|
||||
* @return {!goog.math.Matrix} A new matrix with added columns on the bottom.
|
||||
*/
|
||||
goog.math.Matrix.prototype.appendRows = function(m) {
|
||||
if (this.size_.width != m.getSize().width) {
|
||||
throw Error('The given matrix has width ' + m.size_.width + ', but ' +
|
||||
' needs to have width ' + this.size_.width + '.');
|
||||
}
|
||||
var result = new goog.math.Matrix(this.size_.height + m.size_.height,
|
||||
this.size_.width);
|
||||
goog.math.Matrix.forEach(this, function(value, i, j) {
|
||||
result.array_[i][j] = value;
|
||||
});
|
||||
goog.math.Matrix.forEach(m, function(value, i, j) {
|
||||
result.array_[this.size_.height + i][j] = value;
|
||||
}, this);
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether the given matrix equals this matrix.
|
||||
* @param {goog.math.Matrix} m The matrix to compare to this one.
|
||||
* @param {number=} opt_tolerance The tolerance when comparing array entries.
|
||||
* @return {boolean} Whether the given matrix equals this matrix.
|
||||
*/
|
||||
goog.math.Matrix.prototype.equals = function(m, opt_tolerance) {
|
||||
if (this.size_.width != m.size_.width) {
|
||||
return false;
|
||||
}
|
||||
if (this.size_.height != m.size_.height) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var tolerance = opt_tolerance || 0;
|
||||
for (var i = 0; i < this.size_.height; i++) {
|
||||
for (var j = 0; j < this.size_.width; j++) {
|
||||
if (!goog.math.nearlyEquals(this.array_[i][j], m.array_[i][j],
|
||||
tolerance)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the determinant of this matrix. The determinant of a matrix A is
|
||||
* often denoted as |A| and can only be applied to a square matrix.
|
||||
* @return {number} The determinant of this matrix.
|
||||
*/
|
||||
goog.math.Matrix.prototype.getDeterminant = function() {
|
||||
if (!this.isSquare()) {
|
||||
throw Error('A determinant can only be take on a square matrix');
|
||||
}
|
||||
|
||||
return this.getDeterminant_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the inverse of this matrix if it exists or null if the matrix is
|
||||
* not invertible.
|
||||
* @return {goog.math.Matrix} A new matrix which is the inverse of this matrix.
|
||||
*/
|
||||
goog.math.Matrix.prototype.getInverse = function() {
|
||||
if (!this.isSquare()) {
|
||||
throw Error('An inverse can only be taken on a square matrix.');
|
||||
}
|
||||
if (this.getSize().width == 1) {
|
||||
var a = this.getValueAt(0, 0);
|
||||
return a == 0 ? null : new goog.math.Matrix([[1 / a]]);
|
||||
}
|
||||
var identity = goog.math.Matrix.createIdentityMatrix(this.size_.height);
|
||||
var mi = this.appendColumns(identity).getReducedRowEchelonForm();
|
||||
var i = mi.getSubmatrixByCoordinates_(
|
||||
0, 0, identity.size_.width - 1, identity.size_.height - 1);
|
||||
if (!i.equals(identity)) {
|
||||
return null; // This matrix was not invertible
|
||||
}
|
||||
return mi.getSubmatrixByCoordinates_(0, identity.size_.width);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Transforms this matrix into reduced row echelon form.
|
||||
* @return {!goog.math.Matrix} A new matrix reduced row echelon form.
|
||||
*/
|
||||
goog.math.Matrix.prototype.getReducedRowEchelonForm = function() {
|
||||
var result = new goog.math.Matrix(this);
|
||||
var col = 0;
|
||||
// Each iteration puts one row in reduced row echelon form
|
||||
for (var row = 0; row < result.size_.height; row++) {
|
||||
if (col >= result.size_.width) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Scan each column starting from this row on down for a non-zero value
|
||||
var i = row;
|
||||
while (result.array_[i][col] == 0) {
|
||||
i++;
|
||||
if (i == result.size_.height) {
|
||||
i = row;
|
||||
col++;
|
||||
if (col == result.size_.width) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make the row we found the current row with a leading 1
|
||||
this.swapRows_(i, row);
|
||||
var divisor = result.array_[row][col];
|
||||
for (var j = col; j < result.size_.width; j++) {
|
||||
result.array_[row][j] = result.array_[row][j] / divisor;
|
||||
}
|
||||
|
||||
// Subtract a multiple of this row from each other row
|
||||
// so that all the other entries in this column are 0
|
||||
for (i = 0; i < result.size_.height; i++) {
|
||||
if (i != row) {
|
||||
var multiple = result.array_[i][col];
|
||||
for (var j = col; j < result.size_.width; j++) {
|
||||
result.array_[i][j] -= multiple * result.array_[row][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Move on to the next column
|
||||
col++;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!goog.math.Size} The dimensions of the matrix.
|
||||
*/
|
||||
goog.math.Matrix.prototype.getSize = function() {
|
||||
return this.size_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Return the transpose of this matrix. For an m-by-n matrix, the transpose
|
||||
* is the n-by-m matrix which results from turning rows into columns and columns
|
||||
* into rows
|
||||
* @return {!goog.math.Matrix} A new matrix A^T.
|
||||
*/
|
||||
goog.math.Matrix.prototype.getTranspose = function() {
|
||||
var m = new goog.math.Matrix(this.size_.width, this.size_.height);
|
||||
goog.math.Matrix.forEach(this, function(value, i, j) {
|
||||
m.array_[j][i] = value;
|
||||
});
|
||||
return m;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves the value of a particular coordinate in the matrix or null if the
|
||||
* requested coordinates are out of range.
|
||||
* @param {number} i The i index of the coordinate.
|
||||
* @param {number} j The j index of the coordinate.
|
||||
* @return {?number} The value at the specified coordinate.
|
||||
*/
|
||||
goog.math.Matrix.prototype.getValueAt = function(i, j) {
|
||||
if (!this.isInBounds_(i, j)) {
|
||||
return null;
|
||||
}
|
||||
return this.array_[i][j];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Whether the horizontal and vertical dimensions of this
|
||||
* matrix are the same.
|
||||
*/
|
||||
goog.math.Matrix.prototype.isSquare = function() {
|
||||
return this.size_.width == this.size_.height;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sets the value at a particular coordinate (if the coordinate is within the
|
||||
* bounds of the matrix).
|
||||
* @param {number} i The i index of the coordinate.
|
||||
* @param {number} j The j index of the coordinate.
|
||||
* @param {number} value The new value for the coordinate.
|
||||
*/
|
||||
goog.math.Matrix.prototype.setValueAt = function(i, j, value) {
|
||||
if (!this.isInBounds_(i, j)) {
|
||||
throw Error(
|
||||
'Index out of bounds when setting matrix value, (' + i + ',' + j +
|
||||
') in size (' + this.size_.height + ',' + this.size_.width + ')');
|
||||
}
|
||||
this.array_[i][j] = value;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Performs matrix or scalar multiplication on a matrix and returns the
|
||||
* resultant matrix.
|
||||
*
|
||||
* Matrix multiplication is defined between two matrices only if the number of
|
||||
* columns of the first matrix is the same as the number of rows of the second
|
||||
* matrix. If A is an m-by-n matrix and B is an n-by-p matrix, then their
|
||||
* product AB is an m-by-p matrix
|
||||
*
|
||||
* Scalar multiplication returns a matrix of the same size as the original,
|
||||
* each value multiplied by the given value.
|
||||
*
|
||||
* @param {goog.math.Matrix|number} m Matrix/number to multiply the matrix by.
|
||||
* @return {!goog.math.Matrix} Resultant product.
|
||||
*/
|
||||
goog.math.Matrix.prototype.multiply = function(m) {
|
||||
if (m instanceof goog.math.Matrix) {
|
||||
if (this.size_.width != m.getSize().height) {
|
||||
throw Error('Invalid matrices for multiplication. Second matrix ' +
|
||||
'should have the same number of rows as the first has columns.');
|
||||
}
|
||||
return this.matrixMultiply_(/** @type {!goog.math.Matrix} */ (m));
|
||||
} else if (goog.isNumber(m)) {
|
||||
return this.scalarMultiply_(/** @type {number} */ (m));
|
||||
} else {
|
||||
throw Error('A matrix can only be multiplied by' +
|
||||
' a number or another matrix.');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a new matrix that is the difference of this and the provided matrix.
|
||||
* @param {goog.math.Matrix} m The matrix to subtract from this one.
|
||||
* @return {!goog.math.Matrix} Resultant difference.
|
||||
*/
|
||||
goog.math.Matrix.prototype.subtract = function(m) {
|
||||
if (!goog.math.Size.equals(this.size_, m.getSize())) {
|
||||
throw Error(
|
||||
'Matrix subtraction is only supported on arrays of equal size.');
|
||||
}
|
||||
return goog.math.Matrix.map(this, function(val, i, j) {
|
||||
return val - m.array_[i][j];
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!Array.<!Array.<number>>} A 2D internal array representing this
|
||||
* matrix. Not a clone.
|
||||
*/
|
||||
goog.math.Matrix.prototype.toArray = function() {
|
||||
return this.array_;
|
||||
};
|
||||
|
||||
|
||||
if (goog.DEBUG) {
|
||||
/**
|
||||
* Returns a string representation of the matrix. e.g.
|
||||
* <pre>
|
||||
* [ 12 5 9 1 ]
|
||||
* [ 4 16 0 17 ]
|
||||
* [ 12 5 1 23 ]
|
||||
* </pre>
|
||||
*
|
||||
* @return {string} A string representation of this matrix.
|
||||
* @override
|
||||
*/
|
||||
goog.math.Matrix.prototype.toString = function() {
|
||||
// Calculate correct padding for optimum display of matrix
|
||||
var maxLen = 0;
|
||||
goog.math.Matrix.forEach(this, function(val) {
|
||||
var len = String(val).length;
|
||||
if (len > maxLen) {
|
||||
maxLen = len;
|
||||
}
|
||||
});
|
||||
|
||||
// Build the string
|
||||
var sb = [];
|
||||
goog.array.forEach(this.array_, function(row, x) {
|
||||
sb.push('[ ');
|
||||
goog.array.forEach(row, function(val, y) {
|
||||
var strval = String(val);
|
||||
sb.push(goog.string.repeat(' ', maxLen - strval.length) + strval + ' ');
|
||||
});
|
||||
sb.push(']\n');
|
||||
});
|
||||
|
||||
return sb.join('');
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the signed minor.
|
||||
* @param {number} i The row index.
|
||||
* @param {number} j The column index.
|
||||
* @return {number} The cofactor C[i,j] of this matrix.
|
||||
* @private
|
||||
*/
|
||||
goog.math.Matrix.prototype.getCofactor_ = function(i, j) {
|
||||
return (i + j % 2 == 0 ? 1 : -1) * this.getMinor_(i, j);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the determinant of this matrix. The determinant of a matrix A is
|
||||
* often denoted as |A| and can only be applied to a square matrix. Same as
|
||||
* public method but without validation. Implemented using Laplace's formula.
|
||||
* @return {number} The determinant of this matrix.
|
||||
* @private
|
||||
*/
|
||||
goog.math.Matrix.prototype.getDeterminant_ = function() {
|
||||
if (this.getSize().area() == 1) {
|
||||
return this.array_[0][0];
|
||||
}
|
||||
|
||||
// We might want to use matrix decomposition to improve running time
|
||||
// For now we'll do a Laplace expansion along the first row
|
||||
var determinant = 0;
|
||||
for (var j = 0; j < this.size_.width; j++) {
|
||||
determinant += (this.array_[0][j] * this.getCofactor_(0, j));
|
||||
}
|
||||
return determinant;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the determinant of the submatrix resulting from the deletion of row i
|
||||
* and column j.
|
||||
* @param {number} i The row to delete.
|
||||
* @param {number} j The column to delete.
|
||||
* @return {number} The first minor M[i,j] of this matrix.
|
||||
* @private
|
||||
*/
|
||||
goog.math.Matrix.prototype.getMinor_ = function(i, j) {
|
||||
return this.getSubmatrixByDeletion_(i, j).getDeterminant_();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a submatrix contained within this matrix.
|
||||
* @param {number} i1 The upper row index.
|
||||
* @param {number} j1 The left column index.
|
||||
* @param {number=} opt_i2 The lower row index.
|
||||
* @param {number=} opt_j2 The right column index.
|
||||
* @return {!goog.math.Matrix} The submatrix contained within the given bounds.
|
||||
* @private
|
||||
*/
|
||||
goog.math.Matrix.prototype.getSubmatrixByCoordinates_ =
|
||||
function(i1, j1, opt_i2, opt_j2) {
|
||||
var i2 = opt_i2 ? opt_i2 : this.size_.height - 1;
|
||||
var j2 = opt_j2 ? opt_j2 : this.size_.width - 1;
|
||||
var result = new goog.math.Matrix(i2 - i1 + 1, j2 - j1 + 1);
|
||||
goog.math.Matrix.forEach(result, function(value, i, j) {
|
||||
result.array_[i][j] = this.array_[i1 + i][j1 + j];
|
||||
}, this);
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a new matrix equal to this one, but with row i and column j deleted.
|
||||
* @param {number} i The row index of the coordinate.
|
||||
* @param {number} j The column index of the coordinate.
|
||||
* @return {!goog.math.Matrix} The value at the specified coordinate.
|
||||
* @private
|
||||
*/
|
||||
goog.math.Matrix.prototype.getSubmatrixByDeletion_ = function(i, j) {
|
||||
var m = new goog.math.Matrix(this.size_.width - 1, this.size_.height - 1);
|
||||
goog.math.Matrix.forEach(m, function(value, x, y) {
|
||||
m.setValueAt(x, y, this.array_[x >= i ? x + 1 : x][y >= j ? y + 1 : y]);
|
||||
}, this);
|
||||
return m;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether the given coordinates are contained within the bounds of the
|
||||
* matrix.
|
||||
* @param {number} i The i index of the coordinate.
|
||||
* @param {number} j The j index of the coordinate.
|
||||
* @return {boolean} The value at the specified coordinate.
|
||||
* @private
|
||||
*/
|
||||
goog.math.Matrix.prototype.isInBounds_ = function(i, j) {
|
||||
return i >= 0 && i < this.size_.height &&
|
||||
j >= 0 && j < this.size_.width;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Matrix multiplication is defined between two matrices only if the number of
|
||||
* columns of the first matrix is the same as the number of rows of the second
|
||||
* matrix. If A is an m-by-n matrix and B is an n-by-p matrix, then their
|
||||
* product AB is an m-by-p matrix
|
||||
*
|
||||
* @param {goog.math.Matrix} m Matrix to multiply the matrix by.
|
||||
* @return {!goog.math.Matrix} Resultant product.
|
||||
* @private
|
||||
*/
|
||||
goog.math.Matrix.prototype.matrixMultiply_ = function(m) {
|
||||
var resultMatrix = new goog.math.Matrix(this.size_.height, m.getSize().width);
|
||||
goog.math.Matrix.forEach(resultMatrix, function(val, x, y) {
|
||||
var newVal = 0;
|
||||
for (var i = 0; i < this.size_.width; i++) {
|
||||
newVal += this.getValueAt(x, i) * m.getValueAt(i, y);
|
||||
}
|
||||
resultMatrix.setValueAt(x, y, newVal);
|
||||
}, this);
|
||||
return resultMatrix;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Scalar multiplication returns a matrix of the same size as the original,
|
||||
* each value multiplied by the given value.
|
||||
*
|
||||
* @param {number} m number to multiply the matrix by.
|
||||
* @return {!goog.math.Matrix} Resultant product.
|
||||
* @private
|
||||
*/
|
||||
goog.math.Matrix.prototype.scalarMultiply_ = function(m) {
|
||||
return goog.math.Matrix.map(this, function(val, x, y) {
|
||||
return val * m;
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Swaps two rows.
|
||||
* @param {number} i1 The index of the first row to swap.
|
||||
* @param {number} i2 The index of the second row to swap.
|
||||
* @private
|
||||
*/
|
||||
goog.math.Matrix.prototype.swapRows_ = function(i1, i2) {
|
||||
var tmp = this.array_[i1];
|
||||
this.array_[i1] = this.array_[i2];
|
||||
this.array_[i2] = tmp;
|
||||
};
|
||||
144
nicer-api-docs/closure-library/closure/goog/math/range.js
Normal file
144
nicer-api-docs/closure-library/closure/goog/math/range.js
Normal file
@@ -0,0 +1,144 @@
|
||||
// Copyright 2006 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/**
|
||||
* @fileoverview A utility class for representing a numeric range.
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.math.Range');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A number range.
|
||||
* @param {number} a One end of the range.
|
||||
* @param {number} b The other end of the range.
|
||||
* @constructor
|
||||
*/
|
||||
goog.math.Range = function(a, b) {
|
||||
/**
|
||||
* The lowest value in the range.
|
||||
* @type {number}
|
||||
*/
|
||||
this.start = a < b ? a : b;
|
||||
|
||||
/**
|
||||
* The highest value in the range.
|
||||
* @type {number}
|
||||
*/
|
||||
this.end = a < b ? b : a;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!goog.math.Range} A clone of this Range.
|
||||
*/
|
||||
goog.math.Range.prototype.clone = function() {
|
||||
return new goog.math.Range(this.start, this.end);
|
||||
};
|
||||
|
||||
|
||||
if (goog.DEBUG) {
|
||||
/**
|
||||
* Returns a string representing the range.
|
||||
* @return {string} In the form [-3.5, 8.13].
|
||||
* @override
|
||||
*/
|
||||
goog.math.Range.prototype.toString = function() {
|
||||
return '[' + this.start + ', ' + this.end + ']';
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compares ranges for equality.
|
||||
* @param {goog.math.Range} a A Range.
|
||||
* @param {goog.math.Range} b A Range.
|
||||
* @return {boolean} True iff both the starts and the ends of the ranges are
|
||||
* equal, or if both ranges are null.
|
||||
*/
|
||||
goog.math.Range.equals = function(a, b) {
|
||||
if (a == b) {
|
||||
return true;
|
||||
}
|
||||
if (!a || !b) {
|
||||
return false;
|
||||
}
|
||||
return a.start == b.start && a.end == b.end;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Given two ranges on the same dimension, this method returns the intersection
|
||||
* of those ranges.
|
||||
* @param {goog.math.Range} a A Range.
|
||||
* @param {goog.math.Range} b A Range.
|
||||
* @return {goog.math.Range} A new Range representing the intersection of two
|
||||
* ranges, or null if there is no intersection. Ranges are assumed to
|
||||
* include their end points, and the intersection can be a point.
|
||||
*/
|
||||
goog.math.Range.intersection = function(a, b) {
|
||||
var c0 = Math.max(a.start, b.start);
|
||||
var c1 = Math.min(a.end, b.end);
|
||||
return (c0 <= c1) ? new goog.math.Range(c0, c1) : null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Given two ranges on the same dimension, determines whether they intersect.
|
||||
* @param {goog.math.Range} a A Range.
|
||||
* @param {goog.math.Range} b A Range.
|
||||
* @return {boolean} Whether they intersect.
|
||||
*/
|
||||
goog.math.Range.hasIntersection = function(a, b) {
|
||||
return Math.max(a.start, b.start) <= Math.min(a.end, b.end);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Given two ranges on the same dimension, this returns a range that covers
|
||||
* both ranges.
|
||||
* @param {goog.math.Range} a A Range.
|
||||
* @param {goog.math.Range} b A Range.
|
||||
* @return {!goog.math.Range} A new Range representing the bounding
|
||||
* range.
|
||||
*/
|
||||
goog.math.Range.boundingRange = function(a, b) {
|
||||
return new goog.math.Range(Math.min(a.start, b.start),
|
||||
Math.max(a.end, b.end));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Given two ranges, returns true if the first range completely overlaps the
|
||||
* second.
|
||||
* @param {goog.math.Range} a The first Range.
|
||||
* @param {goog.math.Range} b The second Range.
|
||||
* @return {boolean} True if b is contained inside a, false otherwise.
|
||||
*/
|
||||
goog.math.Range.contains = function(a, b) {
|
||||
return a.start <= b.start && a.end >= b.end;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Given a range and a point, returns true if the range contains the point.
|
||||
* @param {goog.math.Range} range The range.
|
||||
* @param {number} p The point.
|
||||
* @return {boolean} True if p is contained inside range, false otherwise.
|
||||
*/
|
||||
goog.math.Range.containsPoint = function(range, p) {
|
||||
return range.start <= p && range.end >= p;
|
||||
};
|
||||
394
nicer-api-docs/closure-library/closure/goog/math/rangeset.js
Normal file
394
nicer-api-docs/closure-library/closure/goog/math/rangeset.js
Normal file
@@ -0,0 +1,394 @@
|
||||
// Copyright 2009 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/**
|
||||
* @fileoverview A RangeSet is a structure that manages a list of ranges.
|
||||
* Numeric ranges may be added and removed from the RangeSet, and the set may
|
||||
* be queried for the presence or absence of individual values or ranges of
|
||||
* values.
|
||||
*
|
||||
* This may be used, for example, to track the availability of sparse elements
|
||||
* in an array without iterating over the entire array.
|
||||
*
|
||||
* @author brenneman@google.com (Shawn Brenneman)
|
||||
*/
|
||||
|
||||
goog.provide('goog.math.RangeSet');
|
||||
|
||||
goog.require('goog.array');
|
||||
goog.require('goog.iter.Iterator');
|
||||
goog.require('goog.iter.StopIteration');
|
||||
goog.require('goog.math.Range');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new RangeSet, which can store numeric ranges.
|
||||
*
|
||||
* Ranges are treated as half-closed: that is, they are exclusive of their end
|
||||
* value [start, end).
|
||||
*
|
||||
* New ranges added to the set which overlap the values in one or more existing
|
||||
* ranges will be merged.
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
goog.math.RangeSet = function() {
|
||||
/**
|
||||
* A sorted list of ranges that represent the values in the set.
|
||||
* @type {!Array.<!goog.math.Range>}
|
||||
* @private
|
||||
*/
|
||||
this.ranges_ = [];
|
||||
};
|
||||
|
||||
|
||||
if (goog.DEBUG) {
|
||||
/**
|
||||
* @return {string} A debug string in the form [[1, 5], [8, 9], [15, 30]].
|
||||
* @override
|
||||
*/
|
||||
goog.math.RangeSet.prototype.toString = function() {
|
||||
return '[' + this.ranges_.join(', ') + ']';
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compares two sets for equality.
|
||||
*
|
||||
* @param {goog.math.RangeSet} a A range set.
|
||||
* @param {goog.math.RangeSet} b A range set.
|
||||
* @return {boolean} Whether both sets contain the same values.
|
||||
*/
|
||||
goog.math.RangeSet.equals = function(a, b) {
|
||||
// Fast check for object equality. Also succeeds if a and b are both null.
|
||||
return a == b || !!(a && b && goog.array.equals(a.ranges_, b.ranges_,
|
||||
goog.math.Range.equals));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!goog.math.RangeSet} A new RangeSet containing the same values as
|
||||
* this one.
|
||||
*/
|
||||
goog.math.RangeSet.prototype.clone = function() {
|
||||
var set = new goog.math.RangeSet();
|
||||
|
||||
for (var i = this.ranges_.length; i--;) {
|
||||
set.ranges_[i] = this.ranges_[i].clone();
|
||||
}
|
||||
|
||||
return set;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds a range to the set. If the new range overlaps existing values, those
|
||||
* ranges will be merged.
|
||||
*
|
||||
* @param {goog.math.Range} a The range to add.
|
||||
*/
|
||||
goog.math.RangeSet.prototype.add = function(a) {
|
||||
if (a.end <= a.start) {
|
||||
// Empty ranges are ignored.
|
||||
return;
|
||||
}
|
||||
|
||||
a = a.clone();
|
||||
|
||||
// Find the insertion point.
|
||||
for (var i = 0, b; b = this.ranges_[i]; i++) {
|
||||
if (a.start <= b.end) {
|
||||
a.start = Math.min(a.start, b.start);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var insertionPoint = i;
|
||||
|
||||
for (; b = this.ranges_[i]; i++) {
|
||||
if (a.end < b.start) {
|
||||
break;
|
||||
}
|
||||
a.end = Math.max(a.end, b.end);
|
||||
}
|
||||
|
||||
this.ranges_.splice(insertionPoint, i - insertionPoint, a);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes a range of values from the set.
|
||||
*
|
||||
* @param {goog.math.Range} a The range to remove.
|
||||
*/
|
||||
goog.math.RangeSet.prototype.remove = function(a) {
|
||||
if (a.end <= a.start) {
|
||||
// Empty ranges are ignored.
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the insertion point.
|
||||
for (var i = 0, b; b = this.ranges_[i]; i++) {
|
||||
if (a.start < b.end) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!b || a.end < b.start) {
|
||||
// The range being removed doesn't overlap any existing range. Exit early.
|
||||
return;
|
||||
}
|
||||
|
||||
var insertionPoint = i;
|
||||
|
||||
if (a.start > b.start) {
|
||||
// There is an overlap with the nearest range. Modify it accordingly.
|
||||
insertionPoint++;
|
||||
|
||||
if (a.end < b.end) {
|
||||
goog.array.insertAt(this.ranges_,
|
||||
new goog.math.Range(a.end, b.end),
|
||||
insertionPoint);
|
||||
}
|
||||
b.end = a.start;
|
||||
}
|
||||
|
||||
for (i = insertionPoint; b = this.ranges_[i]; i++) {
|
||||
b.start = Math.max(a.end, b.start);
|
||||
if (a.end < b.end) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.ranges_.splice(insertionPoint, i - insertionPoint);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Determines whether a given range is in the set. Only succeeds if the entire
|
||||
* range is available.
|
||||
*
|
||||
* @param {goog.math.Range} a The query range.
|
||||
* @return {boolean} Whether the entire requested range is set.
|
||||
*/
|
||||
goog.math.RangeSet.prototype.contains = function(a) {
|
||||
if (a.end <= a.start) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var i = 0, b; b = this.ranges_[i]; i++) {
|
||||
if (a.start < b.end) {
|
||||
if (a.end >= b.start) {
|
||||
return goog.math.Range.contains(b, a);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Determines whether a given value is set in the RangeSet.
|
||||
*
|
||||
* @param {number} value The value to test.
|
||||
* @return {boolean} Whether the given value is in the set.
|
||||
*/
|
||||
goog.math.RangeSet.prototype.containsValue = function(value) {
|
||||
for (var i = 0, b; b = this.ranges_[i]; i++) {
|
||||
if (value < b.end) {
|
||||
if (value >= b.start) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the union of this RangeSet with another.
|
||||
*
|
||||
* @param {goog.math.RangeSet} set Another RangeSet.
|
||||
* @return {!goog.math.RangeSet} A new RangeSet containing all values from
|
||||
* either set.
|
||||
*/
|
||||
goog.math.RangeSet.prototype.union = function(set) {
|
||||
// TODO(brenneman): A linear-time merge would be preferable if it is ever a
|
||||
// bottleneck.
|
||||
set = set.clone();
|
||||
|
||||
for (var i = 0, a; a = this.ranges_[i]; i++) {
|
||||
set.add(a);
|
||||
}
|
||||
|
||||
return set;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Subtracts the ranges of another set from this one, returning the result
|
||||
* as a new RangeSet.
|
||||
*
|
||||
* @param {!goog.math.RangeSet} set The RangeSet to subtract.
|
||||
* @return {!goog.math.RangeSet} A new RangeSet containing all values in this
|
||||
* set minus the values of the input set.
|
||||
*/
|
||||
goog.math.RangeSet.prototype.difference = function(set) {
|
||||
var ret = this.clone();
|
||||
|
||||
for (var i = 0, a; a = set.ranges_[i]; i++) {
|
||||
ret.remove(a);
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Intersects this RangeSet with another.
|
||||
*
|
||||
* @param {goog.math.RangeSet} set The RangeSet to intersect with.
|
||||
* @return {!goog.math.RangeSet} A new RangeSet containing all values set in
|
||||
* both this and the input set.
|
||||
*/
|
||||
goog.math.RangeSet.prototype.intersection = function(set) {
|
||||
if (this.isEmpty() || set.isEmpty()) {
|
||||
return new goog.math.RangeSet();
|
||||
}
|
||||
|
||||
return this.difference(set.inverse(this.getBounds()));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a subset of this set over the input range.
|
||||
*
|
||||
* @param {goog.math.Range} range The range to copy into the slice.
|
||||
* @return {!goog.math.RangeSet} A new RangeSet with a copy of the values in the
|
||||
* input range.
|
||||
*/
|
||||
goog.math.RangeSet.prototype.slice = function(range) {
|
||||
var set = new goog.math.RangeSet();
|
||||
if (range.start >= range.end) {
|
||||
return set;
|
||||
}
|
||||
|
||||
for (var i = 0, b; b = this.ranges_[i]; i++) {
|
||||
if (b.end <= range.start) {
|
||||
continue;
|
||||
}
|
||||
if (b.start > range.end) {
|
||||
break;
|
||||
}
|
||||
|
||||
set.add(new goog.math.Range(Math.max(range.start, b.start),
|
||||
Math.min(range.end, b.end)));
|
||||
}
|
||||
|
||||
return set;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates an inverted slice of this set over the input range.
|
||||
*
|
||||
* @param {goog.math.Range} range The range to copy into the slice.
|
||||
* @return {!goog.math.RangeSet} A new RangeSet containing inverted values from
|
||||
* the original over the input range.
|
||||
*/
|
||||
goog.math.RangeSet.prototype.inverse = function(range) {
|
||||
var set = new goog.math.RangeSet();
|
||||
|
||||
set.add(range);
|
||||
for (var i = 0, b; b = this.ranges_[i]; i++) {
|
||||
if (range.start >= b.end) {
|
||||
continue;
|
||||
}
|
||||
if (range.end < b.start) {
|
||||
break;
|
||||
}
|
||||
|
||||
set.remove(b);
|
||||
}
|
||||
|
||||
return set;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} The sum of the lengths of ranges covered in the set.
|
||||
*/
|
||||
goog.math.RangeSet.prototype.coveredLength = function() {
|
||||
return /** @type {number} */ (goog.array.reduce(
|
||||
this.ranges_,
|
||||
function(res, range) {
|
||||
return res + range.end - range.start;
|
||||
}, 0));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {goog.math.Range} The total range this set covers, ignoring any
|
||||
* gaps between ranges.
|
||||
*/
|
||||
goog.math.RangeSet.prototype.getBounds = function() {
|
||||
if (this.ranges_.length) {
|
||||
return new goog.math.Range(this.ranges_[0].start,
|
||||
goog.array.peek(this.ranges_).end);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} Whether any ranges are currently in the set.
|
||||
*/
|
||||
goog.math.RangeSet.prototype.isEmpty = function() {
|
||||
return this.ranges_.length == 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Removes all values in the set.
|
||||
*/
|
||||
goog.math.RangeSet.prototype.clear = function() {
|
||||
this.ranges_.length = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns an iterator that iterates over the ranges in the RangeSet.
|
||||
*
|
||||
* @param {boolean=} opt_keys Ignored for RangeSets.
|
||||
* @return {!goog.iter.Iterator} An iterator over the values in the set.
|
||||
*/
|
||||
goog.math.RangeSet.prototype.__iterator__ = function(opt_keys) {
|
||||
var i = 0;
|
||||
var list = this.ranges_;
|
||||
|
||||
var iterator = new goog.iter.Iterator();
|
||||
iterator.next = function() {
|
||||
if (i >= list.length) {
|
||||
throw goog.iter.StopIteration;
|
||||
}
|
||||
return list[i++].clone();
|
||||
};
|
||||
|
||||
return iterator;
|
||||
};
|
||||
463
nicer-api-docs/closure-library/closure/goog/math/rect.js
Normal file
463
nicer-api-docs/closure-library/closure/goog/math/rect.js
Normal file
@@ -0,0 +1,463 @@
|
||||
// Copyright 2006 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/**
|
||||
* @fileoverview A utility class for representing rectangles.
|
||||
*/
|
||||
|
||||
goog.provide('goog.math.Rect');
|
||||
|
||||
goog.require('goog.math.Box');
|
||||
goog.require('goog.math.Coordinate');
|
||||
goog.require('goog.math.Size');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Class for representing rectangular regions.
|
||||
* @param {number} x Left.
|
||||
* @param {number} y Top.
|
||||
* @param {number} w Width.
|
||||
* @param {number} h Height.
|
||||
* @constructor
|
||||
*/
|
||||
goog.math.Rect = function(x, y, w, h) {
|
||||
/** @type {number} */
|
||||
this.left = x;
|
||||
|
||||
/** @type {number} */
|
||||
this.top = y;
|
||||
|
||||
/** @type {number} */
|
||||
this.width = w;
|
||||
|
||||
/** @type {number} */
|
||||
this.height = h;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!goog.math.Rect} A new copy of this Rectangle.
|
||||
*/
|
||||
goog.math.Rect.prototype.clone = function() {
|
||||
return new goog.math.Rect(this.left, this.top, this.width, this.height);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a new Box object with the same position and dimensions as this
|
||||
* rectangle.
|
||||
* @return {!goog.math.Box} A new Box representation of this Rectangle.
|
||||
*/
|
||||
goog.math.Rect.prototype.toBox = function() {
|
||||
var right = this.left + this.width;
|
||||
var bottom = this.top + this.height;
|
||||
return new goog.math.Box(this.top,
|
||||
right,
|
||||
bottom,
|
||||
this.left);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new Rect object with the same position and dimensions as a given
|
||||
* Box. Note that this is only the inverse of toBox if left/top are defined.
|
||||
* @param {goog.math.Box} box A box.
|
||||
* @return {!goog.math.Rect} A new Rect initialized with the box's position
|
||||
* and size.
|
||||
*/
|
||||
goog.math.Rect.createFromBox = function(box) {
|
||||
return new goog.math.Rect(box.left, box.top,
|
||||
box.right - box.left, box.bottom - box.top);
|
||||
};
|
||||
|
||||
|
||||
if (goog.DEBUG) {
|
||||
/**
|
||||
* Returns a nice string representing size and dimensions of rectangle.
|
||||
* @return {string} In the form (50, 73 - 75w x 25h).
|
||||
* @override
|
||||
*/
|
||||
goog.math.Rect.prototype.toString = function() {
|
||||
return '(' + this.left + ', ' + this.top + ' - ' + this.width + 'w x ' +
|
||||
this.height + 'h)';
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compares rectangles for equality.
|
||||
* @param {goog.math.Rect} a A Rectangle.
|
||||
* @param {goog.math.Rect} b A Rectangle.
|
||||
* @return {boolean} True iff the rectangles have the same left, top, width,
|
||||
* and height, or if both are null.
|
||||
*/
|
||||
goog.math.Rect.equals = function(a, b) {
|
||||
if (a == b) {
|
||||
return true;
|
||||
}
|
||||
if (!a || !b) {
|
||||
return false;
|
||||
}
|
||||
return a.left == b.left && a.width == b.width &&
|
||||
a.top == b.top && a.height == b.height;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Computes the intersection of this rectangle and the rectangle parameter. If
|
||||
* there is no intersection, returns false and leaves this rectangle as is.
|
||||
* @param {goog.math.Rect} rect A Rectangle.
|
||||
* @return {boolean} True iff this rectangle intersects with the parameter.
|
||||
*/
|
||||
goog.math.Rect.prototype.intersection = function(rect) {
|
||||
var x0 = Math.max(this.left, rect.left);
|
||||
var x1 = Math.min(this.left + this.width, rect.left + rect.width);
|
||||
|
||||
if (x0 <= x1) {
|
||||
var y0 = Math.max(this.top, rect.top);
|
||||
var y1 = Math.min(this.top + this.height, rect.top + rect.height);
|
||||
|
||||
if (y0 <= y1) {
|
||||
this.left = x0;
|
||||
this.top = y0;
|
||||
this.width = x1 - x0;
|
||||
this.height = y1 - y0;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the intersection of two rectangles. Two rectangles intersect if they
|
||||
* touch at all, for example, two zero width and height rectangles would
|
||||
* intersect if they had the same top and left.
|
||||
* @param {goog.math.Rect} a A Rectangle.
|
||||
* @param {goog.math.Rect} b A Rectangle.
|
||||
* @return {goog.math.Rect} A new intersection rect (even if width and height
|
||||
* are 0), or null if there is no intersection.
|
||||
*/
|
||||
goog.math.Rect.intersection = function(a, b) {
|
||||
// There is no nice way to do intersection via a clone, because any such
|
||||
// clone might be unnecessary if this function returns null. So, we duplicate
|
||||
// code from above.
|
||||
|
||||
var x0 = Math.max(a.left, b.left);
|
||||
var x1 = Math.min(a.left + a.width, b.left + b.width);
|
||||
|
||||
if (x0 <= x1) {
|
||||
var y0 = Math.max(a.top, b.top);
|
||||
var y1 = Math.min(a.top + a.height, b.top + b.height);
|
||||
|
||||
if (y0 <= y1) {
|
||||
return new goog.math.Rect(x0, y0, x1 - x0, y1 - y0);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether two rectangles intersect. Two rectangles intersect if they
|
||||
* touch at all, for example, two zero width and height rectangles would
|
||||
* intersect if they had the same top and left.
|
||||
* @param {goog.math.Rect} a A Rectangle.
|
||||
* @param {goog.math.Rect} b A Rectangle.
|
||||
* @return {boolean} Whether a and b intersect.
|
||||
*/
|
||||
goog.math.Rect.intersects = function(a, b) {
|
||||
return (a.left <= b.left + b.width && b.left <= a.left + a.width &&
|
||||
a.top <= b.top + b.height && b.top <= a.top + a.height);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether a rectangle intersects this rectangle.
|
||||
* @param {goog.math.Rect} rect A rectangle.
|
||||
* @return {boolean} Whether rect intersects this rectangle.
|
||||
*/
|
||||
goog.math.Rect.prototype.intersects = function(rect) {
|
||||
return goog.math.Rect.intersects(this, rect);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Computes the difference regions between two rectangles. The return value is
|
||||
* an array of 0 to 4 rectangles defining the remaining regions of the first
|
||||
* rectangle after the second has been subtracted.
|
||||
* @param {goog.math.Rect} a A Rectangle.
|
||||
* @param {goog.math.Rect} b A Rectangle.
|
||||
* @return {!Array.<!goog.math.Rect>} An array with 0 to 4 rectangles which
|
||||
* together define the difference area of rectangle a minus rectangle b.
|
||||
*/
|
||||
goog.math.Rect.difference = function(a, b) {
|
||||
var intersection = goog.math.Rect.intersection(a, b);
|
||||
if (!intersection || !intersection.height || !intersection.width) {
|
||||
return [a.clone()];
|
||||
}
|
||||
|
||||
var result = [];
|
||||
|
||||
var top = a.top;
|
||||
var height = a.height;
|
||||
|
||||
var ar = a.left + a.width;
|
||||
var ab = a.top + a.height;
|
||||
|
||||
var br = b.left + b.width;
|
||||
var bb = b.top + b.height;
|
||||
|
||||
// Subtract off any area on top where A extends past B
|
||||
if (b.top > a.top) {
|
||||
result.push(new goog.math.Rect(a.left, a.top, a.width, b.top - a.top));
|
||||
top = b.top;
|
||||
// If we're moving the top down, we also need to subtract the height diff.
|
||||
height -= b.top - a.top;
|
||||
}
|
||||
// Subtract off any area on bottom where A extends past B
|
||||
if (bb < ab) {
|
||||
result.push(new goog.math.Rect(a.left, bb, a.width, ab - bb));
|
||||
height = bb - top;
|
||||
}
|
||||
// Subtract any area on left where A extends past B
|
||||
if (b.left > a.left) {
|
||||
result.push(new goog.math.Rect(a.left, top, b.left - a.left, height));
|
||||
}
|
||||
// Subtract any area on right where A extends past B
|
||||
if (br < ar) {
|
||||
result.push(new goog.math.Rect(br, top, ar - br, height));
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Computes the difference regions between this rectangle and {@code rect}. The
|
||||
* return value is an array of 0 to 4 rectangles defining the remaining regions
|
||||
* of this rectangle after the other has been subtracted.
|
||||
* @param {goog.math.Rect} rect A Rectangle.
|
||||
* @return {!Array.<!goog.math.Rect>} An array with 0 to 4 rectangles which
|
||||
* together define the difference area of rectangle a minus rectangle b.
|
||||
*/
|
||||
goog.math.Rect.prototype.difference = function(rect) {
|
||||
return goog.math.Rect.difference(this, rect);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Expand this rectangle to also include the area of the given rectangle.
|
||||
* @param {goog.math.Rect} rect The other rectangle.
|
||||
*/
|
||||
goog.math.Rect.prototype.boundingRect = function(rect) {
|
||||
// We compute right and bottom before we change left and top below.
|
||||
var right = Math.max(this.left + this.width, rect.left + rect.width);
|
||||
var bottom = Math.max(this.top + this.height, rect.top + rect.height);
|
||||
|
||||
this.left = Math.min(this.left, rect.left);
|
||||
this.top = Math.min(this.top, rect.top);
|
||||
|
||||
this.width = right - this.left;
|
||||
this.height = bottom - this.top;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a new rectangle which completely contains both input rectangles.
|
||||
* @param {goog.math.Rect} a A rectangle.
|
||||
* @param {goog.math.Rect} b A rectangle.
|
||||
* @return {goog.math.Rect} A new bounding rect, or null if either rect is
|
||||
* null.
|
||||
*/
|
||||
goog.math.Rect.boundingRect = function(a, b) {
|
||||
if (!a || !b) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var clone = a.clone();
|
||||
clone.boundingRect(b);
|
||||
|
||||
return clone;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Tests whether this rectangle entirely contains another rectangle or
|
||||
* coordinate.
|
||||
*
|
||||
* @param {goog.math.Rect|goog.math.Coordinate} another The rectangle or
|
||||
* coordinate to test for containment.
|
||||
* @return {boolean} Whether this rectangle contains given rectangle or
|
||||
* coordinate.
|
||||
*/
|
||||
goog.math.Rect.prototype.contains = function(another) {
|
||||
if (another instanceof goog.math.Rect) {
|
||||
return this.left <= another.left &&
|
||||
this.left + this.width >= another.left + another.width &&
|
||||
this.top <= another.top &&
|
||||
this.top + this.height >= another.top + another.height;
|
||||
} else { // (another instanceof goog.math.Coordinate)
|
||||
return another.x >= this.left &&
|
||||
another.x <= this.left + this.width &&
|
||||
another.y >= this.top &&
|
||||
another.y <= this.top + this.height;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {!goog.math.Coordinate} point A coordinate.
|
||||
* @return {number} The squared distance between the point and the closest
|
||||
* point inside the rectangle. Returns 0 if the point is inside the
|
||||
* rectangle.
|
||||
*/
|
||||
goog.math.Rect.prototype.squaredDistance = function(point) {
|
||||
var dx = point.x < this.left ?
|
||||
this.left - point.x : Math.max(point.x - (this.left + this.width), 0);
|
||||
var dy = point.y < this.top ?
|
||||
this.top - point.y : Math.max(point.y - (this.top + this.height), 0);
|
||||
return dx * dx + dy * dy;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {!goog.math.Coordinate} point A coordinate.
|
||||
* @return {number} The distance between the point and the closest point
|
||||
* inside the rectangle. Returns 0 if the point is inside the rectangle.
|
||||
*/
|
||||
goog.math.Rect.prototype.distance = function(point) {
|
||||
return Math.sqrt(this.squaredDistance(point));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!goog.math.Size} The size of this rectangle.
|
||||
*/
|
||||
goog.math.Rect.prototype.getSize = function() {
|
||||
return new goog.math.Size(this.width, this.height);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!goog.math.Coordinate} A new coordinate for the top-left corner of
|
||||
* the rectangle.
|
||||
*/
|
||||
goog.math.Rect.prototype.getTopLeft = function() {
|
||||
return new goog.math.Coordinate(this.left, this.top);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!goog.math.Coordinate} A new coordinate for the center of the
|
||||
* rectangle.
|
||||
*/
|
||||
goog.math.Rect.prototype.getCenter = function() {
|
||||
return new goog.math.Coordinate(
|
||||
this.left + this.width / 2, this.top + this.height / 2);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!goog.math.Coordinate} A new coordinate for the bottom-right corner
|
||||
* of the rectangle.
|
||||
*/
|
||||
goog.math.Rect.prototype.getBottomRight = function() {
|
||||
return new goog.math.Coordinate(
|
||||
this.left + this.width, this.top + this.height);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Rounds the fields to the next larger integer values.
|
||||
* @return {!goog.math.Rect} This rectangle with ceil'd fields.
|
||||
*/
|
||||
goog.math.Rect.prototype.ceil = function() {
|
||||
this.left = Math.ceil(this.left);
|
||||
this.top = Math.ceil(this.top);
|
||||
this.width = Math.ceil(this.width);
|
||||
this.height = Math.ceil(this.height);
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Rounds the fields to the next smaller integer values.
|
||||
* @return {!goog.math.Rect} This rectangle with floored fields.
|
||||
*/
|
||||
goog.math.Rect.prototype.floor = function() {
|
||||
this.left = Math.floor(this.left);
|
||||
this.top = Math.floor(this.top);
|
||||
this.width = Math.floor(this.width);
|
||||
this.height = Math.floor(this.height);
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Rounds the fields to nearest integer values.
|
||||
* @return {!goog.math.Rect} This rectangle with rounded fields.
|
||||
*/
|
||||
goog.math.Rect.prototype.round = function() {
|
||||
this.left = Math.round(this.left);
|
||||
this.top = Math.round(this.top);
|
||||
this.width = Math.round(this.width);
|
||||
this.height = Math.round(this.height);
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Translates this rectangle by the given offsets. If a
|
||||
* {@code goog.math.Coordinate} is given, then the left and top values are
|
||||
* translated by the coordinate's x and y values. Otherwise, top and left are
|
||||
* translated by {@code tx} and {@code opt_ty} respectively.
|
||||
* @param {number|goog.math.Coordinate} tx The value to translate left by or the
|
||||
* the coordinate to translate this rect by.
|
||||
* @param {number=} opt_ty The value to translate top by.
|
||||
* @return {!goog.math.Rect} This rectangle after translating.
|
||||
*/
|
||||
goog.math.Rect.prototype.translate = function(tx, opt_ty) {
|
||||
if (tx instanceof goog.math.Coordinate) {
|
||||
this.left += tx.x;
|
||||
this.top += tx.y;
|
||||
} else {
|
||||
this.left += tx;
|
||||
if (goog.isNumber(opt_ty)) {
|
||||
this.top += opt_ty;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Scales this rectangle by the given scale factors. The left and width values
|
||||
* are scaled by {@code sx} and the top and height values are scaled by
|
||||
* {@code opt_sy}. If {@code opt_sy} is not given, then all fields are scaled
|
||||
* by {@code sx}.
|
||||
* @param {number} sx The scale factor to use for the x dimension.
|
||||
* @param {number=} opt_sy The scale factor to use for the y dimension.
|
||||
* @return {!goog.math.Rect} This rectangle after scaling.
|
||||
*/
|
||||
goog.math.Rect.prototype.scale = function(sx, opt_sy) {
|
||||
var sy = goog.isNumber(opt_sy) ? opt_sy : sx;
|
||||
this.left *= sx;
|
||||
this.width *= sx;
|
||||
this.top *= sy;
|
||||
this.height *= sy;
|
||||
return this;
|
||||
};
|
||||
206
nicer-api-docs/closure-library/closure/goog/math/size.js
Normal file
206
nicer-api-docs/closure-library/closure/goog/math/size.js
Normal file
@@ -0,0 +1,206 @@
|
||||
// Copyright 2007 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/**
|
||||
* @fileoverview A utility class for representing two-dimensional sizes.
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.math.Size');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Class for representing sizes consisting of a width and height. Undefined
|
||||
* width and height support is deprecated and results in compiler warning.
|
||||
* @param {number} width Width.
|
||||
* @param {number} height Height.
|
||||
* @constructor
|
||||
*/
|
||||
goog.math.Size = function(width, height) {
|
||||
/**
|
||||
* Width
|
||||
* @type {number}
|
||||
*/
|
||||
this.width = width;
|
||||
|
||||
/**
|
||||
* Height
|
||||
* @type {number}
|
||||
*/
|
||||
this.height = height;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Compares sizes for equality.
|
||||
* @param {goog.math.Size} a A Size.
|
||||
* @param {goog.math.Size} b A Size.
|
||||
* @return {boolean} True iff the sizes have equal widths and equal
|
||||
* heights, or if both are null.
|
||||
*/
|
||||
goog.math.Size.equals = function(a, b) {
|
||||
if (a == b) {
|
||||
return true;
|
||||
}
|
||||
if (!a || !b) {
|
||||
return false;
|
||||
}
|
||||
return a.width == b.width && a.height == b.height;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!goog.math.Size} A new copy of the Size.
|
||||
*/
|
||||
goog.math.Size.prototype.clone = function() {
|
||||
return new goog.math.Size(this.width, this.height);
|
||||
};
|
||||
|
||||
|
||||
if (goog.DEBUG) {
|
||||
/**
|
||||
* Returns a nice string representing size.
|
||||
* @return {string} In the form (50 x 73).
|
||||
* @override
|
||||
*/
|
||||
goog.math.Size.prototype.toString = function() {
|
||||
return '(' + this.width + ' x ' + this.height + ')';
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} The longer of the two dimensions in the size.
|
||||
*/
|
||||
goog.math.Size.prototype.getLongest = function() {
|
||||
return Math.max(this.width, this.height);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} The shorter of the two dimensions in the size.
|
||||
*/
|
||||
goog.math.Size.prototype.getShortest = function() {
|
||||
return Math.min(this.width, this.height);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} The area of the size (width * height).
|
||||
*/
|
||||
goog.math.Size.prototype.area = function() {
|
||||
return this.width * this.height;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} The perimeter of the size (width + height) * 2.
|
||||
*/
|
||||
goog.math.Size.prototype.perimeter = function() {
|
||||
return (this.width + this.height) * 2;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {number} The ratio of the size's width to its height.
|
||||
*/
|
||||
goog.math.Size.prototype.aspectRatio = function() {
|
||||
return this.width / this.height;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {boolean} True if the size has zero area, false if both dimensions
|
||||
* are non-zero numbers.
|
||||
*/
|
||||
goog.math.Size.prototype.isEmpty = function() {
|
||||
return !this.area();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Clamps the width and height parameters upward to integer values.
|
||||
* @return {!goog.math.Size} This size with ceil'd components.
|
||||
*/
|
||||
goog.math.Size.prototype.ceil = function() {
|
||||
this.width = Math.ceil(this.width);
|
||||
this.height = Math.ceil(this.height);
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {!goog.math.Size} target The target size.
|
||||
* @return {boolean} True if this Size is the same size or smaller than the
|
||||
* target size in both dimensions.
|
||||
*/
|
||||
goog.math.Size.prototype.fitsInside = function(target) {
|
||||
return this.width <= target.width && this.height <= target.height;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Clamps the width and height parameters downward to integer values.
|
||||
* @return {!goog.math.Size} This size with floored components.
|
||||
*/
|
||||
goog.math.Size.prototype.floor = function() {
|
||||
this.width = Math.floor(this.width);
|
||||
this.height = Math.floor(this.height);
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Rounds the width and height parameters to integer values.
|
||||
* @return {!goog.math.Size} This size with rounded components.
|
||||
*/
|
||||
goog.math.Size.prototype.round = function() {
|
||||
this.width = Math.round(this.width);
|
||||
this.height = Math.round(this.height);
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Scales this size by the given scale factors. The width and height are scaled
|
||||
* by {@code sx} and {@code opt_sy} respectively. If {@code opt_sy} is not
|
||||
* given, then {@code sx} is used for both the width and height.
|
||||
* @param {number} sx The scale factor to use for the width.
|
||||
* @param {number=} opt_sy The scale factor to use for the height.
|
||||
* @return {!goog.math.Size} This Size object after scaling.
|
||||
*/
|
||||
goog.math.Size.prototype.scale = function(sx, opt_sy) {
|
||||
var sy = goog.isNumber(opt_sy) ? opt_sy : sx;
|
||||
this.width *= sx;
|
||||
this.height *= sy;
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Uniformly scales the size to fit inside the dimensions of a given size. The
|
||||
* original aspect ratio will be preserved.
|
||||
*
|
||||
* This function assumes that both Sizes contain strictly positive dimensions.
|
||||
* @param {!goog.math.Size} target The target size.
|
||||
* @return {!goog.math.Size} This Size object, after optional scaling.
|
||||
*/
|
||||
goog.math.Size.prototype.scaleToFit = function(target) {
|
||||
var s = this.aspectRatio() > target.aspectRatio() ?
|
||||
target.width / this.width :
|
||||
target.height / this.height;
|
||||
|
||||
return this.scale(s);
|
||||
};
|
||||
73
nicer-api-docs/closure-library/closure/goog/math/tdma.js
Normal file
73
nicer-api-docs/closure-library/closure/goog/math/tdma.js
Normal file
@@ -0,0 +1,73 @@
|
||||
// Copyright 2011 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/**
|
||||
* @fileoverview The Tridiagonal matrix algorithm solver solves a special
|
||||
* version of a sparse linear system Ax = b where A is tridiagonal.
|
||||
*
|
||||
* See http://en.wikipedia.org/wiki/Tridiagonal_matrix_algorithm
|
||||
*
|
||||
*/
|
||||
|
||||
goog.provide('goog.math.tdma');
|
||||
|
||||
|
||||
/**
|
||||
* Solves a linear system where the matrix is square tri-diagonal. That is,
|
||||
* given a system of equations:
|
||||
*
|
||||
* A * result = vecRight,
|
||||
*
|
||||
* this class computes result = inv(A) * vecRight, where A has the special form
|
||||
* of a tri-diagonal matrix:
|
||||
*
|
||||
* |dia(0) sup(0) 0 0 ... 0|
|
||||
* |sub(0) dia(1) sup(1) 0 ... 0|
|
||||
* A =| ... |
|
||||
* |0 ... 0 sub(n-2) dia(n-1) sup(n-1)|
|
||||
* |0 ... 0 0 sub(n-1) dia(n)|
|
||||
*
|
||||
* @param {!Array.<number>} subDiag The sub diagonal of the matrix.
|
||||
* @param {!Array.<number>} mainDiag The main diagonal of the matrix.
|
||||
* @param {!Array.<number>} supDiag The super diagonal of the matrix.
|
||||
* @param {!Array.<number>} vecRight The right vector of the system
|
||||
* of equations.
|
||||
* @param {Array.<number>=} opt_result The optional array to store the result.
|
||||
* @return {!Array.<number>} The vector that is the solution to the system.
|
||||
*/
|
||||
goog.math.tdma.solve = function(
|
||||
subDiag, mainDiag, supDiag, vecRight, opt_result) {
|
||||
// Make a local copy of the main diagonal and the right vector.
|
||||
mainDiag = mainDiag.slice();
|
||||
vecRight = vecRight.slice();
|
||||
|
||||
// The dimension of the matrix.
|
||||
var nDim = mainDiag.length;
|
||||
|
||||
// Construct a modified linear system of equations with the same solution
|
||||
// as the input one.
|
||||
for (var i = 1; i < nDim; ++i) {
|
||||
var m = subDiag[i - 1] / mainDiag[i - 1];
|
||||
mainDiag[i] = mainDiag[i] - m * supDiag[i - 1];
|
||||
vecRight[i] = vecRight[i] - m * vecRight[i - 1];
|
||||
}
|
||||
|
||||
// Solve the new system of equations by simple back-substitution.
|
||||
var result = opt_result || new Array(vecRight.length);
|
||||
result[nDim - 1] = vecRight[nDim - 1] / mainDiag[nDim - 1];
|
||||
for (i = nDim - 2; i >= 0; --i) {
|
||||
result[i] = (vecRight[i] - supDiag[i] * result[i + 1]) / mainDiag[i];
|
||||
}
|
||||
return result;
|
||||
};
|
||||
283
nicer-api-docs/closure-library/closure/goog/math/vec2.js
Normal file
283
nicer-api-docs/closure-library/closure/goog/math/vec2.js
Normal file
@@ -0,0 +1,283 @@
|
||||
// Copyright 2007 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/**
|
||||
* @fileoverview Defines a 2-element vector class that can be used for
|
||||
* coordinate math, useful for animation systems and point manipulation.
|
||||
*
|
||||
* Vec2 objects inherit from goog.math.Coordinate and may be used wherever a
|
||||
* Coordinate is required. Where appropriate, Vec2 functions accept both Vec2
|
||||
* and Coordinate objects as input.
|
||||
*
|
||||
* @author brenneman@google.com (Shawn Brenneman)
|
||||
*/
|
||||
|
||||
goog.provide('goog.math.Vec2');
|
||||
|
||||
goog.require('goog.math');
|
||||
goog.require('goog.math.Coordinate');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Class for a two-dimensional vector object and assorted functions useful for
|
||||
* manipulating points.
|
||||
*
|
||||
* @param {number} x The x coordinate for the vector.
|
||||
* @param {number} y The y coordinate for the vector.
|
||||
* @constructor
|
||||
* @extends {goog.math.Coordinate}
|
||||
*/
|
||||
goog.math.Vec2 = function(x, y) {
|
||||
/**
|
||||
* X-value
|
||||
* @type {number}
|
||||
*/
|
||||
this.x = x;
|
||||
|
||||
/**
|
||||
* Y-value
|
||||
* @type {number}
|
||||
*/
|
||||
this.y = y;
|
||||
};
|
||||
goog.inherits(goog.math.Vec2, goog.math.Coordinate);
|
||||
|
||||
|
||||
/**
|
||||
* @return {!goog.math.Vec2} A random unit-length vector.
|
||||
*/
|
||||
goog.math.Vec2.randomUnit = function() {
|
||||
var angle = Math.random() * Math.PI * 2;
|
||||
return new goog.math.Vec2(Math.cos(angle), Math.sin(angle));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!goog.math.Vec2} A random vector inside the unit-disc.
|
||||
*/
|
||||
goog.math.Vec2.random = function() {
|
||||
var mag = Math.sqrt(Math.random());
|
||||
var angle = Math.random() * Math.PI * 2;
|
||||
|
||||
return new goog.math.Vec2(Math.cos(angle) * mag, Math.sin(angle) * mag);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a new Vec2 object from a given coordinate.
|
||||
* @param {!goog.math.Coordinate} a The coordinate.
|
||||
* @return {!goog.math.Vec2} A new vector object.
|
||||
*/
|
||||
goog.math.Vec2.fromCoordinate = function(a) {
|
||||
return new goog.math.Vec2(a.x, a.y);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!goog.math.Vec2} A new vector with the same coordinates as this one.
|
||||
* @override
|
||||
*/
|
||||
goog.math.Vec2.prototype.clone = function() {
|
||||
return new goog.math.Vec2(this.x, this.y);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the magnitude of the vector measured from the origin.
|
||||
* @return {number} The length of the vector.
|
||||
*/
|
||||
goog.math.Vec2.prototype.magnitude = function() {
|
||||
return Math.sqrt(this.x * this.x + this.y * this.y);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the squared magnitude of the vector measured from the origin.
|
||||
* NOTE(brenneman): Leaving out the square root is not a significant
|
||||
* optimization in JavaScript.
|
||||
* @return {number} The length of the vector, squared.
|
||||
*/
|
||||
goog.math.Vec2.prototype.squaredMagnitude = function() {
|
||||
return this.x * this.x + this.y * this.y;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @return {!goog.math.Vec2} This coordinate after scaling.
|
||||
* @override
|
||||
*/
|
||||
goog.math.Vec2.prototype.scale =
|
||||
/** @type {function(number, number=):!goog.math.Vec2} */
|
||||
(goog.math.Coordinate.prototype.scale);
|
||||
|
||||
|
||||
/**
|
||||
* Reverses the sign of the vector. Equivalent to scaling the vector by -1.
|
||||
* @return {!goog.math.Vec2} The inverted vector.
|
||||
*/
|
||||
goog.math.Vec2.prototype.invert = function() {
|
||||
this.x = -this.x;
|
||||
this.y = -this.y;
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Normalizes the current vector to have a magnitude of 1.
|
||||
* @return {!goog.math.Vec2} The normalized vector.
|
||||
*/
|
||||
goog.math.Vec2.prototype.normalize = function() {
|
||||
return this.scale(1 / this.magnitude());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds another vector to this vector in-place.
|
||||
* @param {!goog.math.Coordinate} b The vector to add.
|
||||
* @return {!goog.math.Vec2} This vector with {@code b} added.
|
||||
*/
|
||||
goog.math.Vec2.prototype.add = function(b) {
|
||||
this.x += b.x;
|
||||
this.y += b.y;
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Subtracts another vector from this vector in-place.
|
||||
* @param {!goog.math.Coordinate} b The vector to subtract.
|
||||
* @return {!goog.math.Vec2} This vector with {@code b} subtracted.
|
||||
*/
|
||||
goog.math.Vec2.prototype.subtract = function(b) {
|
||||
this.x -= b.x;
|
||||
this.y -= b.y;
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Rotates this vector in-place by a given angle, specified in radians.
|
||||
* @param {number} angle The angle, in radians.
|
||||
* @return {!goog.math.Vec2} This vector rotated {@code angle} radians.
|
||||
*/
|
||||
goog.math.Vec2.prototype.rotate = function(angle) {
|
||||
var cos = Math.cos(angle);
|
||||
var sin = Math.sin(angle);
|
||||
var newX = this.x * cos - this.y * sin;
|
||||
var newY = this.y * cos + this.x * sin;
|
||||
this.x = newX;
|
||||
this.y = newY;
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Rotates a vector by a given angle, specified in radians, relative to a given
|
||||
* axis rotation point. The returned vector is a newly created instance - no
|
||||
* in-place changes are done.
|
||||
* @param {!goog.math.Vec2} v A vector.
|
||||
* @param {!goog.math.Vec2} axisPoint The rotation axis point.
|
||||
* @param {number} angle The angle, in radians.
|
||||
* @return {!goog.math.Vec2} The rotated vector in a newly created instance.
|
||||
*/
|
||||
goog.math.Vec2.rotateAroundPoint = function(v, axisPoint, angle) {
|
||||
var res = v.clone();
|
||||
return res.subtract(axisPoint).rotate(angle).add(axisPoint);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Compares this vector with another for equality.
|
||||
* @param {!goog.math.Vec2} b The other vector.
|
||||
* @return {boolean} Whether this vector has the same x and y as the given
|
||||
* vector.
|
||||
*/
|
||||
goog.math.Vec2.prototype.equals = function(b) {
|
||||
return this == b || !!b && this.x == b.x && this.y == b.y;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the distance between two vectors.
|
||||
* @param {!goog.math.Coordinate} a The first vector.
|
||||
* @param {!goog.math.Coordinate} b The second vector.
|
||||
* @return {number} The distance.
|
||||
*/
|
||||
goog.math.Vec2.distance = goog.math.Coordinate.distance;
|
||||
|
||||
|
||||
/**
|
||||
* Returns the squared distance between two vectors.
|
||||
* @param {!goog.math.Coordinate} a The first vector.
|
||||
* @param {!goog.math.Coordinate} b The second vector.
|
||||
* @return {number} The squared distance.
|
||||
*/
|
||||
goog.math.Vec2.squaredDistance = goog.math.Coordinate.squaredDistance;
|
||||
|
||||
|
||||
/**
|
||||
* Compares vectors for equality.
|
||||
* @param {!goog.math.Coordinate} a The first vector.
|
||||
* @param {!goog.math.Coordinate} b The second vector.
|
||||
* @return {boolean} Whether the vectors have the same x and y coordinates.
|
||||
*/
|
||||
goog.math.Vec2.equals = goog.math.Coordinate.equals;
|
||||
|
||||
|
||||
/**
|
||||
* Returns the sum of two vectors as a new Vec2.
|
||||
* @param {!goog.math.Coordinate} a The first vector.
|
||||
* @param {!goog.math.Coordinate} b The second vector.
|
||||
* @return {!goog.math.Vec2} The sum vector.
|
||||
*/
|
||||
goog.math.Vec2.sum = function(a, b) {
|
||||
return new goog.math.Vec2(a.x + b.x, a.y + b.y);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the difference between two vectors as a new Vec2.
|
||||
* @param {!goog.math.Coordinate} a The first vector.
|
||||
* @param {!goog.math.Coordinate} b The second vector.
|
||||
* @return {!goog.math.Vec2} The difference vector.
|
||||
*/
|
||||
goog.math.Vec2.difference = function(a, b) {
|
||||
return new goog.math.Vec2(a.x - b.x, a.y - b.y);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the dot-product of two vectors.
|
||||
* @param {!goog.math.Coordinate} a The first vector.
|
||||
* @param {!goog.math.Coordinate} b The second vector.
|
||||
* @return {number} The dot-product of the two vectors.
|
||||
*/
|
||||
goog.math.Vec2.dot = function(a, b) {
|
||||
return a.x * b.x + a.y * b.y;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a new Vec2 that is the linear interpolant between vectors a and b at
|
||||
* scale-value x.
|
||||
* @param {!goog.math.Coordinate} a Vector a.
|
||||
* @param {!goog.math.Coordinate} b Vector b.
|
||||
* @param {number} x The proportion between a and b.
|
||||
* @return {!goog.math.Vec2} The interpolated vector.
|
||||
*/
|
||||
goog.math.Vec2.lerp = function(a, b, x) {
|
||||
return new goog.math.Vec2(goog.math.lerp(a.x, b.x, x),
|
||||
goog.math.lerp(a.y, b.y, x));
|
||||
};
|
||||
308
nicer-api-docs/closure-library/closure/goog/math/vec3.js
Normal file
308
nicer-api-docs/closure-library/closure/goog/math/vec3.js
Normal file
@@ -0,0 +1,308 @@
|
||||
// Copyright 2008 The Closure Library Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/**
|
||||
* @fileoverview Defines a 3-element vector class that can be used for
|
||||
* coordinate math, useful for animation systems and point manipulation.
|
||||
*
|
||||
* Based heavily on code originally by:
|
||||
*/
|
||||
|
||||
|
||||
goog.provide('goog.math.Vec3');
|
||||
|
||||
goog.require('goog.math');
|
||||
goog.require('goog.math.Coordinate3');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Class for a three-dimensional vector object and assorted functions useful for
|
||||
* manipulation.
|
||||
*
|
||||
* Inherits from goog.math.Coordinate3 so that a Vec3 may be passed in to any
|
||||
* function that requires a Coordinate.
|
||||
*
|
||||
* @param {number} x The x value for the vector.
|
||||
* @param {number} y The y value for the vector.
|
||||
* @param {number} z The z value for the vector.
|
||||
* @constructor
|
||||
* @extends {goog.math.Coordinate3}
|
||||
*/
|
||||
goog.math.Vec3 = function(x, y, z) {
|
||||
/**
|
||||
* X-value
|
||||
* @type {number}
|
||||
*/
|
||||
this.x = x;
|
||||
|
||||
/**
|
||||
* Y-value
|
||||
* @type {number}
|
||||
*/
|
||||
this.y = y;
|
||||
|
||||
/**
|
||||
* Z-value
|
||||
* @type {number}
|
||||
*/
|
||||
this.z = z;
|
||||
};
|
||||
goog.inherits(goog.math.Vec3, goog.math.Coordinate3);
|
||||
|
||||
|
||||
/**
|
||||
* Generates a random unit vector.
|
||||
*
|
||||
* http://mathworld.wolfram.com/SpherePointPicking.html
|
||||
* Using (6), (7), and (8) to generate coordinates.
|
||||
* @return {!goog.math.Vec3} A random unit-length vector.
|
||||
*/
|
||||
goog.math.Vec3.randomUnit = function() {
|
||||
var theta = Math.random() * Math.PI * 2;
|
||||
var phi = Math.random() * Math.PI * 2;
|
||||
|
||||
var z = Math.cos(phi);
|
||||
var x = Math.sqrt(1 - z * z) * Math.cos(theta);
|
||||
var y = Math.sqrt(1 - z * z) * Math.sin(theta);
|
||||
|
||||
return new goog.math.Vec3(x, y, z);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Generates a random vector inside the unit sphere.
|
||||
*
|
||||
* @return {!goog.math.Vec3} A random vector.
|
||||
*/
|
||||
goog.math.Vec3.random = function() {
|
||||
return goog.math.Vec3.randomUnit().scale(Math.random());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a new Vec3 object from a given coordinate.
|
||||
*
|
||||
* @param {goog.math.Coordinate3} a The coordinate.
|
||||
* @return {!goog.math.Vec3} A new vector object.
|
||||
*/
|
||||
goog.math.Vec3.fromCoordinate3 = function(a) {
|
||||
return new goog.math.Vec3(a.x, a.y, a.z);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new copy of this Vec3.
|
||||
*
|
||||
* @return {!goog.math.Vec3} A new vector with the same coordinates as this one.
|
||||
* @override
|
||||
*/
|
||||
goog.math.Vec3.prototype.clone = function() {
|
||||
return new goog.math.Vec3(this.x, this.y, this.z);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the magnitude of the vector measured from the origin.
|
||||
*
|
||||
* @return {number} The length of the vector.
|
||||
*/
|
||||
goog.math.Vec3.prototype.magnitude = function() {
|
||||
return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the squared magnitude of the vector measured from the origin.
|
||||
* NOTE(brenneman): Leaving out the square root is not a significant
|
||||
* optimization in JavaScript.
|
||||
*
|
||||
* @return {number} The length of the vector, squared.
|
||||
*/
|
||||
goog.math.Vec3.prototype.squaredMagnitude = function() {
|
||||
return this.x * this.x + this.y * this.y + this.z * this.z;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Scales the current vector by a constant.
|
||||
*
|
||||
* @param {number} s The scale factor.
|
||||
* @return {!goog.math.Vec3} This vector, scaled.
|
||||
*/
|
||||
goog.math.Vec3.prototype.scale = function(s) {
|
||||
this.x *= s;
|
||||
this.y *= s;
|
||||
this.z *= s;
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Reverses the sign of the vector. Equivalent to scaling the vector by -1.
|
||||
*
|
||||
* @return {!goog.math.Vec3} This vector, inverted.
|
||||
*/
|
||||
goog.math.Vec3.prototype.invert = function() {
|
||||
this.x = -this.x;
|
||||
this.y = -this.y;
|
||||
this.z = -this.z;
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Normalizes the current vector to have a magnitude of 1.
|
||||
*
|
||||
* @return {!goog.math.Vec3} This vector, normalized.
|
||||
*/
|
||||
goog.math.Vec3.prototype.normalize = function() {
|
||||
return this.scale(1 / this.magnitude());
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Adds another vector to this vector in-place.
|
||||
*
|
||||
* @param {goog.math.Vec3} b The vector to add.
|
||||
* @return {!goog.math.Vec3} This vector with {@code b} added.
|
||||
*/
|
||||
goog.math.Vec3.prototype.add = function(b) {
|
||||
this.x += b.x;
|
||||
this.y += b.y;
|
||||
this.z += b.z;
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Subtracts another vector from this vector in-place.
|
||||
*
|
||||
* @param {goog.math.Vec3} b The vector to subtract.
|
||||
* @return {!goog.math.Vec3} This vector with {@code b} subtracted.
|
||||
*/
|
||||
goog.math.Vec3.prototype.subtract = function(b) {
|
||||
this.x -= b.x;
|
||||
this.y -= b.y;
|
||||
this.z -= b.z;
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Compares this vector with another for equality.
|
||||
*
|
||||
* @param {goog.math.Vec3} b The other vector.
|
||||
* @return {boolean} True if this vector's x, y and z equal the given vector's
|
||||
* x, y, and z, respectively.
|
||||
*/
|
||||
goog.math.Vec3.prototype.equals = function(b) {
|
||||
return this == b || !!b && this.x == b.x && this.y == b.y && this.z == b.z;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the distance between two vectors.
|
||||
*
|
||||
* @param {goog.math.Vec3} a The first vector.
|
||||
* @param {goog.math.Vec3} b The second vector.
|
||||
* @return {number} The distance.
|
||||
*/
|
||||
goog.math.Vec3.distance = goog.math.Coordinate3.distance;
|
||||
|
||||
|
||||
/**
|
||||
* Returns the squared distance between two vectors.
|
||||
*
|
||||
* @param {goog.math.Vec3} a The first vector.
|
||||
* @param {goog.math.Vec3} b The second vector.
|
||||
* @return {number} The squared distance.
|
||||
*/
|
||||
goog.math.Vec3.squaredDistance = goog.math.Coordinate3.squaredDistance;
|
||||
|
||||
|
||||
/**
|
||||
* Compares vectors for equality.
|
||||
*
|
||||
* @param {goog.math.Vec3} a The first vector.
|
||||
* @param {goog.math.Vec3} b The second vector.
|
||||
* @return {boolean} True if the vectors have equal x, y, and z coordinates.
|
||||
*/
|
||||
goog.math.Vec3.equals = goog.math.Coordinate3.equals;
|
||||
|
||||
|
||||
/**
|
||||
* Returns the sum of two vectors as a new Vec3.
|
||||
*
|
||||
* @param {goog.math.Vec3} a The first vector.
|
||||
* @param {goog.math.Vec3} b The second vector.
|
||||
* @return {!goog.math.Vec3} The sum vector.
|
||||
*/
|
||||
goog.math.Vec3.sum = function(a, b) {
|
||||
return new goog.math.Vec3(a.x + b.x, a.y + b.y, a.z + b.z);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the difference of two vectors as a new Vec3.
|
||||
*
|
||||
* @param {goog.math.Vec3} a The first vector.
|
||||
* @param {goog.math.Vec3} b The second vector.
|
||||
* @return {!goog.math.Vec3} The difference vector.
|
||||
*/
|
||||
goog.math.Vec3.difference = function(a, b) {
|
||||
return new goog.math.Vec3(a.x - b.x, a.y - b.y, a.z - b.z);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the dot-product of two vectors.
|
||||
*
|
||||
* @param {goog.math.Vec3} a The first vector.
|
||||
* @param {goog.math.Vec3} b The second vector.
|
||||
* @return {number} The dot-product of the two vectors.
|
||||
*/
|
||||
goog.math.Vec3.dot = function(a, b) {
|
||||
return a.x * b.x + a.y * b.y + a.z * b.z;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the cross-product of two vectors.
|
||||
*
|
||||
* @param {goog.math.Vec3} a The first vector.
|
||||
* @param {goog.math.Vec3} b The second vector.
|
||||
* @return {!goog.math.Vec3} The cross-product of the two vectors.
|
||||
*/
|
||||
goog.math.Vec3.cross = function(a, b) {
|
||||
return new goog.math.Vec3(a.y * b.z - a.z * b.y,
|
||||
a.z * b.x - a.x * b.z,
|
||||
a.x * b.y - a.y * b.x);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a new Vec3 that is the linear interpolant between vectors a and b at
|
||||
* scale-value x.
|
||||
*
|
||||
* @param {goog.math.Vec3} a Vector a.
|
||||
* @param {goog.math.Vec3} b Vector b.
|
||||
* @param {number} x The proportion between a and b.
|
||||
* @return {!goog.math.Vec3} The interpolated vector.
|
||||
*/
|
||||
goog.math.Vec3.lerp = function(a, b, x) {
|
||||
return new goog.math.Vec3(goog.math.lerp(a.x, b.x, x),
|
||||
goog.math.lerp(a.y, b.y, x),
|
||||
goog.math.lerp(a.z, b.z, x));
|
||||
};
|
||||
Reference in New Issue
Block a user