Skip to content

Commit

Permalink
Included bug fix from (non-generic) MultivariatePolynomial library.
Browse files Browse the repository at this point in the history
MultivariatePolynomial<T>.Factor now working.
Tests for  MultivariatePolynomial<T>.Factor.
MultivariatePolynomial<T>.GCD now working for the univariate case.
Tests for MultivariatePolynomial<T>.GCD univariate case.
  • Loading branch information
AdamWhiteHat committed Mar 5, 2023
1 parent 81e69dc commit 31035ce
Show file tree
Hide file tree
Showing 12 changed files with 901 additions and 65 deletions.
23 changes: 22 additions & 1 deletion GenericMultivariatePolynomial/ComplexHelperMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public static class ComplexHelperMethods
{
public static bool IsComplexValueType(Type type)
{
return type.Name.Contains("Complex");
return type.Name.Contains("Complex", StringComparison.OrdinalIgnoreCase);
}

public static int ComplexGetRealPartSign<T>(T value)
Expand Down Expand Up @@ -200,5 +200,26 @@ public static Complex Parse(string s)

return new Complex(real, imaginary);
}

public static T ModuloFreeGCD<T>(T left, T right)
{
if (GenericArithmetic<T>.Equal(left, GenericArithmetic<T>.Zero))
{
return right;
}
while (GenericArithmetic<T>.NotEqual(right, GenericArithmetic<T>.Zero))
{

if (GenericArithmetic<T>.GreaterThan(left, right))
{
left = GenericArithmetic<T>.Subtract(left, right);
}
else
{
right = GenericArithmetic<T>.Subtract(right, left);
}
}
return left;
}
}
}
16 changes: 16 additions & 0 deletions GenericMultivariatePolynomial/ExtensionMethods.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ExtendedArithmetic
{
public static class StringExtensionMethods
{
public static bool Contains(this string source, string value, StringComparison comparisonType)
{
return source?.IndexOf(value, comparisonType) >= 0;
}
}
}
169 changes: 159 additions & 10 deletions GenericMultivariatePolynomial/GenericArithmetic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Globalization;
using System.Runtime.CompilerServices;
using ExtendedArithmetic.Internal;
using System.Collections;

namespace ExtendedArithmetic
{
Expand Down Expand Up @@ -319,20 +320,28 @@ public static T GCD(IEnumerable<T> array)

public static T GCD(T left, T right)
{
T absLeft = Abs(left);
T absRight = Abs(right);
while (NotEqual(absLeft, Zero) && NotEqual(absRight, Zero))
if (ComplexHelperMethods.IsComplexValueType(typeof(T))
|| typeof(T).Name.Contains("BigDecimal", StringComparison.OrdinalIgnoreCase))
{
if (GreaterThan(absLeft, absRight))
{
absLeft = Modulo(absLeft, absRight);
}
else
return ComplexHelperMethods.ModuloFreeGCD(left, right);
}
else
{
T absLeft = Abs(left);
T absRight = Abs(right);
while (NotEqual(absLeft, Zero) && NotEqual(absRight, Zero))
{
absRight = Modulo(absRight, absLeft);
if (GreaterThan(absLeft, absRight))
{
absLeft = Modulo(absLeft, absRight);
}
else
{
absRight = Modulo(absRight, absLeft);
}
}
return Max(absLeft, absRight);
}
return Max(absLeft, absRight);
}

public static T Log(T value, double baseValue)
Expand All @@ -345,6 +354,85 @@ public static T Log(T value, double baseValue)
return _logFunction.Invoke(value, baseValue);
}

/// <summary>
/// Returns all divisors of an integer, including 1 and itself.
/// </summary>
public static List<T> GetAllDivisors(T value)
{
if (IsFloatingPointType(typeof(T)))
{
return GetAllDivisors_IntegerImpl(value);
}

T n = value;

if (Equal(Abs(n), One))
{
return new List<T> { n };
}

List<T> results = new List<T>();
if (Sign(n) == -1)
{
results.Add(MinusOne);
n = Multiply(n, MinusOne);
}

for (T i = One; LessThan(Multiply(i, i), n); i = Increment(i))
{
if (Equal(Modulo(n, i), Zero))
{
results.Add(i);
}
}

for (T i = SquareRoot(n); GreaterThanOrEqual(i, One); i = Decrement(i))
{
if (Equal(Modulo(n, i), Zero))
{
results.Add(Divide(n, i));
}
}
return results;
}

private static List<T> GetAllDivisors_IntegerImpl(T value)
{
int n = ConvertImplementation<T, int>.Convert(value);

List<int> results = new List<int>();
if (Math.Abs(n) == 1)
{
results.Add(n);
}
else
{
if (Math.Sign(n) == -1)
{
results.Add(-1);
n = n * -1;
}

for (int i = 1; i * i < n; i++)
{
if (GenericArithmetic<int>.Modulo(n, i) == 0)
{
results.Add(i);
}
}

for (int i = GenericArithmetic<int>.SquareRoot(n); i >= 1; i--)
{
if (GenericArithmetic<int>.Modulo(n, i) == 0)
{
results.Add(n / i);
}
}
}

return results.Select(i => ConvertImplementation<int, T>.Convert(i)).ToList();
}

public static byte[] ToBytes(T input)
{
Type typeFromHandle = typeof(T);
Expand Down Expand Up @@ -415,6 +503,67 @@ public static bool IsWholeNumber(T value)
return false;
}

public static bool IsFloatingPointType(Type type)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
type = type.GetGenericArguments()[0];
}
TypeCode typeCode = GenericArithmeticCommon.GetTypeCode(typeof(T));

if (typeCode == TypeCode.Single || typeCode == TypeCode.Double || typeCode == TypeCode.Decimal)
{
return true;
}

//if (type.Name.Contains("Decimal", StringComparison.OrdinalIgnoreCase)) // BigDecimal
//{
// return true;
//}

return false;
}

public static bool IsIntegerType(Type type)
{
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
type = type.GetGenericArguments()[0];
}
TypeCode typeCode = GenericArithmeticCommon.GetTypeCode(typeof(T));
uint typeCodeValue = (uint)typeCode;

if (type == typeof(BigInteger))
{
return true;
}
else if (typeCodeValue >= 5 && typeCodeValue <= 12) // Is between SByte and UInt64
{
return true;
}
else if (typeCode == TypeCode.Double || typeCode == TypeCode.Decimal)
{
return false;
}
else if (ComplexHelperMethods.IsComplexValueType(type))
{
return false;
}
else if (type.Name.Contains("Rational", StringComparison.OrdinalIgnoreCase) // BigRational
|| type.Name.Contains("Decimal", StringComparison.OrdinalIgnoreCase) // BigDecimal
|| type.Name.Contains("Fraction", StringComparison.OrdinalIgnoreCase) // Fraction
|| type.Name.Contains("Float", StringComparison.OrdinalIgnoreCase)) // BigFloat
{
return false;
}
else if (type.Name.Contains("Integer", StringComparison.OrdinalIgnoreCase))
{
return true;
}

return false; // ???
}

public static bool IsFractionalValue(T value)
{
return (GenericArithmeticCommon.IsArithmeticValueType(value.GetType()) && !IsWholeNumber(value));
Expand Down
16 changes: 16 additions & 0 deletions GenericMultivariatePolynomial/Indeterminate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ public class Indeterminate : ICloneable<Indeterminate>, IEquatable<Indeterminate
public char Symbol { get; }
public int Exponent { get; }

internal static Indeterminate[] Empty = new Indeterminate[0];
internal static Indeterminate[] Zero = new Indeterminate[] { new Indeterminate('X', 0) };

private UnicodeCategory[] AllowedSymbolCategories = new UnicodeCategory[]
{
UnicodeCategory.LowercaseLetter,
Expand Down Expand Up @@ -84,6 +87,15 @@ public bool Equals(Indeterminate x, Indeterminate y)
return true;
}

internal static bool AreCompatable(Indeterminate left, Indeterminate right)
{
if (left.Exponent == 0 || right.Exponent == 0)
{
return left.Exponent == right.Exponent;
}
return left.Symbol == right.Symbol;
}

public override bool Equals(object obj)
{
return this.Equals(obj as Indeterminate);
Expand All @@ -96,6 +108,10 @@ public int GetHashCode(Indeterminate obj)

public override int GetHashCode()
{
if (Exponent == 0)
{
return new Tuple<char, int>('X', 0).GetHashCode();
}
return new Tuple<char, int>(Symbol, Exponent).GetHashCode();
}

Expand Down
Loading

0 comments on commit 31035ce

Please # to comment.