divide method

UcumDecimal divide(
  1. UcumDecimal other
)

Implementation

UcumDecimal divide(UcumDecimal other) {
  if (isZero()) {
    return zero();
  } else if (other.isZero()) {
    throw UcumException('Attempt to divide $toString() by zero');
  } else {
    final String s = '0${other.digits}';
    final int m = math.max(digits.length, other.digits.length) +
        40; // max loops we'll do
    final List<String> tens = List<String>.filled(10, '');
    tens[0] = stringAddition(stringMultiply('0', s.length), s);
    for (int i = 1; i < 10; i++) {
      tens[i] = stringAddition(tens[i - 1], s);
    }
    String v = digits;
    String r = '';
    int l = 0;
    int d = (digits.length - decimal + 1) -
        (other.digits.length - other.decimal + 1);

    while (v.length < tens[0].length) {
      v = '${v}0';
      d++;
    }

    String w;
    int vi;
    if (v.substring(0, other.digits.length).compareTo(other.digits) < 0) {
      if (v.length == tens[0].length) {
        v = '${v}0';
        d++;
      }
      w = v.substring(0, other.digits.length + 1);
      vi = w.length;
    } else {
      w = '0${v.substring(0, other.digits.length)}';
      vi = w.length - 1;
    }

    bool handled = false;
    bool proc;

    while (!(handled &&
        ((l > m) ||
            ((vi >= v.length) && (Utilities.noString(w) || allZeros(w)))))) {
      l++;
      handled = true;
      proc = false;
      for (int i = 8; i >= 0; i--) {
        if (tens[i].compareTo(w) <= 0) {
          proc = true;
          r = r + cdig(i + 1);
          w = trimLeadingZeros(stringSubtraction(w, tens[i]));
          if (!(handled &&
              ((l > m) ||
                  ((vi >= v.length) &&
                      (Utilities.noString(w) || allZeros(w)))))) {
            if (vi < v.length) {
              w = w + v[vi];
              vi++;
              handled = false;
            } else {
              w = '${w}0';
              d++;
            }
            while (w.length < tens[0].length) {
              w = '0$w';
            }
          }
          break;
        }
      }
      if (!proc) {
        assert(w[0] == '0');
        w = delete(w, 0, 1);
        r = '${r}0';
        if (!(handled &&
            ((l > m) ||
                ((vi >= v.length) &&
                    (Utilities.noString(w) || allZeros(w)))))) {
          if (vi < v.length) {
            w = w + v[vi];
            vi++;
            handled = false;
          } else {
            w = '${w}0';
            d++;
          }
          while (w.length < tens[0].length) {
            w = '0$w';
          }
        }
      }
    }
    int prec;

    if (isWholeNumber() && other.isWholeNumber() && (l < m)) {
      for (int i = 0; i < d; i++) {
        if (r[r.length - 1] == '0') {
          r = delete(r, r.length - 1, 1);
          d--;
        }
      }
      prec = 100;
    } else {
      if (isWholeNumber() && other.isWholeNumber()) {
        prec = math.max(digits.length, other.digits.length);
      } else if (isWholeNumber()) {
        prec = math.max(other.precision, r.length - d);
      } else if (other.isWholeNumber()) {
        prec = math.max(precision, r.length - d);
      } else {
        prec = math.max(math.min(precision, other.precision), r.length - d);
      }

      if (r.length > prec) {
        d = d - (r.length - prec);
        final int digit = r[prec].codeUnitAt(0);
        final bool up = digit >= '5'.codeUnitAt(0);
        if (up) {
          final List<int> rs = r.substring(0, prec).codeUnits.toList();
          int i = rs.length - 1;
          bool carry = true;
          while (carry && i >= 0) {
            int ls = rs[i];
            if (ls == '9'.codeUnitAt(0)) {
              rs[i] = '0'.codeUnitAt(0);
            } else {
              ls = ls + 1;
              rs[i] = ls;
              carry = false;
            }
            i--;
          }
          if (carry) {
            r = '1${String.fromCharCodes(rs)}';
            d++; // because we added one at the start
          } else {
            r = String.fromCharCodes(rs);
          }
        } else {
          r = r.substring(0, prec);
        }
      }
    }

    final UcumDecimal result = UcumDecimal();
    result.setValueUcumDecimal(r);
    result.decimal = r.length - d;
    result.negative = negative != other.negative;
    result.precision = prec;
    result.scientific = scientific || other.scientific;
    return result;
  }
}