/// <summary>Computes the nearest number greater than or equal to the /// specified start value that is coprime to another specified value. /// Returns 0 if no coprime was found in the range start to MaxValue.</summary> /// <param name="start">The start value.</param> /// <param name="value2">The value to test against.</param> /// <returns>The largest value that is less than or equal to the start value /// and also coprime to the other specified value.</returns> public static long NearestCoprimeCeiling(this long start, long value2) { ulong v1, v2; v2 = (value2 >= 0) ? (ulong)value2 : value2.AbsU(); if ((value2 == 0) && (start <= -1)) { return(-1); } if ((start == int.MaxValue) || ((value2 == 0) && (start > 1))) { return(0); } v1 = start.AbsU(); if (start >= 0) { while (!IsCoprime(v1, v2)) { if (v1 == long.MaxValue) { return(0); } v1++; } return((long)v1); } else { while (!IsCoprime(v1, v2)) { v1--; } return(-(long)v1); } }
/// <summary>Computes the greatest common divisor of two values.</summary> /// <param name="value1">The first value.</param> /// <param name="value2">The other value.</param> /// <returns>The greatest common divisor of the two values.</returns> public static long Gcd(this long value1, long value2) { if ((value1 | value2) < 0) { return((long)Gcd(value1.AbsU(), value2.AbsU())); } return((long)Gcd((ulong)value1, (ulong)value2)); }
/// <summary>Compute the modulo (division remainder) of a number multiplied by another number.</summary> /// <remarks>Overflow safe for all input values. </remarks> /// <param name="value1">The number to be multiplied by value2.</param> /// <param name="value2">The number to be multiplied by value1.</param> /// <param name="modulus">The number by which to divide value raised to the exponent power.</param> /// <returns>The remainder after dividing the product of multiplying value1 and value2.</returns> public static long MulMod(this long value1, long value2, long modulus) { if (modulus <= 0) { return(0); } unchecked { if ((value1 | value2) >= 0) { return((long)MulMod((ulong)value1, (ulong)value2, (ulong)modulus)); } return(((1 | (value1 ^ value2) >> 63)) * (long)MulMod(value1.AbsU(), value2.AbsU(), (ulong)modulus)); } }
/// <summary>Computes the nearest number less than or equal to the /// specified start value that is coprime to another specified value. /// Returns 0 if no coprime was found in the range MinValue to start.</summary> /// <param name="start">The start value.</param> /// <param name="value2">The value to test against.</param> /// <returns>The largest value that is less than or equal to the start value /// and also coprime to the other specified value.</returns> public static long NearestCoprimeFloor(this long start, long value2) { ulong v1, v2; v2 = (value2 >= 0) ? (ulong)value2 : value2.AbsU(); if (start > 0) { return((long)NearestCoprimeFloor((ulong)start, v2)); } if ((v2 == 0) && (start < -1)) { return(0); } for (v1 = start.AbsU(); v1 <= (ulong)(-(long.MinValue + 1)) + 1; v1++) { if (v1.IsCoprime(v2)) { return(-(long)v1); } } return(0); }