divide method

Divides polyNumerator by polyDenominator and wraps quotient and remainder in the AlgebraicDivision class.

An exception of type PolynomialLongDivisionException is thrown if the degree of the denominator cannot exceed the degree of the numerator.

Implementation

AlgebraicDivision divide() {
  if (polyNumerator.degree < polyDenominator.degree) {
    throw const PolynomialLongDivisionException(
        'The degree of the denominator cannot exceed the degree of the numerator.');
  }

  // If both are equals, just return 1 with a remainder of 0
  if (polyNumerator == polyDenominator) {
    return AlgebraicDivision(
      quotient: Constant(),
      remainder: Constant(
        a: const Complex.zero(),
      ),
    );
  }

  final numerator = List<Complex>.from(polyNumerator.coefficients.reversed);
  final denominator =
      List<Complex>.from(polyDenominator.coefficients.reversed);

  var numDegree = polyNumerator.degree as int;
  final denomDegree = polyDenominator.degree as int;

  // Support list.
  var tempDen = List<Complex>.generate(
    numDegree + 1,
    (_) => const Complex.zero(),
    growable: false,
  );

  // The results (quotient and remainder).
  final quotient = List<Complex>.generate(
    numDegree - denomDegree + 1,
    (_) => const Complex.zero(),
    growable: false,
  );

  // Polynomial long division algorithm that produces.
  if (numDegree >= denomDegree) {
    while (numDegree >= denomDegree) {
      tempDen = List<Complex>.generate(
        tempDen.length,
        (_) => const Complex.zero(),
        growable: false,
      );

      for (var i = 0; i <= denomDegree; i++) {
        tempDen[i + numDegree - denomDegree] = denominator[i];
      }

      quotient[numDegree - denomDegree] =
          numerator[numDegree] / tempDen[numDegree];

      for (var i = 0; i < numDegree - denomDegree + 1; i++) {
        tempDen[i] = tempDen[i] * quotient[numDegree - denomDegree];
      }

      for (var i = 0; i < numDegree + 1; i++) {
        numerator[i] = numerator[i] - tempDen[i];
      }

      numDegree--;
    }
  }

  // Creating the remainder array.
  final remainder = <Complex>[];

  // Skipping leading zeroes which will raise an exception when reversing the
  // contents of the list.
  for (var i = 0; i <= numDegree; i++) {
    if (numerator[i] == const Complex.zero()) {
      continue;
    }

    remainder.add(numerator[i]);
  }

  // Returning the results.
  return AlgebraicDivision(
    quotient: Algebraic.from(quotient.reversed.toList()),
    remainder: Algebraic.from(remainder.reversed.toList()),
  );
}