// // Math.NET Numerics, part of the Math.NET Project // http://numerics.mathdotnet.com // http://github.com/mathnet/mathnet-numerics // // Copyright (c) 2009-2014 Math.NET // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the "Software"), to deal in the Software without // restriction, including without limitation the rights to use, // copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following // conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // using System; using System.Collections.Generic; using System.Runtime.CompilerServices; using BigInteger = System.Numerics.BigInteger; namespace IStation.Numerics { /// /// Integer number theory functions. /// public static class Euclid { /// /// Canonical Modulus. The result has the sign of the divisor. /// #if !NET40 [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static double Modulus(double dividend, double divisor) { return ((dividend%divisor) + divisor)%divisor; } /// /// Canonical Modulus. The result has the sign of the divisor. /// #if !NET40 [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static float Modulus(float dividend, float divisor) { return ((dividend%divisor) + divisor)%divisor; } /// /// Canonical Modulus. The result has the sign of the divisor. /// #if !NET40 [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static int Modulus(int dividend, int divisor) { return ((dividend%divisor) + divisor)%divisor; } /// /// Canonical Modulus. The result has the sign of the divisor. /// #if !NET40 [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static long Modulus(long dividend, long divisor) { return ((dividend%divisor) + divisor)%divisor; } /// /// Canonical Modulus. The result has the sign of the divisor. /// #if !NET40 [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static BigInteger Modulus(BigInteger dividend, BigInteger divisor) { return ((dividend%divisor) + divisor)%divisor; } /// /// Remainder (% operator). The result has the sign of the dividend. /// #if !NET40 [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static double Remainder(double dividend, double divisor) { return dividend%divisor; } /// /// Remainder (% operator). The result has the sign of the dividend. /// #if !NET40 [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static float Remainder(float dividend, float divisor) { return dividend%divisor; } /// /// Remainder (% operator). The result has the sign of the dividend. /// #if !NET40 [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static int Remainder(int dividend, int divisor) { return dividend%divisor; } /// /// Remainder (% operator). The result has the sign of the dividend. /// #if !NET40 [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static long Remainder(long dividend, long divisor) { return dividend%divisor; } /// /// Remainder (% operator). The result has the sign of the dividend. /// #if !NET40 [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static BigInteger Remainder(BigInteger dividend, BigInteger divisor) { return dividend%divisor; } /// /// Find out whether the provided 32 bit integer is an even number. /// /// The number to very whether it's even. /// True if and only if it is an even number. #if !NET40 [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static bool IsEven(this int number) { return (number & 0x1) == 0x0; } /// /// Find out whether the provided 64 bit integer is an even number. /// /// The number to very whether it's even. /// True if and only if it is an even number. #if !NET40 [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static bool IsEven(this long number) { return (number & 0x1) == 0x0; } /// /// Find out whether the provided 32 bit integer is an odd number. /// /// The number to very whether it's odd. /// True if and only if it is an odd number. #if !NET40 [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static bool IsOdd(this int number) { return (number & 0x1) == 0x1; } /// /// Find out whether the provided 64 bit integer is an odd number. /// /// The number to very whether it's odd. /// True if and only if it is an odd number. #if !NET40 [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static bool IsOdd(this long number) { return (number & 0x1) == 0x1; } /// /// Find out whether the provided 32 bit integer is a perfect power of two. /// /// The number to very whether it's a power of two. /// True if and only if it is a power of two. #if !NET40 [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static bool IsPowerOfTwo(this int number) { return number > 0 && (number & (number - 1)) == 0x0; } /// /// Find out whether the provided 64 bit integer is a perfect power of two. /// /// The number to very whether it's a power of two. /// True if and only if it is a power of two. #if !NET40 [MethodImpl(MethodImplOptions.AggressiveInlining)] #endif public static bool IsPowerOfTwo(this long number) { return number > 0 && (number & (number - 1)) == 0x0; } /// /// Find out whether the provided 32 bit integer is a perfect square, i.e. a square of an integer. /// /// The number to very whether it's a perfect square. /// True if and only if it is a perfect square. public static bool IsPerfectSquare(this int number) { if (number < 0) { return false; } int lastHexDigit = number & 0xF; if (lastHexDigit > 9) { return false; // return immediately in 6 cases out of 16. } if (lastHexDigit == 0 || lastHexDigit == 1 || lastHexDigit == 4 || lastHexDigit == 9) { int t = (int)Math.Floor(Math.Sqrt(number) + 0.5); return (t * t) == number; } return false; } /// /// Find out whether the provided 64 bit integer is a perfect square, i.e. a square of an integer. /// /// The number to very whether it's a perfect square. /// True if and only if it is a perfect square. public static bool IsPerfectSquare(this long number) { if (number < 0) { return false; } int lastHexDigit = (int)(number & 0xF); if (lastHexDigit > 9) { return false; // return immediately in 6 cases out of 16. } if (lastHexDigit == 0 || lastHexDigit == 1 || lastHexDigit == 4 || lastHexDigit == 9) { long t = (long)Math.Floor(Math.Sqrt(number) + 0.5); return (t * t) == number; } return false; } /// /// Raises 2 to the provided integer exponent (0 <= exponent < 31). /// /// The exponent to raise 2 up to. /// 2 ^ exponent. /// public static int PowerOfTwo(this int exponent) { if (exponent < 0 || exponent >= 31) { throw new ArgumentOutOfRangeException(nameof(exponent)); } return 1 << exponent; } /// /// Raises 2 to the provided integer exponent (0 <= exponent < 63). /// /// The exponent to raise 2 up to. /// 2 ^ exponent. /// public static long PowerOfTwo(this long exponent) { if (exponent < 0 || exponent >= 63) { throw new ArgumentOutOfRangeException(nameof(exponent)); } return ((long)1) << (int)exponent; } /// /// Evaluate the binary logarithm of an integer number. /// /// Two-step method using a De Bruijn-like sequence table lookup. public static int Log2(this int number) { number |= number >> 1; number |= number >> 2; number |= number >> 4; number |= number >> 8; number |= number >> 16; return MultiplyDeBruijnBitPosition[(uint)(number * 0x07C4ACDDU) >> 27]; } static readonly int[] MultiplyDeBruijnBitPosition = new int[32] { 0, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18, 22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31 }; /// /// Find the closest perfect power of two that is larger or equal to the provided /// 32 bit integer. /// /// The number of which to find the closest upper power of two. /// A power of two. /// public static int CeilingToPowerOfTwo(this int number) { if (number == Int32.MinValue) { return 0; } const int maxPowerOfTwo = 0x40000000; if (number > maxPowerOfTwo) { throw new ArgumentOutOfRangeException(nameof(number)); } number--; number |= number >> 1; number |= number >> 2; number |= number >> 4; number |= number >> 8; number |= number >> 16; return number + 1; } /// /// Find the closest perfect power of two that is larger or equal to the provided /// 64 bit integer. /// /// The number of which to find the closest upper power of two. /// A power of two. /// public static long CeilingToPowerOfTwo(this long number) { if (number == Int64.MinValue) { return 0; } const long maxPowerOfTwo = 0x4000000000000000; if (number > maxPowerOfTwo) { throw new ArgumentOutOfRangeException(nameof(number)); } number--; number |= number >> 1; number |= number >> 2; number |= number >> 4; number |= number >> 8; number |= number >> 16; number |= number >> 32; return number + 1; } /// /// Returns the greatest common divisor (gcd) of two integers using Euclid's algorithm. /// /// First Integer: a. /// Second Integer: b. /// Greatest common divisor gcd(a,b) public static long GreatestCommonDivisor(long a, long b) { while (b != 0) { var remainder = a%b; a = b; b = remainder; } return Math.Abs(a); } /// /// Returns the greatest common divisor (gcd) of a set of integers using Euclid's /// algorithm. /// /// List of Integers. /// Greatest common divisor gcd(list of integers) public static long GreatestCommonDivisor(IList integers) { if (null == integers) { throw new ArgumentNullException(nameof(integers)); } if (integers.Count == 0) { return 0; } var gcd = Math.Abs(integers[0]); for (var i = 1; (i < integers.Count) && (gcd > 1); i++) { gcd = GreatestCommonDivisor(gcd, integers[i]); } return gcd; } /// /// Returns the greatest common divisor (gcd) of a set of integers using Euclid's algorithm. /// /// List of Integers. /// Greatest common divisor gcd(list of integers) public static long GreatestCommonDivisor(params long[] integers) { return GreatestCommonDivisor((IList)integers); } /// /// Computes the extended greatest common divisor, such that a*x + b*y = gcd(a,b). /// /// First Integer: a. /// Second Integer: b. /// Resulting x, such that a*x + b*y = gcd(a,b). /// Resulting y, such that a*x + b*y = gcd(a,b) /// Greatest common divisor gcd(a,b) /// /// /// long x,y,d; /// d = Fn.GreatestCommonDivisor(45,18,out x, out y); /// -> d == 9 && x == 1 && y == -2 /// /// The gcd of 45 and 18 is 9: 18 = 2*9, 45 = 5*9. 9 = 1*45 -2*18, therefore x=1 and y=-2. /// public static long ExtendedGreatestCommonDivisor(long a, long b, out long x, out long y) { long mp = 1, np = 0, m = 0, n = 1; while (b != 0) { long rem; #if NETSTANDARD1_3 rem = a % b; var quot = a / b; #else long quot = Math.DivRem(a, b, out rem); #endif a = b; b = rem; var tmp = m; m = mp - (quot*m); mp = tmp; tmp = n; n = np - (quot*n); np = tmp; } if (a >= 0) { x = mp; y = np; return a; } x = -mp; y = -np; return -a; } /// /// Returns the least common multiple (lcm) of two integers using Euclid's algorithm. /// /// First Integer: a. /// Second Integer: b. /// Least common multiple lcm(a,b) public static long LeastCommonMultiple(long a, long b) { if ((a == 0) || (b == 0)) { return 0; } return Math.Abs((a/GreatestCommonDivisor(a, b))*b); } /// /// Returns the least common multiple (lcm) of a set of integers using Euclid's algorithm. /// /// List of Integers. /// Least common multiple lcm(list of integers) public static long LeastCommonMultiple(IList integers) { if (null == integers) { throw new ArgumentNullException(nameof(integers)); } if (integers.Count == 0) { return 1; } var lcm = Math.Abs(integers[0]); for (var i = 1; i < integers.Count; i++) { lcm = LeastCommonMultiple(lcm, integers[i]); } return lcm; } /// /// Returns the least common multiple (lcm) of a set of integers using Euclid's algorithm. /// /// List of Integers. /// Least common multiple lcm(list of integers) public static long LeastCommonMultiple(params long[] integers) { return LeastCommonMultiple((IList)integers); } /// /// Returns the greatest common divisor (gcd) of two big integers. /// /// First Integer: a. /// Second Integer: b. /// Greatest common divisor gcd(a,b) public static BigInteger GreatestCommonDivisor(BigInteger a, BigInteger b) { return BigInteger.GreatestCommonDivisor(a, b); } /// /// Returns the greatest common divisor (gcd) of a set of big integers. /// /// List of Integers. /// Greatest common divisor gcd(list of integers) public static BigInteger GreatestCommonDivisor(IList integers) { if (null == integers) { throw new ArgumentNullException(nameof(integers)); } if (integers.Count == 0) { return 0; } var gcd = BigInteger.Abs(integers[0]); for (int i = 1; (i < integers.Count) && (gcd > BigInteger.One); i++) { gcd = GreatestCommonDivisor(gcd, integers[i]); } return gcd; } /// /// Returns the greatest common divisor (gcd) of a set of big integers. /// /// List of Integers. /// Greatest common divisor gcd(list of integers) public static BigInteger GreatestCommonDivisor(params BigInteger[] integers) { return GreatestCommonDivisor((IList)integers); } /// /// Computes the extended greatest common divisor, such that a*x + b*y = gcd(a,b). /// /// First Integer: a. /// Second Integer: b. /// Resulting x, such that a*x + b*y = gcd(a,b). /// Resulting y, such that a*x + b*y = gcd(a,b) /// Greatest common divisor gcd(a,b) /// /// /// long x,y,d; /// d = Fn.GreatestCommonDivisor(45,18,out x, out y); /// -> d == 9 && x == 1 && y == -2 /// /// The gcd of 45 and 18 is 9: 18 = 2*9, 45 = 5*9. 9 = 1*45 -2*18, therefore x=1 and y=-2. /// public static BigInteger ExtendedGreatestCommonDivisor(BigInteger a, BigInteger b, out BigInteger x, out BigInteger y) { BigInteger mp = BigInteger.One, np = BigInteger.Zero, m = BigInteger.Zero, n = BigInteger.One; while (!b.IsZero) { BigInteger rem; BigInteger quot = BigInteger.DivRem(a, b, out rem); a = b; b = rem; BigInteger tmp = m; m = mp - (quot*m); mp = tmp; tmp = n; n = np - (quot*n); np = tmp; } if (a >= BigInteger.Zero) { x = mp; y = np; return a; } x = -mp; y = -np; return -a; } /// /// Returns the least common multiple (lcm) of two big integers. /// /// First Integer: a. /// Second Integer: b. /// Least common multiple lcm(a,b) public static BigInteger LeastCommonMultiple(BigInteger a, BigInteger b) { if (a.IsZero || b.IsZero) { return BigInteger.Zero; } return BigInteger.Abs((a/BigInteger.GreatestCommonDivisor(a, b))*b); } /// /// Returns the least common multiple (lcm) of a set of big integers. /// /// List of Integers. /// Least common multiple lcm(list of integers) public static BigInteger LeastCommonMultiple(IList integers) { if (null == integers) { throw new ArgumentNullException(nameof(integers)); } if (integers.Count == 0) { return 1; } var lcm = BigInteger.Abs(integers[0]); for (int i = 1; i < integers.Count; i++) { lcm = LeastCommonMultiple(lcm, integers[i]); } return lcm; } /// /// Returns the least common multiple (lcm) of a set of big integers. /// /// List of Integers. /// Least common multiple lcm(list of integers) public static BigInteger LeastCommonMultiple(params BigInteger[] integers) { return LeastCommonMultiple((IList)integers); } } }