div method
Return a new Big whose value is the value of this Big divided by the value of Big y, rounded, if necessary, to a maximum of Big.dp decimal places using rounding mode Big.rm.
Implementation
Big div(dynamic y) {
var yBig = Big(y);
var x = this,
a = x.c, // dividend
b = yBig.c, // divisor
k = x.s == yBig.s ? 1 : -1,
dp = Big.dp;
// Divisor is zero?
if (!b.isElementIsValid(0)) {
throw BigError(
code: BigErrorCode.divByZero,
);
}
// Dividend is 0? Return +-0.
if (!a.isElementIsValid(0)) {
yBig.s = k;
yBig.c = [yBig.e = 0];
return yBig;
}
int? cmp;
int n, ri, bl;
List<int> bt;
var bz = [...b],
ai = bl = b.length,
al = a.length,
q = yBig, // quotient
qc = q.c = [],
qi = 0;
q.e = x.e - yBig.e;
var p = dp + q.e + 1; // precision of the result
var r = a.slice(0, bl); // remainder
var rl = r.length;
q.s = k;
k = p < 0 ? 0 : p;
// Create version of divisor with leading zero.
unShift(bz, 0);
// Add zeros to make remainder as long as divisor.
for (; rl++ < bl;) {
r.add(0);
}
do {
// n is how many times the divisor goes into current remainder.
for (n = 0; n < 10; n++) {
// Compare divisor and remainder.
if (bl != (rl = r.length)) {
cmp = bl > rl ? 1 : -1;
} else {
cmp = 0;
for (ri = -1; ++ri < bl;) {
if (b[ri] != r[ri]) {
cmp = b[ri] > r[ri] ? 1 : -1;
break;
}
}
}
// If divisor < remainder, subtract divisor from remainder.
if (cmp != null && cmp < 0) {
// Remainder can't be more than 1 digit longer than divisor.
// Equalise lengths using divisor with extra leading zero?
for (bt = rl == bl ? b : bz; rl != 0;) {
if (r[--rl] < (bt.elementAtOrNull(rl) ?? 0)) {
ri = rl;
for (; ri != 0 && !r.isElementIsValid(--ri);) {
r[ri] = 9;
}
--r[ri];
r[rl] += 10;
}
r[rl] -= bt.elementAtOrNull(rl) ?? 0;
}
for (; !r.isElementIsValid(0);) {
r.removeAt(0);
}
} else {
break;
}
}
// Add the digit n to the result array.
if (cmp != null && cmp != 0) {
qi++;
qc.add(n);
} else {
qi++;
qc.add(++n);
}
// Update the remainder.
if (r.isElementIsValid(0) && cmp != null && cmp != 0) {
r.add(a.elementAtOrNull(ai) ?? 0);
} else {
r = a.elementAtOrNull(ai) != null ? [a.elementAt(ai)] : [];
}
} while ((ai++ < al || r.firstOrNull != null) && (k--).intToBool);
// Leading zero? Do not remove if result is simply zero (qi == 1).
if (!qc.isElementIsValid(0) && qi != 1) {
// There can't be more than one zero.
qc.removeAt(0);
q.e--;
p--;
}
// Round?
if (qi > p) {
_round(q, p, rm, more: r.firstOrNull != null);
}
return q;
}