private static IEnumerable <BigIntRange> EnumerateIncludedRanges(IEnumerable <BigIntRangeBound> sortedBounds) { BigInteger?prevBound = null; //only non-null when the previous bound is incomplete and needs the next bound before anything can be returned foreach (var bound in sortedBounds) { if (bound.Direction == Direction.Nowhere) { if (prevBound != null) { throw new InvalidOperationException("Underlying sorted set of range bounds is corrupt - previous bound (at value " + prevBound.Value + ") expected a matching closing bound next but current bound (at value " + bound.Bound + ") represents a single point."); } yield return(BigIntRange.Single(bound.Bound)); } else if (bound.Direction == Direction.Up) { if (prevBound != null) { throw new InvalidOperationException("Underlying sorted set of range bounds is corrupt - previous bound (at value " + prevBound.Value + ") expected a matching closing bound next but current bound (at value " + bound.Bound + ") represents the start of a new range."); } prevBound = bound.Bound; } else { if (prevBound == null) { throw new InvalidOperationException("Underlying sorted set of range bounds is corrupt - current bound (at value " + bound.Bound + ") represents the end of a range, but the previous bound was a complete range or there was no previous bound"); } yield return(BigIntRange.CreateStartEnd(prevBound.Value, bound.Bound)); prevBound = null; } } }
public IEnumerable <BigInteger> EnumerateIncludedValues(bool reverse = false) { if (_sortedSet.Count == 0) { return(Enumerable.Empty <BigInteger>()); } else { return(EnumerateIncludedValues(BigIntRange.CreateStartEnd(this.Min.Value, this.Max.Value), reverse)); } }
public static IEnumerable <BigInteger> IterateNonTrivialZeros(BigInteger maxZ, Action <ExpansionTerm> currentPathStartingPointPrinter = null) { var termOptions = new TermOptionsMatrix(maxZ); // var sortedEliminatedRanges = new List<BigIntRange>(); var eliminatedRanges = new RangeSet(); BigInteger prevStartingPointEval = BigInteger.Zero; //Starts lower than any evaluated starting point foreach (ExpansionTerm pathStartingPoint in EnumerateSortedTermOptions()) { currentPathStartingPointPrinter?.Invoke(pathStartingPoint); // Console.WriteLine("#25 current starting point: " + pathStartingPoint); // //Debugging: // eliminatedRanges.DebugBounds(); // foreach (var range in eliminatedRanges.IncludedRanges) { // Console.WriteLine("#40: " + range.Start + " to " + range.End); // } // Console.WriteLine("#41: " + eliminatedRanges.Count); BigInteger startingPointEval = pathStartingPoint.Evaluate(); if (startingPointEval > maxZ) { //If gone past end of requested range, return all remaining stored values //up to end of requested range, then stop enumerating. var gaps = eliminatedRanges.EnumerateExcludedValues( searchRange: BigIntRange.CreateStartEnd( start: prevStartingPointEval + 1, end: maxZ ) ); foreach (BigInteger gap in gaps) { yield return(gap); } // foreach (var range in eliminatedRanges.IncludedRanges) { // Console.WriteLine("#42: " + range.Start + " to " + range.End); // } // Console.WriteLine("#43: " + eliminatedRanges.Count); yield break; } foreach (BigInteger summedPath in termOptions.EnumerateSummedExpansionPaths(pathStartingPoint, capToMaximum: true)) { // Console.WriteLine("#44: " + summedPath + ", " + expansionPath.ToString(includeSpaces: false)); BigInteger newRangeMax = summedPath; BigInteger newRangeMin = summedPath; // Console.WriteLine("#44.1: " + newRangeMin + ", " + newRangeMax); //Exclude adjacent trivial zeros (multiples of 3) as well if ((newRangeMax + 1) % 3 == 0) { newRangeMax += 1; } if ((newRangeMin - 1) % 3 == 0) { newRangeMin -= 1; } // Console.WriteLine("#44.2: " + newRangeMin + ", " + newRangeMax); // Console.WriteLine("#45: " + eliminatedRanges.Count); eliminatedRanges.AddRange(BigIntRange.CreateStartEnd(newRangeMin, newRangeMax)); // Console.WriteLine("#46: " + eliminatedRanges.Count); } { // Console.WriteLine("#47: " + eliminatedRanges.Count); var gaps = eliminatedRanges.EnumerateExcludedValues( searchRange: BigIntRange.CreateStartEnd( start: prevStartingPointEval + 1, end: startingPointEval ) ); foreach (BigInteger gap in gaps) { yield return(gap); } // Console.WriteLine("#48"); } prevStartingPointEval = startingPointEval; } }
public bool TryGetSurroundingRange(BigInteger x, out BigIntRange range, out bool rangeIsIncluded) { BigIntRangeBound below; BigIntRangeBound above; if (TryGetSurroundingBounds(x, out below, out above)) { switch (below.Direction) { case Direction.Nowhere: range = BigIntRange.Single(below.Bound); //below == above rangeIsIncluded = true; return(true); case Direction.Down: switch (above.Direction) { case Direction.Down: throw new InvalidOperationException( "Underlying sorted set of range bounds is corrupt - the bound below or equal to " + nameof(x) + "=" + x + " " + "(at value " + below.Bound + ") represents the end of a range, but the bound above or equal " + "to " + nameof(x) + "=" + x + " (at value " + above.Bound + ") also represents the end of a range, meaning " + "this second range would have no starting value." ); case Direction.Nowhere: //Same behaviour as for Direction.Up case Direction.Up: if (BigInteger.Abs(below.Bound - above.Bound) >= 2) //If there is a gap between the bounds { range = BigIntRange.CreateStartEnd(below.Bound + 1, above.Bound - 1); rangeIsIncluded = false; return(true); } else { range = default(BigIntRange); rangeIsIncluded = default(bool); return(false); } default: break; } break; case Direction.Up: switch (above.Direction) { case Direction.Nowhere: throw new InvalidOperationException( "Underlying sorted set of range bounds is corrupt - the bound below or equal to " + nameof(x) + "=" + x + " " + "(at value " + below.Bound + ") represents the start of a range, so and end to this range is expected next, " + "but the bound above or equal to " + nameof(x) + "=" + x + " (at value " + above.Bound + ") represents a range " + "containing only single value." ); case Direction.Up: throw new InvalidOperationException( "Underlying sorted set of range bounds is corrupt - the bound below or equal to " + nameof(x) + "=" + x + " " + "(at value " + below.Bound + ") represents the end of a range, so and end to this range is expected next, " + "but the bound above or equal to " + nameof(x) + "=" + x + " (at value " + above.Bound + ") represents " + "the start of another range." ); case Direction.Down: range = BigIntRange.CreateStartEnd(below.Bound, above.Bound); rangeIsIncluded = true; return(true); default: break; } break; default: break; } } range = default(BigIntRange); rangeIsIncluded = default(bool); return(false); }
/// <summary>Gets a range from (-End) to (-Start)</summary> public BigIntRange GetNegative() => BigIntRange.CreateStartEnd(start: -this.End, end: -this.Start);
//Not a clear name & difficult to define (it's not a union - what is it) // public static BigIntRange Combine(BigIntRange a, BigIntRange b) => BigIntRange.CreateStartEnd( // start: BigInteger.Min(a.Start, b.Start), // end: BigInteger.Max(a.End , b.End ) // ); //Instead do: public BigIntRange ExpandToInclude(BigIntRange other) => BigIntRange.CreateStartEnd( start: BigInteger.Min(this.Start, other.Start), end: BigInteger.Max(this.End, other.End) );
public BigIntRange ExpandToInclude(BigInteger x) => BigIntRange.CreateStartEnd( start: BigInteger.Min(this.Start, x), end: BigInteger.Max(this.End, x) );
public BigIntRange Expand(BigInteger downBy, BigInteger upBy) => BigIntRange.CreateStartEnd(this.Start - downBy, this.End + upBy);