/// <summary> /// Gets the least common multiple of two elements in a <see cref="IEuclideanDomain{T, TFirst, TSecond}"/> via Euclid's algorithm. The LCDM is defined as: /// <code> /// r.Mult(r.Gcd(x,y), r.Lcm(x,y)) == r.Mult(x,y) /// </code> /// </summary> /// <typeparam name="T">The type of the carrier set.</typeparam> /// <typeparam name="TFirst">The type of the first grouplike operation.</typeparam> /// <typeparam name="TSecond">The type of the second groupike operation.</typeparam> /// <param name="r">The ringlike structure.</param> /// <param name="x">The first element.</param> /// <param name="y">The second element.</param> /// <exception cref="DivideByZeroException">If <paramref name="x"/> or <paramref name="y"/> is zero.</exception> public static T Lcm <T, TFirst, TSecond>(this IEuclideanDomain <T, TFirst, TSecond> r, T x, T y) where TFirst : ICommutativeGroup <T> where TSecond : IMonoid <T>, ICommutative <T> { if (r.IsZero(x) || r.IsZero(y)) { throw new DivideByZeroException(); } var gcd = r.Gcd(x, y); var numerator = r.Mult(x, y); var ret = r.EuclideanDivide(numerator, gcd).quotient; return(ret); }
/// <summary> /// Gets the greatest common divisor of two elements in a <see cref="IEuclideanDomain{T, TFirst, TSecond}"/> via Euclid's algorithm. The GCD of two elements <c>X</c> and <c>Y</c> is the unique minimal principal ideal. /// </summary> /// <typeparam name="T">The type of the carrier set.</typeparam> /// <typeparam name="TFirst">The type of the first grouplike operation.</typeparam> /// <typeparam name="TSecond">The type of the second groupike operation.</typeparam> /// <param name="r">The ringlike structure.</param> /// <param name="x">The first element.</param> /// <param name="y">The second element.</param> public static T Gcd <T, TFirst, TSecond>(this IEuclideanDomain <T, TFirst, TSecond> r, T x, T y) where TFirst : ICommutativeGroup <T> where TSecond : IMonoid <T>, ICommutative <T> { if (r.IsZero(x) || r.IsZero(y)) { return(r.Zero <T, TFirst>()); } while (!r.IsZero(y)) { var t = y; y = r.EuclideanDivide(x, y).remainder; x = t; } return(x); }
/// <summary> /// Performs the modulus-operation on two elements, returning the remainder of <see cref="IEuclideanDomain{T, TFirst, TSecond}.EuclideanDivide(T, T)"/>. /// </summary> /// <typeparam name="T">The type of the carrier set.</typeparam> /// <typeparam name="TFirst">The type of the first grouplike operation.</typeparam> /// <typeparam name="TSecond">The type of the second groupike operation.</typeparam> /// <param name="r">The ringlike structure.</param> /// <param name="x">The first element.</param> /// <param name="y">The second element.</param> public static T Mod <T, TFirst, TSecond>(this IEuclideanDomain <T, TFirst, TSecond> r, T x, T y) where TFirst : ICommutativeGroup <T> where TSecond : IMonoid <T>, ICommutative <T> => r.EuclideanDivide(x, y).remainder;