div method

Big div(
  1. dynamic y
)

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;
}