/// <summary> /// Multiplies two big integers. /// </summary> /// <param name="int1">First big integer.</param> /// <param name="int2">Second big integer.</param> /// <returns>Resulting big integer.</returns> /// <exception cref="ArgumentNullException"><paramref name="int1" /> or <paramref name="int2" /> is a null reference.</exception> /// <exception cref="ArgumentException"><paramref name="int1" /> or <paramref name="int2" /> is too big for multiply operation.</exception> virtual public BigInteger Multiply(BigInteger int1, BigInteger int2) { // Exceptions if (ReferenceEquals(int1, null)) { throw new ArgumentNullException("int1", Strings.CantBeNull); } else if (ReferenceEquals(int2, null)) { throw new ArgumentNullException("int2", Strings.CantBeNull); } // Special behavior for zero cases if (int1._length == 0 || int2._length == 0) return new BigInteger(0); // Get new big integer length and check it ulong newLength = (ulong)int1._length + int2._length; if (newLength >> 32 != 0) { throw new ArgumentException(Strings.IntegerTooBig); } // Create resulting big int BigInteger newInt = new BigInteger((uint)newLength, int1._negative ^ int2._negative); // Perform actual digits multiplication newInt._length = Multiply(int1._digits, int1._length, int2._digits, int2._length, newInt._digits); // Normalization may be needed newInt.TryNormalize(); return newInt; }
/// <summary> /// Adds two big integers. /// </summary> /// <param name="int1">First big integer.</param> /// <param name="int2">Second big integer.</param> /// <returns>Resulting big integer.</returns> /// <exception cref="ArgumentException"><paramref name="int1" /> or <paramref name="int2" /> is too big for add operation.</exception> static public BigInteger Add(BigInteger int1, BigInteger int2) { // Process zero values in special way if (int2._length == 0) return new BigInteger(int1); if (int1._length == 0) { BigInteger x = new BigInteger(int2); x._negative = int1._negative; // always get sign of the first big integer return x; } // Determine big int with lower length BigInteger smallerInt; BigInteger biggerInt; DigitHelper.GetMinMaxLengthObjects(int1, int2, out smallerInt, out biggerInt); // Check for add operation possibility if (biggerInt._length == uint.MaxValue) { throw new ArgumentException(Strings.IntegerTooBig); } // Create new big int object of needed length BigInteger newInt = new BigInteger(biggerInt._length + 1, int1._negative); // Do actual addition newInt._length = DigitOpHelper.Add( biggerInt._digits, biggerInt._length, smallerInt._digits, smallerInt._length, newInt._digits); // Normalization may be needed newInt.TryNormalize(); return newInt; }
/// <summary> /// Subtracts two big integers. /// </summary> /// <param name="int1">First big integer.</param> /// <param name="int2">Second big integer.</param> /// <returns>Resulting big integer.</returns> static public BigInteger Sub(BigInteger int1, BigInteger int2) { // Process zero values in special way if (int1._length == 0) return new BigInteger(int2._digits, true); if (int2._length == 0) return new BigInteger(int1); // Determine lower big int (without sign) BigInteger smallerInt; BigInteger biggerInt; int compareResult = DigitOpHelper.Cmp(int1._digits, int1._length, int2._digits, int2._length); if (compareResult == 0) return new BigInteger(0); // integers are equal if (compareResult < 0) { smallerInt = int1; biggerInt = int2; } else { smallerInt = int2; biggerInt = int1; } // Create new big int object BigInteger newInt = new BigInteger(biggerInt._length, ReferenceEquals(int1, smallerInt) ^ int1._negative); // Do actual subtraction newInt._length = DigitOpHelper.Sub( biggerInt._digits, biggerInt._length, smallerInt._digits, smallerInt._length, newInt._digits); // Normalization may be needed newInt.TryNormalize(); return newInt; }