multiply method

UcumDecimal multiply(
  1. UcumDecimal other
)

Implementation

UcumDecimal multiply(UcumDecimal other) {
  if (isZero() || other.isZero()) {
    return zero();
  }

  final int max = math.max(decimal, other.decimal);
  String s1 = stringMultiply('0', max - decimal + 1) + digits;
  String s2 = stringMultiply('0', max - other.decimal + 1) + other.digits;

  if (s1.length < s2.length) {
    s1 = s1 + stringMultiply('0', s2.length - s1.length);
  } else if (s2.length < s1.length) {
    s2 = s2 + stringMultiply('0', s1.length - s2.length);
  }

  if (s2.compareTo(s1) > 0) {
    final String temp = s1;
    s1 = s2;
    s2 = temp;
  }

  List<String> s = List<String>.generate(s2.length, (_) => '');

  int carry;
  for (int i = s2.length - 1; i >= 0; i--) {
    s[i] = stringMultiply('0', s2.length - (i + 1));
    carry = 0;
    for (int j = s1.length - 1; j >= 0; j--) {
      final int t = carry + (dig(s1[j]) * dig(s2[i]));
      s[i] = '${cdig(t % 10)}${s[i]}';
      carry = t ~/ 10;
    }
    while (carry > 0) {
      s[i] = '${cdig(carry % 10)}${s[i]}';
      carry ~/= 10;
    }
  }

  final int maxLength = s.map((String str) => str.length).reduce(math.max);
  s = s
      .map((String str) => stringMultiply('0', maxLength - str.length) + str)
      .toList();

  String result = '';
  carry = 0;
  for (int i = maxLength - 1; i >= 0; i--) {
    for (final String str in s) {
      carry += dig(str[i]);
    }
    result = '${cdig(carry % 10)}$result';
    carry ~/= 10;
  }

  if (carry > 0) {
    throw Exception('Internal logic error');
  }

  int decimalPos = result.length - ((s1.length - (max + 1)) * 2);
  while (result.isNotEmpty && result != '0' && result.startsWith('0')) {
    result = result.substring(1);
    decimalPos--;
  }

  int precisionResult;
  if (isWholeNumber() && other.isWholeNumber()) {
    precisionResult = math.max(math.max(digits.length, other.digits.length),
        math.min(precision, other.precision));
  } else if (isWholeNumber()) {
    precisionResult = other.precision;
  } else if (other.isWholeNumber()) {
    precisionResult = precision;
  } else {
    precisionResult = math.min(precision, other.precision);
  }

  while (result.length > precisionResult && result.endsWith('0')) {
    result = result.substring(0, result.length - 1);
  }

  final UcumDecimal newUcumDecimal = UcumDecimal();
  newUcumDecimal.setValueUcumDecimal(result);
  newUcumDecimal.precision = precisionResult;
  newUcumDecimal.decimal = decimalPos;
  newUcumDecimal.negative = negative != other.negative;
  newUcumDecimal.scientific = scientific || other.scientific;
  return newUcumDecimal;
}