/// <summary> /// Splits the range on the given <paramref name="splitPoint"/>. /// </summary> /// <param name="splitPoint">The point on the range to split it.</param> /// <param name="includeSplitPointToUpperRange">Which range gets the <paramref name="splitPoint"/>?</param> /// <param name="whatToDoWithResults">What to do with the result?</param> /// <returns>Result <see cref="IRangeMathableSingleSize{UInt64, BigInteger}"/>s.</returns> public IRangeMathableSingleSize <UInt64, BigInteger>[] Split(UInt64 splitPoint, bool includeSplitPointToUpperRange, RangeMathematicResultUseage whatToDoWithResults) { IRangeMathableSingleSize <UInt64, BigInteger>[] result; if (TheRange.EmptyRange) { result = new IRangeMathableSingleSize <UInt64, BigInteger>[2] { default(UInt64RangeMathable), default(UInt64RangeMathable) }; } else { result = new IRangeMathableSingleSize <UInt64, BigInteger> [2]; switch (TheRange.CompareTo(splitPoint)) { case -1: result[0] = new UInt64RangeMathable(TheRange.EmptyRange, TheRange.StartBound, TheRange.EndBound); result[1] = default(UInt64RangeMathable); break; case 0: if (includeSplitPointToUpperRange) { if (TheRange.StartBound == TheRange.EndBound || TheRange.StartBound == splitPoint) { result[0] = default(UInt64RangeMathable); result[1] = new UInt64RangeMathable(TheRange.EmptyRange, TheRange.StartBound, TheRange.EndBound); } else { result[0] = new UInt64RangeMathable(TheRange.EmptyRange, TheRange.StartBound, (splitPoint - 1)); result[1] = new UInt64RangeMathable(TheRange.EmptyRange, splitPoint, TheRange.EndBound); } } else { if (TheRange.StartBound == TheRange.EndBound || TheRange.EndBound == splitPoint) { result[0] = new UInt64RangeMathable(TheRange.EmptyRange, TheRange.StartBound, TheRange.EndBound); result[1] = default(UInt64RangeMathable); } else { result[0] = new UInt64RangeMathable(TheRange.EmptyRange, TheRange.StartBound, splitPoint); result[1] = new UInt64RangeMathable(TheRange.EmptyRange, (splitPoint + 1), TheRange.EndBound); } } break; case 1: result[0] = default(UInt64RangeMathable); result[1] = new UInt64RangeMathable(TheRange.EmptyRange, TheRange.StartBound, TheRange.EndBound); break; } } // working with the result to do the wanted actions if ((whatToDoWithResults & RangeMathematicResultUseage.UseLowestResultRangeOnOwnRange) > 0) { if (result[0].StartBound > TheRange.EndBound) { TheRange.EndBound = result[0].EndBound; TheRange.StartBound = result[0].StartBound; } else { TheRange.StartBound = result[0].StartBound; TheRange.EndBound = result[0].EndBound; } TheRange.EmptyRange = result[0].EmptyRange; } else if ((whatToDoWithResults & RangeMathematicResultUseage.UseHighestResultRangeOnOwnRange) > 0) { if (result[1].StartBound > TheRange.EndBound) { TheRange.EndBound = result[1].EndBound; TheRange.StartBound = result[1].StartBound; } else { TheRange.StartBound = result[1].StartBound; TheRange.EndBound = result[1].EndBound; } TheRange.EmptyRange = result[1].EmptyRange; } return(result); }
/// <summary> /// Splits the range in nearly equal sized ranges. /// </summary> /// <param name="includeOddToUpperRange">If the range range is odd where to add the element on the split to?</param> /// <param name="whatToDoWithResults">What to do with the result?</param> /// <returns>Result <see cref="IRangeMathable{UInt64, BigInteger}"/>s.</returns> public IRangeMathableSingleSize <UInt64, BigInteger>[] Split(bool includeOddToUpperRange, RangeMathematicResultUseage whatToDoWithResults) { IRangeMathableSingleSize <UInt64, BigInteger>[] result = new IRangeMathableSingleSize <UInt64, BigInteger> [2]; BigInteger tempSize = BigInteger.ToUInt64(RangeSize()); switch (tempSize.CompareTo(new BigInteger(1))) { case -1: result[0] = default(UInt64RangeMathable); result[1] = default(UInt64RangeMathable); break; case 0: if (includeOddToUpperRange) { result[0] = default(UInt64RangeMathable); result[1] = new UInt64RangeMathable(true, TheRange.StartBound, TheRange.EndBound); } else { result[0] = new UInt64RangeMathable(true, TheRange.StartBound, TheRange.EndBound); result[1] = default(UInt64RangeMathable); } break; case 1: bool storedOddBit = (tempSize & 1) == 1; BigInteger halfSize = tempSize >> 1; if (storedOddBit) { if (halfSize > 0) { if (includeOddToUpperRange) { result[0] = new UInt64RangeMathable(false, TheRange.StartBound, (TheRange.StartBound + BigInteger.ToUInt64(halfSize) - 1)); result[1] = new UInt64RangeMathable(false, (TheRange.EndBound - BigInteger.ToUInt64(halfSize)), TheRange.EndBound); } else { result[0] = new UInt64RangeMathable(false, TheRange.StartBound, (TheRange.StartBound + BigInteger.ToUInt64(halfSize))); result[1] = new UInt64RangeMathable(false, (TheRange.EndBound - BigInteger.ToUInt64(halfSize) + 1), TheRange.EndBound); } } else { if (includeOddToUpperRange) { result[0] = default(UInt64RangeMathable); result[1] = new UInt64RangeMathable(false, TheRange.EndBound, TheRange.EndBound); } else { result[0] = new UInt64RangeMathable(false, TheRange.StartBound, TheRange.StartBound); result[1] = default(UInt64RangeMathable); } } } else { if (halfSize > 0) { result[0] = new UInt64RangeMathable(false, TheRange.StartBound, (TheRange.StartBound + BigInteger.ToUInt64(halfSize) - 1)); result[1] = new UInt64RangeMathable(false, (TheRange.EndBound - BigInteger.ToUInt64(halfSize) + 1), TheRange.EndBound); } else { result[0] = default(UInt64RangeMathable); result[1] = default(UInt64RangeMathable); } } break; } // working with the result to do the wanted actions if ((whatToDoWithResults & RangeMathematicResultUseage.UseLowestResultRangeOnOwnRange) > 0) { if (result[0].StartBound > TheRange.EndBound) { TheRange.EndBound = result[0].EndBound; TheRange.StartBound = result[0].StartBound; } else { TheRange.StartBound = result[0].StartBound; TheRange.EndBound = result[0].EndBound; } TheRange.EmptyRange = result[0].EmptyRange; } else if ((whatToDoWithResults & RangeMathematicResultUseage.UseHighestResultRangeOnOwnRange) > 0) { if (result[1].StartBound > TheRange.EndBound) { TheRange.EndBound = result[1].EndBound; TheRange.StartBound = result[1].StartBound; } else { TheRange.StartBound = result[1].StartBound; TheRange.EndBound = result[1].EndBound; } TheRange.EmptyRange = result[1].EmptyRange; } return(result); }
/// <summary> /// Combines this range with the given range <paramref name="toCombine"/> based on the given <see cref="RangeCombination"/>. /// </summary> /// <param name="toCombine">The other range to combine with.</param> /// <param name="combinationType">How to combine the 2 ranges.</param> /// <param name="whatToDoWithResults">What to do with the result?</param> /// <returns>Result <see cref="IRangeMathable{UInt64, UInt64}"/>s.</returns> /// <exception cref="ArgumentOutOfRangeException">The <paramref name="combinationType"/> is not a valid <see cref="RangeCombination"/> value!</exception> public IRangeMathableSingleSize <UInt64, BigInteger>[] Combine(IRangeMathableSingleSize <UInt64, BigInteger> toCombine, RangeCombination combinationType, RangeMathematicResultUseage whatToDoWithResults) { IRangeMathableSingleSize <UInt64, BigInteger>[] result; if (toCombine == null) { result = new IRangeMathableSingleSize <UInt64, BigInteger> [1]; switch (combinationType) { case RangeCombination.Difference: case RangeCombination.Union: result[0] = new UInt64RangeMathable(TheRange.EmptyRange, TheRange.StartBound, TheRange.EndBound); break; case RangeCombination.Intersect: result[0] = default(UInt64RangeMathable); break; default: throw new ArgumentOutOfRangeException("The combinationType is not a valid RangeCombinations value!"); } } else { int comparationResult = CompareTo(toCombine); switch (combinationType) { case RangeCombination.Difference: if (TheRange.EmptyRange) { result = new IRangeMathableSingleSize <UInt64, BigInteger>[1] { new UInt64RangeMathable(toCombine.EmptyRange, toCombine.StartBound, toCombine.EndBound) }; } else if (toCombine.EmptyRange) { result = new IRangeMathableSingleSize <UInt64, BigInteger>[1] { new UInt64RangeMathable(TheRange.EmptyRange, TheRange.StartBound, TheRange.EndBound) }; } else { if (comparationResult == 0) { result = new IRangeMathableSingleSize <UInt64, BigInteger>[1] { new UInt64RangeMathable(true, 0, 0) }; } else { if (TheRange.EndBound < toCombine.EndBound) { result = new IRangeMathableSingleSize <UInt64, BigInteger> [2]; BigInteger tempNewBound = new BigInteger(toCombine.StartBound) - 1; if (tempNewBound <= TheRange.StartBound) { result[0] = new UInt64RangeMathable(true, TheRange.StartBound, TheRange.StartBound); } else { result[0] = new UInt64RangeMathable(false, TheRange.StartBound, BigInteger.ToUInt64(tempNewBound)); } tempNewBound = new BigInteger(toCombine.EndBound) + 1; if (tempNewBound >= toCombine.EndBound) { result[1] = new UInt64RangeMathable(true, toCombine.EndBound, toCombine.EndBound); } else { result[1] = new UInt64RangeMathable(false, BigInteger.ToUInt64(tempNewBound), toCombine.EndBound); } } else { BigInteger newEndBound = new BigInteger(toCombine.StartBound) - 1; if (newEndBound <= TheRange.StartBound) { result = new IRangeMathableSingleSize <UInt64, BigInteger>[1] { new UInt64RangeMathable(true, TheRange.StartBound, TheRange.StartBound) }; } else { result = new IRangeMathableSingleSize <UInt64, BigInteger>[1] { new UInt64RangeMathable(false, TheRange.StartBound, BigInteger.ToUInt64(newEndBound)) }; } } } } break; case RangeCombination.Intersect: result = new IRangeMathableSingleSize <UInt64, BigInteger> [1]; if (TheRange.EmptyRange || toCombine.EmptyRange) { result[0] = default(UInt64RangeMathable); } else { switch (comparationResult) { case -1: if (toCombine.StartBound > UInt64.MinValue && TheRange.EndBound < (toCombine.StartBound - 1)) { result[0] = default(UInt64RangeMathable); } else { if (TheRange.EndBound > toCombine.EndBound) { result[0] = new UInt64RangeMathable(false, toCombine.StartBound, toCombine.EndBound); } else { result[0] = new UInt64RangeMathable(false, toCombine.StartBound, TheRange.EndBound); } } break; case 0: result[0] = new UInt64RangeMathable(false, TheRange.StartBound, TheRange.EndBound); break; case 1: if (TheRange.StartBound < UInt64.MinValue && toCombine.EndBound < (TheRange.StartBound - 1)) { result[0] = default(UInt64RangeMathable); } else { if (toCombine.EndBound > TheRange.EndBound) { result[0] = new UInt64RangeMathable(false, toCombine.StartBound, toCombine.EndBound); } else { result[0] = new UInt64RangeMathable(false, toCombine.StartBound, TheRange.EndBound); } } break; } } break; case RangeCombination.Union: if (TheRange.EmptyRange && toCombine.EmptyRange) { result = new IRangeMathableSingleSize <UInt64, BigInteger>[1] { default(UInt64RangeMathable) }; } else { switch (comparationResult) { case -1: if (TheRange.EmptyRange) { result = new IRangeMathableSingleSize <UInt64, BigInteger>[1] { new UInt64RangeMathable(toCombine.EmptyRange, toCombine.StartBound, toCombine.EndBound) }; } else if (toCombine.EmptyRange) { result = new IRangeMathableSingleSize <UInt64, BigInteger>[1] { new UInt64RangeMathable(TheRange.EmptyRange, TheRange.StartBound, TheRange.EndBound) }; } else { if (TheRange.EndBound < UInt64.MaxValue && (TheRange.EndBound + 1) < toCombine.StartBound) { result = new IRangeMathableSingleSize <UInt64, BigInteger> [2]; result[0] = new UInt64RangeMathable(false, TheRange.StartBound, TheRange.EndBound); result[1] = new UInt64RangeMathable(false, toCombine.StartBound, toCombine.EndBound); } else { result = new IRangeMathableSingleSize <UInt64, BigInteger> [1]; if (TheRange.EndBound <= toCombine.EndBound) { result[0] = new UInt64RangeMathable(false, TheRange.StartBound, toCombine.EndBound); } else { result[0] = new UInt64RangeMathable(false, TheRange.StartBound, TheRange.EndBound); } } } break; case 0: result = new IRangeMathableSingleSize <UInt64, BigInteger>[1] { new UInt64RangeMathable(false, TheRange.StartBound, TheRange.EndBound) }; break; case 1: if (TheRange.EmptyRange) { result = new IRangeMathableSingleSize <UInt64, BigInteger>[1] { new UInt64RangeMathable(toCombine.EmptyRange, toCombine.StartBound, toCombine.EndBound) }; } else if (toCombine.EmptyRange) { result = new IRangeMathableSingleSize <UInt64, BigInteger>[1] { new UInt64RangeMathable(TheRange.EmptyRange, TheRange.StartBound, TheRange.EndBound) }; } else { if (toCombine.EndBound < UInt64.MaxValue && TheRange.StartBound < (toCombine.EndBound + 1)) { result = new IRangeMathableSingleSize <UInt64, BigInteger> [2]; result[1] = new UInt64RangeMathable(false, toCombine.StartBound, toCombine.EndBound); result[0] = new UInt64RangeMathable(false, TheRange.StartBound, TheRange.EndBound); } else { result = new IRangeMathableSingleSize <UInt64, BigInteger> [1]; if (TheRange.EndBound >= toCombine.EndBound) { result[0] = new UInt64RangeMathable(false, toCombine.StartBound, TheRange.EndBound); } else { result[0] = new UInt64RangeMathable(false, toCombine.StartBound, toCombine.EndBound); } } } break; } } result = new IRangeMathableSingleSize <UInt64, BigInteger>[1] { new UInt64RangeMathable(TheRange.EmptyRange, TheRange.StartBound, TheRange.EndBound) }; break; default: throw new ArgumentOutOfRangeException("The combinationType is not a valid RangeCombinations value!"); } } // working with the result to do the wanted actions if ((whatToDoWithResults & RangeMathematicResultUseage.UseLowestResultRangeOnOwnRange) > 0) { if (result[0].StartBound > TheRange.EndBound) { TheRange.EndBound = result[0].EndBound; TheRange.StartBound = result[0].StartBound; } else { TheRange.StartBound = result[0].StartBound; TheRange.EndBound = result[0].EndBound; } TheRange.EmptyRange = result[0].EmptyRange; } else if ((whatToDoWithResults & RangeMathematicResultUseage.UseHighestResultRangeOnOwnRange) > 0) { int targetPosition = result.Length - 1; if (result[targetPosition].StartBound > TheRange.EndBound) { TheRange.EndBound = result[targetPosition].EndBound; TheRange.StartBound = result[targetPosition].StartBound; } else { TheRange.StartBound = result[targetPosition].StartBound; TheRange.EndBound = result[targetPosition].EndBound; } TheRange.EmptyRange = result[targetPosition].EmptyRange; } return(result); }