Task: Polynomial long division



C#: using System;

namespace PolynomialLongDivision {
    class Solution {
        public Solution(double[] q, double[] r) {
            Quotient = q;
            Remainder = r;
        }

        public double[] Quotient { get; }
        public double[] Remainder { get; }
    }

    class Program {
        static int PolyDegree(double[] p) {
            for (int i = p.Length - 1; i >= 0; --i) {
                if (p[i] != 0.0) return i;
            }
            return int.MinValue;
        }

        static double[] PolyShiftRight(double[] p, int places) {
            if (places <= 0) return p;
            int pd = PolyDegree(p);
            if (pd + places >= p.Length) {
                throw new ArgumentOutOfRangeException("The number of places to be shifted is too large");
            }
            double[] d = new double[p.Length];
            p.CopyTo(d, 0);
            for (int i = pd; i >= 0; --i) {
                d[i + places] = d[i];
                d[i] = 0.0;
            }
            return d;
        }

        static void PolyMultiply(double[] p, double m) {
            for (int i = 0; i < p.Length; ++i) {
                p[i] *= m;
            }
        }

        static void PolySubtract(double[] p, double[] s) {
            for (int i = 0; i < p.Length; ++i) {
                p[i] -= s[i];
            }
        }

        static Solution PolyLongDiv(double[] n, double[] d) {
            if (n.Length != d.Length) {
                throw new ArgumentException("Numerator and denominator vectors must have the same size");
            }
            int nd = PolyDegree(n);
            int dd = PolyDegree(d);
            if (dd < 0) {
                throw new ArgumentException("Divisor must have at least one one-zero coefficient");
            }
            if (nd < dd) {
                throw new ArgumentException("The degree of the divisor cannot exceed that of the numerator");
            }
            double[] n2 = new double[n.Length];
            n.CopyTo(n2, 0);
            double[] q = new double[n.Length];
            while (nd >= dd) {
                double[] d2 = PolyShiftRight(d, nd - dd);
                q[nd - dd] = n2[nd] / d2[nd];
                PolyMultiply(d2, q[nd - dd]);
                PolySubtract(n2, d2);
                nd = PolyDegree(n2);
            }
            return new Solution(q, n2);
        }

        static void PolyShow(double[] p) {
            int pd = PolyDegree(p);
            for (int i = pd; i >= 0; --i) {
                double coeff = p[i];
                if (coeff == 0.0) continue;
                if (coeff == 1.0) {
                    if (i < pd) {
                        Console.Write(" + ");
                    }
                } else if (coeff == -1.0) {
                    if (i < pd) {
                        Console.Write(" - ");
                    } else {
                        Console.Write("-");
                    }
                } else if (coeff < 0.0) {
                    if (i < pd) {
                        Console.Write(" - {0:F1}", -coeff);
                    } else {
                        Console.Write("{0:F1}", coeff);
                    }
                } else {
                    if (i < pd) {
                        Console.Write(" + {0:F1}", coeff);
                    } else {
                        Console.Write("{0:F1}", coeff);
                    }
                }
                if (i > 1) Console.Write("x^{0}", i);
                else if (i == 1) Console.Write("x");
            }
            Console.WriteLine();
        }

        static void Main(string[] args) {
            double[] n = { -42.0, 0.0, -12.0, 1.0 };
            double[] d = { -3.0, 1.0, 0.0, 0.0 };
            Console.Write("Numerator   : ");
            PolyShow(n);
            Console.Write("Denominator : ");
            PolyShow(d);
            Console.WriteLine("-------------------------------------");
            Solution sol = PolyLongDiv(n, d);
            Console.Write("Quotient    : ");
            PolyShow(sol.Quotient);
            Console.Write("Remainder   : ");
            PolyShow(sol.Remainder);
        }
    }
}









Ada: with Ada.Text_IO; use Ada.Text_IO;

procedure Long_Division is
   package Int_IO is new Ada.Text_IO.Integer_IO (Integer);
   use Int_IO;

   type Degrees is range -1 .. Integer'Last;
   subtype Valid_Degrees is Degrees range 0 .. Degrees'Last;
   type Polynom is array (Valid_Degrees range <>) of Integer;

   function Degree (P : Polynom) return Degrees is
   begin
      for I in reverse P'Range loop
         if P (I) /= 0 then
            return I;
         end if;
      end loop;
      return -1;
   end Degree;

   function Shift_Right (P : Polynom; D : Valid_Degrees) return Polynom is
      Result : Polynom (0 .. P'Last + D) := (others => 0);
   begin
      Result (Result'Last - P'Length + 1 .. Result'Last) := P;
      return Result;
   end Shift_Right;

   function "*" (Left : Polynom; Right : Integer) return Polynom is
      Result : Polynom (Left'Range);
   begin
      for I in Result'Range loop
         Result (I) := Left (I) * Right;
      end loop;
      return Result;
   end "*";

   function "-" (Left, Right : Polynom) return Polynom is
      Result : Polynom (Left'Range);
   begin
      for I in Result'Range loop
         if I in Right'Range then
            Result (I) := Left (I) - Right (I);
         else
            Result (I) := Left (I);
         end if;
      end loop;
      return Result;
   end "-";

   procedure Poly_Long_Division (Num, Denom : Polynom; Q, R : out Polynom) is
      N : Polynom := Num;
      D : Polynom := Denom;
   begin
      if Degree (D) < 0 then
         raise Constraint_Error;
      end if;
      Q := (others => 0);
      while Degree (N) >= Degree (D) loop
         declare
            T : Polynom := Shift_Right (D, Degree (N) - Degree (D));
         begin
            Q (Degree (N) - Degree (D)) := N (Degree (N)) / T (Degree (T));
            T := T * Q (Degree (N) - Degree (D));
            N := N - T;
         end;
      end loop;
      R := N;
   end Poly_Long_Division;

   procedure Output (P : Polynom) is
      First : Boolean := True;
   begin
      for I in reverse P'Range loop
         if P (I) /= 0 then
            if First then
               First := False;
            else
               Put (" + ");
            end if;
            if I > 0 then
               if P (I) /= 1 then
                  Put (P (I), 0);
                  Put ("*");
               end if;
               Put ("x");
               if I > 1 then
                  Put ("^");
                  Put (Integer (I), 0);
               end if;
            elsif P (I) /= 0 then
               Put (P (I), 0);
            end if;
         end if;
      end loop;
      New_Line;
   end Output;

   Test_N : constant Polynom := (0 => -42, 1 => 0, 2 => -12, 3 => 1);
   Test_D : constant Polynom := (0 => -3, 1 => 1);
   Test_Q : Polynom (Test_N'Range);
   Test_R : Polynom (Test_N'Range);
begin
   Poly_Long_Division (Test_N, Test_D, Test_Q, Test_R);
   Put_Line ("Dividing Polynoms:");
   Put ("N: "); Output (Test_N);
   Put ("D: "); Output (Test_D);
   Put_Line ("
   Put ("Q: "); Output (Test_Q);
   Put ("R: "); Output (Test_R);
end Long_Division;