/// <summary> /// Create a new partition /// </summary> /// <param name="symCard">The symbol alphabet cardinality</param> internal Partition(int symCard, TaskState task) { this.myTask = task; CharRange.Init(symCard); PartitionElement.Reset(); elements.Add(PartitionElement.AllChars()); }
internal MapRun(int min, int max, int val) { hash = (max - min + 1) * val; range = new CharRange(min, max); if (min == max) { tag = TagType.singleton; } else if (max - min + 1 >= Partition.CutOff) { tag = TagType.longRun; } else { tag = TagType.shortRun; } }
/// <summary> /// Canonicalize the set. This may mutate /// both this.ranges and the invert flag. /// </summary> internal void Canonicalize() { if (this.isCanonical) { return; } if (!invert && this.ranges.Count <= 1) { this.isCanonical = true; return; // Empty, singleton and upper/lower pair RangeLists are trivially canonical } // Process non-empty lists. int listIx = 0; this.ranges.Sort(); List <CharRange> newList = new List <CharRange>(); CharRange currentRange = ranges[listIx++]; while (listIx < ranges.Count) { CharRange nextRange = ranges[listIx++]; if (nextRange.minChr > currentRange.maxChr + 1) // Merge contiguous ranges { newList.Add(currentRange); currentRange = nextRange; } else if (nextRange.minChr <= (currentRange.maxChr + 1) && nextRange.maxChr >= currentRange.maxChr) { currentRange = new CharRange(currentRange.minChr, nextRange.maxChr); } // Else skip ... } newList.Add(currentRange); this.ranges = newList; if (this.invert) { this.invert = false; this.ranges = this.InvertedList(); } isCanonical = true; }
/// <summary> /// Return a new RangeList that is the intersection of /// "this" and rhOp. Neither operand is mutated. /// </summary> /// <param name="rhOp"></param> /// <returns></returns> internal RangeList AND(RangeList rhOp) { if (!isCanonical || !rhOp.isCanonical) { throw new GplexInternalException("RangeList non canonicalized"); } if (this.ranges.Count == 0 || rhOp.ranges.Count == 0) { return(new RangeList(false)); // return empty RangeList } int thisIx; int rhOpIx = 0; int thisNm = this.ranges.Count; int rhOpNm = rhOp.ranges.Count; List <CharRange> newList = new List <CharRange>(); RangeList result = new RangeList(newList, false); CharRange rhOpElem = rhOp.ranges[rhOpIx++]; for (thisIx = 0; thisIx < thisNm; thisIx++) { CharRange thisElem = this.ranges[thisIx]; // Attempt to find an overlapping element. // If necessary fetch new elements from rhOp // until maxChr of the new element is greater // than minChr of the current thisElem. while (rhOpElem.maxChr < thisElem.minChr) { if (rhOpIx < rhOpNm) { rhOpElem = rhOp.ranges[rhOpIx++]; } else { return(result); } } // It is possible that the rhOpElem is entirely beyond thisElem // It is also possible that rhOpElem and several following // elements are all overlapping with thisElem. while (rhOpElem.minChr <= thisElem.maxChr) { // process overlap newList.Add(new CharRange( (thisElem.minChr < rhOpElem.minChr ? rhOpElem.minChr : thisElem.minChr), (thisElem.maxChr < rhOpElem.maxChr ? thisElem.maxChr : rhOpElem.maxChr))); // If rhOpElem extends beyond thisElem.maxChr it is possible that // it will overlap with the next thisElem, so do not advance rhOpIx. if (rhOpElem.maxChr > thisElem.maxChr) { break; } else if (rhOpIx == rhOpNm) { return(result); } else { rhOpElem = rhOp.ranges[rhOpIx++]; } } } return(result); }
internal void Add(CharRange rng) { ranges.Add(rng); // AddToRange isCanonical = !invert && ranges.Count == 1; }