예제 #1
0
        public static RadicalSum Add(RadicalSum left, RadicalSum right)
        {
            var z = new Radical[left.Radicals.Length + right.Radicals.Length];

            left.Radicals.CopyTo(z, 0);
            right.Radicals.CopyTo(z, left.Radicals.Length);
            return(new RadicalSum(z));
        }
예제 #2
0
        public static RadicalSum Negate(RadicalSum value)
        {
            Radical[] radicals = new Radical[value.Radicals.Length];
            for (int i = 0; i < value.Radicals.Length; i++)
            {
                radicals[i] = -value.Radicals[i];
            }
            var result = new RadicalSum(radicals);

            return(result);
        }
예제 #3
0
        public static RadicalSum Multiply(RadicalSum left, RadicalSum right)
        {
            var z = new Radical[left.Radicals.Length * right.Radicals.Length];

            for (int i = 0; i < left.Radicals.Length; i++)
            {
                for (int j = 0; j < right.Radicals.Length; j++)
                {
                    z[(i * right.Radicals.Length) + j] = left.Radicals[i] * right.Radicals[j];
                }
            }
            return(new RadicalSum(z));
        }
예제 #4
0
        public static RadicalSum Divide(RadicalSum left, Radical right)
        {
            if (right == 0)
            {
                throw new DivideByZeroException("Cannot divide by zero");
            }
            var z = new Radical[left.Radicals.Length];

            for (int i = 0; i < left.Radicals.Length; i++)
            {
                z[i] = left.Radicals[i] / right;
            }
            return(new RadicalSum(z));
        }
예제 #5
0
        public static Radical[] SimplifyRadicals(Radical[] radicals)
        {
            if (radicals == null)
            {
                return(null);
            }
            if (radicals.Length == 0)
            {
                return(new Radical[0]);
            }
            if (radicals.Length == 1)
            {
                return(radicals);
            }

            var uniqueRadicals = new Dictionary <Tuple <BigInteger, int>, Radical>();

            for (int i = 0; i < radicals.Length; i++)
            {
                Radical b   = radicals[i];
                var     key = new Tuple <BigInteger, int>(b.Radicand, b.Index);
                if (uniqueRadicals.ContainsKey(key))
                {
                    uniqueRadicals[key] = Radical.AddCompatible(uniqueRadicals[key], b);
                }
                else if (!b.IsZero)
                {
                    uniqueRadicals[key] = b;
                }
            }

            Radical[] result =
                uniqueRadicals.Values
                .Where(f => !f.IsZero)
                .OrderBy(f => f.Index)
                .ThenBy(f => f.Radicand)
                .ToArray();
            if (result.Length == 0)
            {
                result = new Radical[1] {
                    Radical.Zero
                }
            }
            ;
            return(result);
        }
예제 #6
0
 public RadicalSumRatio(Radical radical)
     : this(new RadicalSum(radical), RadicalSum.One)
 {
 }
예제 #7
0
        /// <summary>
        /// Returns multiplicative inverse, i.e., B such that this * B = 1
        /// </summary>
        /// <returns></returns>
        public static RadicalSum GetRationalizer(RadicalSum value)
        {
            // Method derived from:
            // Rationalizing Denominators
            // Allan Berele and Stefan Catoiu
            // https://www.jstor.org/stable/10.4169/mathmaga.88.issue-2
            // See Example 9

            if (value == 0)
            {
                throw new Exception("Cannot get rationalization of zero");
            }

            // Solve for the largest field extensions in turn
            // S = r_1 + r_2 + ... + r_n
            // r_n = S - r_1 - r_2 - ... - r_(n-1)
            // r_n^2 = [S - r_1 - r_2 - ... - r_(n-1)]^2


            // Create polynomial in S
            // S - r_1 - r_2 - ... - r_n = 0
            var term1 = new Polynomials.PolynomialTerm(1, 1);
            var term0 = new Polynomials.PolynomialTerm(-value, 0);
            var p     = new Polynomials.Polynomial(new Polynomials.PolynomialTerm[2] {
                term0, term1
            });

            // Get the set of unique indexes and radicands for each index
            var uniquePrimeNthRoots = p.GetUniquePrimeNthRoots();

            // Main loop
            for (int i = uniquePrimeNthRoots.Length - 1; i >= 0; i--)
            {
                var currentPrimeNthRoot = uniquePrimeNthRoots[i];
                if (currentPrimeNthRoot.Item1 < 2) // Index
                {
                    continue;
                }
                if (currentPrimeNthRoot.Item2 < 2) // Radicand
                {
                    continue;
                }
                // Solve for largest radicand
                // p = p_reduced + p_extract = 0
                // p_extract = root[currentIndex](currentRadicand) * p' for some p'
                Polynomials.Polynomial p_reduced;
                Polynomials.Polynomial p_extract;
                p.ExtractTermsContainingNthRoot(
                    radicand: currentPrimeNthRoot.Item2,
                    index: currentPrimeNthRoot.Item1,
                    p_reduced: out p_reduced,
                    p_extract: out p_extract);

                // Remove root[currentIndex](currentRadicand) to keep p' === p_extract_coefficient
                var r = new Radical(1, currentPrimeNthRoot.Item2, currentPrimeNthRoot.Item1);
                var p_extract_coefficient = p_extract /= r;

                // p_reduced = -p_extract
                // p_reduced^currentIndex = (-p_extract)^currentIndex
                // p_reduced^currentIndex = (-p_extract_coefficient)^currentIndex * currentRadicand
                // p => p_reduced^currentIndex - currentRadicand * (-p_extract_coefficient)^currentIndex = 0
                var left  = Polynomials.Polynomial.Pow(p_reduced, currentPrimeNthRoot.Item1);
                var right = Polynomials.Polynomial.Pow(-p_extract, currentPrimeNthRoot.Item1) * currentPrimeNthRoot.Item2;
                p = left - right;
            }

            // We now have a polynomial in S with all radicals removed:
            // a_0 + a_1 * S + a_2 * S^2 + ... + a_n * S^n = 0
            // Radicalizer then becomes:
            // -a_0 / S = a_1 + a_2 * S + ... + a_n * S^(n-1)
            //
            // 1   a_1 + a_2 * S + ... + a_n * S^(n-1)
            // - = -----------------------------------
            // S                 -a_0
            var constantTerm = p.GetConstantTerm();
            var constantP    = new Polynomials.Polynomial(constantTerm);

            p -= constantP;
            if (!p.IsDivisibleByX)
            {
                throw new Exception("All terms should have at least degree 1");
            }
            if (!constantTerm.IsRational)
            {
                throw new Exception("No radicals should remain in any terms");
            }
            p  = Polynomials.Polynomial.DivideByX(p);
            p /= (Rational)(-constantTerm);

            var rationalizer = p.EvaluateAt(value);

            return(rationalizer);
        }
예제 #8
0
 public RadicalSum(Radical radical)
 {
     _radicals = new Radical[1] {
         radical
     };
 }