in asdoc/library/closure/goog/math/long.js [749:825]
goog.math.Long.prototype.div = function(other) {
if (other.isZero()) {
throw new Error('division by zero');
}
if (this.isNegative()) {
if (this.equals(goog.math.Long.getMinValue())) {
if (other.equals(goog.math.Long.getOne()) ||
other.equals(goog.math.Long.getNegOne())) {
return goog.math.Long.getMinValue(); // recall -MIN_VALUE == MIN_VALUE
}
if (other.equals(goog.math.Long.getMinValue())) {
return goog.math.Long.getOne();
}
// 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.getZero())) {
return other.isNegative() ? goog.math.Long.getOne() :
goog.math.Long.getNegOne();
}
var rem = this.subtract(other.multiply(approx));
var result = approx.add(rem.div(other));
return result;
}
if (other.isNegative()) {
return this.negate().div(other.negate());
}
return this.negate().div(other).negate();
}
if (this.isZero()) {
return goog.math.Long.getZero();
}
if (other.isNegative()) {
if (other.equals(goog.math.Long.getMinValue())) {
return goog.math.Long.getZero();
}
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.getZero();
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.getOne();
}
res = res.add(approxRes);
rem = rem.subtract(approxRem);
}
return res;
};