Documentation
¶
Overview ¶
SpanTools Overview ¶
Implements the universal span intersection algorithm. The algorithm represents a unified way to find intersections and overlaps of "one dimensional spans" of any data type. The package is built around the SpanUtil[E any] struct, and the manipulation of the SpanBoundry[E any] interface.
For examples and extended documentation please see the Project page.
How it works ¶
The "Universal Span Intersection Algorithm" is implemented by breaking operations down into their constituent parts.
Finding intersections of one dimensional spans of generic data types requires the following:
- A way contian the begin and end values, representing our span
- Method to compare values.
- Method to create a next value
Instance Construction ¶
The st.NewSpanUtil[E any](Cmp,Next) function requires 2 methods be passed to the constructor in order to implement the algorithm:
- A "Compare" function see: cmp.Compare for more details.
- A "Next" function, takes a given value and returns next value. The next value must be greater than the input value
Example of creating a new instance of SpanUtil[int]:
var u = st.NewSpanUtil(
//use the standard Compare function
cmp.Compare,
//Define our Next function
func(e int) int { return e + 1 },
)
The algorithm is primarily implemented by 2 methods of the SpanUtil[E any] struct:
- FirstSpan, finds the initial data span intersection.
- NextSpan, finds all subsequent data span intersections.
Basic example ¶
Our Example Set data:
var list = &[]st.SpanBoundry[int]{
u.Ns(1, 2),
u.Ns(2, 7),
u.Ns(5, 11),
}
The act of "Finding the first span" is performed in 3 stages:
- The first stage requires finding the smallest begin and end value of all of our spans.
- If a begin value in our sets is both greater than the smallest begin value and less than or equal to smallest end value, then the initial end value must set to the smallest begin value, else we use the smallest end value.
- We will use the begin value from stage 1 and the end value from stage 2 as our "first span"
Example code snipped:
var span, ok = u.FirstSpan(list)
The act of "Finding the next span" is performed in 4 stages:
- The first stage we create a "new next value" that is greater than our last span end value. This "new next value" will be used as the "begin" value for step 3.
- We look for the next smallest begin or end value in our sets that are, greater than or equal to our "new next value". The value from this process will be used as our next "end" value for step 3.
- For each set that overlaps with the span defined by the "begin" from step 1 and the "end" from step 2: We need to look for the largest begin value and the smallest end value.
- We will used the largest begin value and smallest end value as our "next span"
We can repeat the "Finding the next set" until step 1 yields a value beyond any end value in our sets:
// Denote which set we are on
var count = 0
for ok {
// Find the indexes of our input set
var sources = u.GetOverlapIndexes(span, list)
fmt.Printf("Overlap Set: %d, Span: %v, Columns: %v\n", count, span, sources)
count++
span, ok = u.NextSpan(span, list)
}
Beyond the basics ¶
Finding overlaps between lists of lists takes a bit more work, but is greatly simplified by this package. In this example we will create an instance of st.ColumnSets[int]. The ColumnSets instance is created by a factory interface of SpanUtil.
Build our column accumulator:
ac := u.NewColumnSets() // Always make sure a defer to close is scoped correctly! defer ac.Close()
In order to compare a list of list of spans we will add the following constraints:
- Each list of list of spans must be presented in a specific order. The order is defined as: begin value in ascending order, end value in descending order.
- Each time a overlapping value is encountered a new Larger span consisting of the smallest begin value and largest end value must be created. As a side effect of this the original spans that caused this overlapping set should be retained to explain where this new larger span came from.
- To find the end of an overlapping set we must continue until we find the next span that does not overlap with our current span or we run out of spans to process.
Example data set:
// We will map our ColumnId to our Set Name
m := make(map[int]string)
var seta = &[]st.SpanBoundry[int]{
u.Ns(1, 2),
u.Ns(3, 7), // will consolidate to 3-11
u.Ns(5, 11), // will consolidate to 3-11
}
m[0] = "SetA"
var setb = &[]st.SpanBoundry[int]{
u.Ns(3, 3),
u.Ns(5, 11),
}
m[1] = "SetB"
var setc = &[]st.SpanBoundry[int]{
u.Ns(1, 7),
u.Ns(8, 11),
}
m[2] = "SetC"
// The internals sort slices and applys the constrains automatically
ac.AddColumnFromSpanSlice(seta)
ac.AddColumnFromSpanSlice(setb)
ac.AddColumnFromSpanSlice(setc)
With our constraints applied, we can now consolidate list of list of spans, however we will need to add some enhancements to the process.
The enhancements are as follows:
- Now our our "Finding the first span" list of spans are pulled the first member of each constrained and consolidated list list of spans. We will refer the "first span" as the "current span".
- For each constrained list of spans: iterate through each constrained span and save all the constrained spans that overlap with our current span. When we find a span with an end or begin value beyond the current span end value we or we have exhausted this list of spans, this list iteration is complete.
- Now we apply "Finding the next span" to our current list of constrained spans. We will refer to the "next span" as the "current span"
- Repeat steps 2 and 3 until we have exhausted all lists of constrained spans.
Example Iterator loop:
header := "+-----+--------------------+------------------------------------+\n"
fmt.Print(header)
fmt.Print("| Seq | Begin and End | Set Name:(Row,Row) |\n")
for pos, res := range ac.Iter() {
// check if there were errors
if ac.Err != nil {
fmt.Printf("Error: on Column: %s, error was: %v\n",m[ac.ErrCol],ac.Err)
return
}
cols := res.GetColumns()
names := []string{}
for _, column := range *cols {
str :=fmt.Sprintf("%s:(%d-%d)",m[column.ColumnId],column.GetSrcId(),column.GetEndId())
names = append(names, str)
}
fmt.Print(header)
fmt.Printf("| %- 3d | Begin:% 3d, End:% 3d | %- 34s |\n",
pos,
res.GetBegin(),
res.GetEnd(),
strings.Join(names, ", "),
)
}
fmt.Print(header)
Integrating go routines and streaming data sets ¶
The internals of the st package, can be used to create context instances to mange communication between go routines for us. If the spans are recived out of order or fail to pass error checking constraints, then the main iterator loop will be halted. In this example we will simulate streaming the same data set via go routines.
First we create an "Add" function to create our go routien and push data into our column channel based iterators:
var Add = func(list *[]st.SpanBoundry[int]) int {
s := u.NewSpanOverlapAccumulator().NewOlssChanStater()
// Please note, we must start the go routine before we add
// the accumulator to the ColumnSets instance. If not we
// will run into a race condition.
go func() {
// Scope our cleanup code to the go routine
defer s.Final()
end := len(*list) - 1
id := 0
span := (*list)[id]
for s.CanAccumulate(span) {
id++
if id > end {
return
}
span = (*list)[id]
}
}()
// Adding the st.OlssChanStater instance to the ColumnSets
return ac.AddColumnFromNewOlssChanStater(s)
}
We can now add our data sets:
Add(&[]st.SpanBoundry[int]{
u.Ns(1, 2),
u.Ns(3, 7), // will consolidate to 3-11
u.Ns(5, 11), // will consolidate to 3-11
})
Add(&[]st.SpanBoundry[int]{
u.Ns(3, 3),
u.Ns(5, 11),
})
Add(&[]st.SpanBoundry[int]{
u.Ns(1, 7),
u.Ns(8, 11),
})
The for loop and map remain unchanged from our previous example. The only differnce is the internals have no way to sort the data before it is consolidated.
Index ¶
- type ColumnOverlap
- type ColumnOverlapAccumulator
- func (s *ColumnOverlapAccumulator[E]) Close()
- func (s *ColumnOverlapAccumulator[E]) GetBegin() E
- func (s *ColumnOverlapAccumulator[E]) GetEnd() E
- func (s *ColumnOverlapAccumulator[E]) GetEndId() int
- func (s *ColumnOverlapAccumulator[E]) GetFirstSpan() (int, SpanBoundry[E])
- func (s *ColumnOverlapAccumulator[E]) GetLastSpan() (int, SpanBoundry[E])
- func (s *ColumnOverlapAccumulator[E]) GetOverlaps() *[]*OverlappingSpanSets[E]
- func (s *ColumnOverlapAccumulator[E]) GetSources() *[]*OvelapSources[E]
- func (s *ColumnOverlapAccumulator[E]) GetSrcId() int
- func (s *ColumnOverlapAccumulator[E]) HasNext() bool
- func (s *ColumnOverlapAccumulator[E]) InOverlap() bool
- func (s *ColumnOverlapAccumulator[E]) SetNext(overlap SpanBoundry[E])
- type ColumnResults
- type ColumnSets
- func (s *ColumnSets[E]) AddColumn(c *ColumnOverlapAccumulator[E]) int
- func (s *ColumnSets[E]) AddColumnFromNewOlssChanStater(sa *OlssChanStater[E]) int
- func (s *ColumnSets[E]) AddColumnFromOverlappingSpanSets(list *[]*OverlappingSpanSets[E]) int
- func (s *ColumnSets[E]) AddColumnFromSpanSlice(list *[]SpanBoundry[E]) (int, *SpanOverlapAccumulator[E])
- func (s *ColumnSets[E]) AddOnClose(todo func())
- func (s *ColumnSets[E]) Close()
- func (s *ColumnSets[E]) GetBegin() E
- func (s *ColumnSets[E]) GetColumns() *[]*CurrentColumn[E]
- func (s *ColumnSets[E]) GetEnd() E
- func (s *ColumnSets[E]) GetSpan() SpanBoundry[E]
- func (s *ColumnSets[E]) Iter() iter.Seq2[int, ColumnResults[E]]
- func (s *ColumnSets[E]) OverlapCount() int
- type CurrentColumn
- type OlssChanStater
- type OvelapSources
- type OverlappingSpanSets
- func (s *OverlappingSpanSets[E]) GetBegin() E
- func (s *OverlappingSpanSets[E]) GetContains() *[]SpanBoundry[E]
- func (s *OverlappingSpanSets[E]) GetEnd() E
- func (s *OverlappingSpanSets[E]) GetEndId() int
- func (s *OverlappingSpanSets[E]) GetFirstSpan() (int, SpanBoundry[E])
- func (s *OverlappingSpanSets[E]) GetLastSpan() (int, SpanBoundry[E])
- func (s *OverlappingSpanSets[E]) GetOverlaps() *[]*OverlappingSpanSets[E]
- func (s *OverlappingSpanSets[E]) GetSources() *[]*OvelapSources[E]
- func (s *OverlappingSpanSets[E]) GetSrcId() int
- func (s *OverlappingSpanSets[E]) IsUnique() bool
- type Span
- type SpanBoundry
- type SpanIterSeq2Stater
- type SpanOverlapAccumulator
- func (s *SpanOverlapAccumulator[E]) Accumulate(span SpanBoundry[E]) (*OverlappingSpanSets[E], error)
- func (s *SpanOverlapAccumulator[E]) NewCoaFromOlssChan(c <-chan *OverlappingSpanSets[E]) *ColumnOverlapAccumulator[E]
- func (s *SpanOverlapAccumulator[E]) NewCoaFromSbSlice(list *[]SpanBoundry[E]) *ColumnOverlapAccumulator[E]
- func (s *SpanOverlapAccumulator[E]) NewOlssChanStater() *OlssChanStater[E]
- func (s *SpanOverlapAccumulator[E]) NewOlssSeq2FromOlssSlice(list *[]*OverlappingSpanSets[E]) iter.Seq2[int, *OverlappingSpanSets[E]]
- func (s *SpanOverlapAccumulator[E]) NewOlssSeq2FromSbChan(c <-chan SpanBoundry[E]) iter.Seq2[int, *OverlappingSpanSets[E]]
- func (s *SpanOverlapAccumulator[E]) NewOlssSeq2FromSbSlice(list *[]SpanBoundry[E]) iter.Seq2[int, *OverlappingSpanSets[E]]
- func (s *SpanOverlapAccumulator[E]) NewSpanIterSeq2Stater() *SpanIterSeq2Stater[E]
- type SpanUtil
- func (s *SpanUtil[E]) Check(next, current SpanBoundry[E]) error
- func (s *SpanUtil[E]) Compare(a, b SpanBoundry[E]) int
- func (s *SpanUtil[E]) ContainedBy(a, b SpanBoundry[E]) (int, int)
- func (s *SpanUtil[E]) Contains(a SpanBoundry[E], b E) bool
- func (s *SpanUtil[E]) CreateOverlapSpan(list *[]SpanBoundry[E]) (SpanBoundry[E], bool)
- func (s *SpanUtil[E]) FirstSpan(list *[]SpanBoundry[E]) (SpanBoundry[E], bool)
- func (s *SpanUtil[E]) GetOverlapIndexes(overlap SpanBoundry[E], list *[]SpanBoundry[E]) *[]int
- func (s *SpanUtil[E]) GetP(x E) *E
- func (s *SpanUtil[E]) NewCoaFromOlssSeq2(driver iter.Seq2[int, *OverlappingSpanSets[E]]) *ColumnOverlapAccumulator[E]
- func (s *SpanUtil[E]) NewColumnOverlapAccumulator(next func() (int, *OverlappingSpanSets[E], bool), stop func()) *ColumnOverlapAccumulator[E]
- func (s *SpanUtil[E]) NewColumnSets() *ColumnSets[E]
- func (s *SpanUtil[E]) NewOlssSeq2FromOlssChan(c <-chan *OverlappingSpanSets[E]) iter.Seq2[int, *OverlappingSpanSets[E]]
- func (s *SpanUtil[E]) NewSpan(a, b E) (SpanBoundry[E], error)
- func (s *SpanUtil[E]) NewSpanOverlapAccumulator() *SpanOverlapAccumulator[E]
- func (s *SpanUtil[E]) NextSpan(start SpanBoundry[E], list *[]SpanBoundry[E]) (SpanBoundry[E], bool)
- func (s *SpanUtil[E]) Ns(a, b E) SpanBoundry[E]
- func (s *SpanUtil[E]) Overlap(a, b SpanBoundry[E]) bool
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ColumnOverlap ¶
type ColumnOverlap[E any] interface { SpanBoundry[E] // Returns the first index point from the soruce data set GetSrcId() int // Returns the last index point from the soruce data set GetEndId() int GetOverlaps() *[]*OverlappingSpanSets[E] // Returns both the index point of the first data soruce, and the original SpanBoundry. GetFirstSpan() (int, SpanBoundry[E]) // Returns both the index point of the last data soruce, and the original SpanBoundry. GetLastSpan() (int, SpanBoundry[E]) // Returns all intersecting SpanBoundry instances and their indexes GetSources() *[]*OvelapSources[E] }
Represents an intersection of data. Intersections can represent data that overlaps from a given source, or intersections between multiple sources.
Representation as a SpanBoundry is as follows:
- GetBegin() returns the smallest most intersection boundry.
- GetEnd() returns the largest most intersection boundry.
type ColumnOverlapAccumulator ¶
type ColumnOverlapAccumulator[E any] struct { // Representation of the data that intersected with an SpanBoundry passed to GetNext. // A value of nil means no data overlaps. Overlaps *[]*OverlappingSpanSets[E] // Where Overlaps begins relative to our OverlappingSpanSets[E,T] iteration. // A value of -1 means there was no overlap with the last SpanBoundry[E,T] compared. SrcStart int // Where Overlaps ends relative to our OverlappingSpanSets[E,T] iteration. // A value of -1 means there was no overlap with the last SpanBoundry[E,T] compared. SrcEnd int // Span utility instance Util *SpanUtil[E] // The iter.Pull2 "next" method generated from the iter.Seq2 instance. ItrGetNext func() (int, *OverlappingSpanSets[E], bool) // The iter.Pull2 "stop" method generated from the iter.Seq2 instance. ItrStop func() // The next set to operate on, when nil. Next *OverlappingSpanSets[E] // Denotes if the object is closed Closed bool Err error }
This structure represents a "data source" and how it intersects with an external SpanBoundry. Contains the current iterator control functions and represents the column position in the iterator process.
func (*ColumnOverlapAccumulator[E]) Close ¶
func (s *ColumnOverlapAccumulator[E]) Close()
This method is used to call the stop method of the iter.Pull2 iterator method. If you are managing an instance of ColumnOverlapAccumulator[E,T] on your own, make sure to setup a defer SpanOverlapColumnAccumulator[E,T].Close() to ensure your code does not leak memory or run into undefined behaviors.
func (*ColumnOverlapAccumulator[E]) GetBegin ¶
func (s *ColumnOverlapAccumulator[E]) GetBegin() E
func (*ColumnOverlapAccumulator[E]) GetEnd ¶
func (s *ColumnOverlapAccumulator[E]) GetEnd() E
func (*ColumnOverlapAccumulator[E]) GetEndId ¶
func (s *ColumnOverlapAccumulator[E]) GetEndId() int
Returns the last positional id from the orignal data set for this column.
func (*ColumnOverlapAccumulator[E]) GetFirstSpan ¶
func (s *ColumnOverlapAccumulator[E]) GetFirstSpan() (int, SpanBoundry[E])
Returns the first span that intersecs with this set.
func (*ColumnOverlapAccumulator[E]) GetLastSpan ¶
func (s *ColumnOverlapAccumulator[E]) GetLastSpan() (int, SpanBoundry[E])
Returns the last span that intersecs with this set.
func (*ColumnOverlapAccumulator[E]) GetOverlaps ¶
func (s *ColumnOverlapAccumulator[E]) GetOverlaps() *[]*OverlappingSpanSets[E]
Returns the overlap sets.
func (*ColumnOverlapAccumulator[E]) GetSources ¶
func (s *ColumnOverlapAccumulator[E]) GetSources() *[]*OvelapSources[E]
Returns all spans with the sequence id from the orginal data source.
func (*ColumnOverlapAccumulator[E]) GetSrcId ¶
func (s *ColumnOverlapAccumulator[E]) GetSrcId() int
Returns the first positional id from the orignal data set for this column.
func (*ColumnOverlapAccumulator[E]) HasNext ¶
func (s *ColumnOverlapAccumulator[E]) HasNext() bool
Returns true if there are more elements in this column.
func (*ColumnOverlapAccumulator[E]) InOverlap ¶
func (s *ColumnOverlapAccumulator[E]) InOverlap() bool
When true this instance contains elements in "Overlaps" that intersect with the last value passed to SetNext.
func (*ColumnOverlapAccumulator[E]) SetNext ¶
func (s *ColumnOverlapAccumulator[E]) SetNext(overlap SpanBoundry[E])
This method updates the state of the instance instance in relation to overlap. The overlap is considered an external point for comparison, and the internal data sets are updated to reflect the current intersection points if any.
type ColumnResults ¶
type ColumnResults[E any] interface { // Returns the current columns GetColumns() *[]*CurrentColumn[E] // Denotes how many columns overlap with the current span. OverlapCount() int // Returns the SpanBoundry representing the current position in our data set. GetSpan() SpanBoundry[E] SpanBoundry[E] }
type ColumnSets ¶
type ColumnSets[E any] struct { Util *SpanUtil[E] // The last error, nil if there were no errors Err error // ColumnId the our last error came from ErrCol int OnClose *[]func() // contains filtered or unexported fields }
This struct acts as the majordomo of the constrained span intersection iteration process.
For every instance created make sure to scope the proper defer call:
defer i.Close()
func (*ColumnSets[E]) AddColumn ¶
func (s *ColumnSets[E]) AddColumn(c *ColumnOverlapAccumulator[E]) int
Appends an a column accumulator to the current column set. Returns the id of the column, if the instance is closed returns -1.
func (*ColumnSets[E]) AddColumnFromNewOlssChanStater ¶
func (s *ColumnSets[E]) AddColumnFromNewOlssChanStater(sa *OlssChanStater[E]) int
Adds a context aware channel based ColumnOverlapAccumulator.
Warning ¶
If you don't start the go routine that appends to the channel before calling this method, it will cause a race condition that will prevent the ColumnSets instancce from working correctly.
func (*ColumnSets[E]) AddColumnFromOverlappingSpanSets ¶
func (s *ColumnSets[E]) AddColumnFromOverlappingSpanSets(list *[]*OverlappingSpanSets[E]) int
Adds list as a column to the internals.
func (*ColumnSets[E]) AddColumnFromSpanSlice ¶
func (s *ColumnSets[E]) AddColumnFromSpanSlice(list *[]SpanBoundry[E]) (int, *SpanOverlapAccumulator[E])
This is a helper method that constructs an SpanOverlapAccumulator and then produces an iterator from the SpanOverlapAccumulator based on list.
func (*ColumnSets[E]) AddOnClose ¶
func (s *ColumnSets[E]) AddOnClose(todo func())
Adds a function to call when the close operation is called or the iterator optations have been completed.
func (*ColumnSets[E]) Close ¶
func (s *ColumnSets[E]) Close()
Shuts down and cleans up the instance, and any go routines that were registered.
func (*ColumnSets[E]) GetBegin ¶
func (s *ColumnSets[E]) GetBegin() E
This is a wrapper for s.GetSpan.GetBegin().
func (*ColumnSets[E]) GetColumns ¶
func (s *ColumnSets[E]) GetColumns() *[]*CurrentColumn[E]
func (*ColumnSets[E]) GetEnd ¶
func (s *ColumnSets[E]) GetEnd() E
This is a wrapper for s.GetSpan.GetEnd().
func (*ColumnSets[E]) GetSpan ¶
func (s *ColumnSets[E]) GetSpan() SpanBoundry[E]
Returns the SpanBoundry instance that represents the intersection of our current column state.
func (*ColumnSets[E]) Iter ¶
func (s *ColumnSets[E]) Iter() iter.Seq2[int, ColumnResults[E]]
Creates an iteraotr to walk all added columns and find the overlaps.
func (*ColumnSets[E]) OverlapCount ¶
func (s *ColumnSets[E]) OverlapCount() int
Denotes how many columns overlap with this span, if the set of current colums is empty then the returned value will be -1.
type CurrentColumn ¶
type CurrentColumn[E any] struct { ColumnOverlap[E] ColumnId int }
Represents a source data set of the culumn consolidation process.
type OlssChanStater ¶
type OlssChanStater[E any] struct { Chan chan *OverlappingSpanSets[E] Closed bool Stater SpanIterSeq2Stater[E] Ctx context.Context Cancel func() IsShutDown bool }
Context aware goroutine channel accumulator instance. This struct is meant to be instantiated factory interfaces. If you are managing an instance ouside of the normal factory methods, you will need to add the following defer statements in the properly scopes:
- in the main thread add a defer s.Shutdown()
- in the go routine add a defer s.Final()
func (*OlssChanStater[E]) CanAccumulate ¶
func (s *OlssChanStater[E]) CanAccumulate(span SpanBoundry[E]) bool
Acts as a control method in for loops, handles pushing data to the channel from within a goroutine.
Example:
defer s.Final()
for s.CanAccumulate(span) {
// get your next SpanBoundry
}
func (*OlssChanStater[E]) Final ¶
func (s *OlssChanStater[E]) Final() bool
Call this method with a derfer statement in your goroutine when you are done processing SpanBoundry instances.
Example:
defer s.Final()
func (*OlssChanStater[E]) Push ¶
func (s *OlssChanStater[E]) Push(next *OverlappingSpanSets[E]) bool
Attempts to push the next value to the channel, if this instance is Closed or if the context has been cancled, then the method returns false.
func (*OlssChanStater[E]) Shutdown ¶
func (s *OlssChanStater[E]) Shutdown()
Shuts down the context from the Column accumulator thread. Do not call this outside of the thread running the ColumnOverlapAccumulator instance or you will get undefined behavior.
type OvelapSources ¶
type OvelapSources[E any] struct { SpanBoundry[E] SrcId int }
Represents the SpanBoundry[E] that caused this intersection and its index point.
type OverlappingSpanSets ¶
type OverlappingSpanSets[E any] struct { // The Span that contains all Spans in this instance. Span SpanBoundry[E] // When nil, Span is the only value representing this Span. // When not nil, contains all the Spans accumulated to create this instance. Contains *[]SpanBoundry[E] // Starting position in the original data set SrcBegin int // Ending position in the original data set SrcEnd int Err error }
A representation of accumulated Span from a given source. The *Span[E,T] represents the span that contains all SpanBoundry[E,T] in *Contains. When *Contains is nil, then this struct only has 1 SpanBoundry[E,T]. When *Contains is not nil, the original *SpanBoundry[E,T] values are contained within.
func (*OverlappingSpanSets[E]) GetBegin ¶
func (s *OverlappingSpanSets[E]) GetBegin() E
Implementation required for this object instance to act as a SpanBoundry[E] instance.
func (*OverlappingSpanSets[E]) GetContains ¶
func (s *OverlappingSpanSets[E]) GetContains() *[]SpanBoundry[E]
Returns all of the span values that drive this current intersection.
func (*OverlappingSpanSets[E]) GetEnd ¶
func (s *OverlappingSpanSets[E]) GetEnd() E
Implementation required for this object instance to act as a SpanBoundry[E] instance.
func (*OverlappingSpanSets[E]) GetEndId ¶
func (s *OverlappingSpanSets[E]) GetEndId() int
Returns the indexed sequence point of the last original span representing this intersection.
func (*OverlappingSpanSets[E]) GetFirstSpan ¶
func (s *OverlappingSpanSets[E]) GetFirstSpan() (int, SpanBoundry[E])
Returns the first span that created this interseciton.
func (*OverlappingSpanSets[E]) GetLastSpan ¶
func (s *OverlappingSpanSets[E]) GetLastSpan() (int, SpanBoundry[E])
Returns the last span that created this interseciton.
func (*OverlappingSpanSets[E]) GetOverlaps ¶
func (s *OverlappingSpanSets[E]) GetOverlaps() *[]*OverlappingSpanSets[E]
Returns the slice of OverlappingSpanSets that drive this current intersection.
func (*OverlappingSpanSets[E]) GetSources ¶
func (s *OverlappingSpanSets[E]) GetSources() *[]*OvelapSources[E]
Returns all of the spans and thier indexes that caused this current intersection.
func (*OverlappingSpanSets[E]) GetSrcId ¶
func (s *OverlappingSpanSets[E]) GetSrcId() int
Returns the indexed sequence point of the first original span representing this intersection.
func (*OverlappingSpanSets[E]) IsUnique ¶
func (s *OverlappingSpanSets[E]) IsUnique() bool
Returns true of there are no overlaps with this span.
type Span ¶
type Span[E any] struct { // Start of the Span. Begin E // End of the Span. End E }
Representation of a Span/Range of values in a generic context. The assumption is that Begin is less than or equal to the End value.
type SpanBoundry ¶
type SpanBoundry[E any] interface { // Returns the Begin value. GetBegin() E // Returns the End value. GetEnd() E }
This interface acts as the core representation of spans for the "st" pacakge. Spans are represent by 2 values a "Begin" value and an "End" value. The Begin value should be returned by GetBegin and should be greater than or equal to the End value returned by GetEnd.
type SpanIterSeq2Stater ¶
type SpanIterSeq2Stater[E any] struct { Current *OverlappingSpanSets[E] Next *OverlappingSpanSets[E] Sa *SpanOverlapAccumulator[E] Id int }
Represents the stater for going to the: next span.
func (*SpanIterSeq2Stater[E]) GetNext ¶
func (s *SpanIterSeq2Stater[E]) GetNext() (int, *OverlappingSpanSets[E])
Returns the current index and intersection if any.
func (*SpanIterSeq2Stater[E]) HasNext ¶
func (s *SpanIterSeq2Stater[E]) HasNext() bool
Returns true if we have any more intersections.
func (*SpanIterSeq2Stater[E]) SetNext ¶
func (s *SpanIterSeq2Stater[E]) SetNext(span SpanBoundry[E]) bool
Returns true if this SpanBoundry[E] created a new data intersrection. If the value is true you must make a call to s.GetNext() instance method before calling this method again!
type SpanOverlapAccumulator ¶
type SpanOverlapAccumulator[E any] struct { Rss *OverlappingSpanSets[E] *SpanUtil[E] // When true slices passed in will be sorted. Sort bool // When not nil, this object has encounter an error Err error // Sequence counter Pos int // Turns validation on/off, default false or off Validate bool // Turns consolidation of adjacent spans on or off, default false or off Consolidate bool }
This is a stater structure, used to drive the creation of new OverlappingSpanSets. Each source of spans should have their own instance of SpanOverlapAccumulator.
func (*SpanOverlapAccumulator[E]) Accumulate ¶
func (s *SpanOverlapAccumulator[E]) Accumulate(span SpanBoundry[E]) (*OverlappingSpanSets[E], error)
The Accumulate method.
For a given span provided: When the span overlaps with the current internal span, the OverlappingSpanSets is expanded and the span is append to the Contains slice. When the span is outside of the current internal span, then a new OverlappingSpanSets is created with this span as its current span. The error value is nil, by default, when an error has happend it is no longer nil.
func (*SpanOverlapAccumulator[E]) NewCoaFromOlssChan ¶
func (s *SpanOverlapAccumulator[E]) NewCoaFromOlssChan(c <-chan *OverlappingSpanSets[E]) *ColumnOverlapAccumulator[E]
Factory for convering a channel of OverlappingSpanSets[E] to a ColumnOverlapAccumulator[E].
func (*SpanOverlapAccumulator[E]) NewCoaFromSbSlice ¶
func (s *SpanOverlapAccumulator[E]) NewCoaFromSbSlice(list *[]SpanBoundry[E]) *ColumnOverlapAccumulator[E]
This is a convenience method for initializing the iter.Seq2 stater internals based on a slice of SpanBoundry.
func (*SpanOverlapAccumulator[E]) NewOlssChanStater ¶
func (s *SpanOverlapAccumulator[E]) NewOlssChanStater() *OlssChanStater[E]
Creates a new context aware context.Context aware SpanBoundry[E] accumulation instance.
func (*SpanOverlapAccumulator[E]) NewOlssSeq2FromOlssSlice ¶
func (s *SpanOverlapAccumulator[E]) NewOlssSeq2FromOlssSlice(list *[]*OverlappingSpanSets[E]) iter.Seq2[int, *OverlappingSpanSets[E]]
Helper function to create an overlap iterator from a slice of list.
func (*SpanOverlapAccumulator[E]) NewOlssSeq2FromSbChan ¶
func (s *SpanOverlapAccumulator[E]) NewOlssSeq2FromSbChan(c <-chan SpanBoundry[E]) iter.Seq2[int, *OverlappingSpanSets[E]]
Generates a iter.Seq2 iterator, for a channel of SpanBoundry instances.
func (*SpanOverlapAccumulator[E]) NewOlssSeq2FromSbSlice ¶
func (s *SpanOverlapAccumulator[E]) NewOlssSeq2FromSbSlice(list *[]SpanBoundry[E]) iter.Seq2[int, *OverlappingSpanSets[E]]
Factory interface for converting slices of SpanBoundaries instances into iterator sequences of OverlappingSpanSets.
func (*SpanOverlapAccumulator[E]) NewSpanIterSeq2Stater ¶
func (s *SpanOverlapAccumulator[E]) NewSpanIterSeq2Stater() *SpanIterSeq2Stater[E]
Factory interface for stater creator.
type SpanUtil ¶
type SpanUtil[E any] struct { // Compare function. This function should be atomic and be able t compare the E type by return -1,0,1. Cmp func(a, b E) int // Turns validation on for new child objects created. Validate bool // Next value function, should return the next E. // The new E value must always be greater than the argument passed in Next func(e E) E // Flag denoting if overlaps that are adjacent should be consolidated. // Example of when true: 1,2 and 2,3 consolidate to 1,3, when false they do not consolidate. // Default is false. Consolidate bool // Denotes if objects created should sort by default. Sort bool SpanFactory func(begin, end E) SpanBoundry[E] }
Core of the span utilities: Provides methods for processing ranges.
func NewSpanUtil ¶
Creates an instance of *SpanUtil[E], the value of cmp is expected to be able to compare the Span.Begin and Span.End values. See: cmp.Compare for more info.
The default SpanFormat is set to: "Span: [%s -> %s], Tag: %s"
func (*SpanUtil[E]) Check ¶
func (s *SpanUtil[E]) Check(next, current SpanBoundry[E]) error
This method is used to verify the sanity of the next and current value. The comparison operation is performed in 2 stages: 1. next.GetBegin() must be less than or equal to next.GetEnd(). 2. When the current value is not nil, then next must come after current. Returns nil when checks pass, the error is not nil when checks fail.
func (*SpanUtil[E]) Compare ¶
func (s *SpanUtil[E]) Compare(a, b SpanBoundry[E]) int
This method is used to sort slice of spans in the accumulation order. For more details see: slices.SortFunc.
func (*SpanUtil[E]) ContainedBy ¶
func (s *SpanUtil[E]) ContainedBy(a, b SpanBoundry[E]) (int, int)
This method is used to determine the outer bounds of ranges a and b. The first int represents comparing a.Begin to b.Begin and the second int represents comparing a.End to b.End.
func (*SpanUtil[E]) Contains ¶
func (s *SpanUtil[E]) Contains(a SpanBoundry[E], b E) bool
Returns true if a contains b.
func (*SpanUtil[E]) CreateOverlapSpan ¶
func (s *SpanUtil[E]) CreateOverlapSpan(list *[]SpanBoundry[E]) (SpanBoundry[E], bool)
Generates the "common overlapping span". This method assumes that all SpanBoundry instances in list overlap, and does not check if some SpanBoundry instances do not overlap. If some SpanBoundry instances do not overlap, then this will result in the creation of an invalid SpanBoundry.
How the "common overlapping span" is created is as follows:
- Find the largest begin value in list and uses that as the begin value.
- Find the smallest end value in list and uses that as the end value.
func (*SpanUtil[E]) FirstSpan ¶
func (s *SpanUtil[E]) FirstSpan(list *[]SpanBoundry[E]) (SpanBoundry[E], bool)
Generates the first valid span representing the smallest overlapping set. If list is nil, or contains no spans, then the span is nil and the bool value will be false.
Finding the "initial span" is done by first finding the smallest begin and end values. The resulting span is referred to as the "initial span". If there is a begin value in list, that overlaps with the smallest end value, then the "initial span" begin value will also be set as the end value for the "initial span".
func (*SpanUtil[E]) GetOverlapIndexes ¶
func (s *SpanUtil[E]) GetOverlapIndexes(overlap SpanBoundry[E], list *[]SpanBoundry[E]) *[]int
Given overlap and list, returns the indexs of the SpanBoundry instances that intersect with overlap.
func (*SpanUtil[E]) GetP ¶
func (s *SpanUtil[E]) GetP(x E) *E
Wrapper function to return a pointer to the value passed in.
func (*SpanUtil[E]) NewCoaFromOlssSeq2 ¶
func (s *SpanUtil[E]) NewCoaFromOlssSeq2(driver iter.Seq2[int, *OverlappingSpanSets[E]]) *ColumnOverlapAccumulator[E]
This method takes a iter.Seq2 iterator of OverlappingSpanSets and initializes the ColumnOverlapAccumulator struct.
Warning ¶
This methods creates an iter.Pull2 and exposes the resulting functions in the returned struct pointer. If you are using this method outside of the normal operations, you should a setup a defer call to ColumnOverlapAccumulator[E].Close() method to clean the instance up in order to prevent memory leaks or undefined behavior.
func (*SpanUtil[E]) NewColumnOverlapAccumulator ¶
func (s *SpanUtil[E]) NewColumnOverlapAccumulator(next func() (int, *OverlappingSpanSets[E], bool), stop func()) *ColumnOverlapAccumulator[E]
This method takes the next and stop functions and creates a new fully initialized instance of ColumnOverlapAccumulator[E]. Each data set should have its own accumulator.
func (*SpanUtil[E]) NewColumnSets ¶
func (s *SpanUtil[E]) NewColumnSets() *ColumnSets[E]
func (*SpanUtil[E]) NewOlssSeq2FromOlssChan ¶
func (s *SpanUtil[E]) NewOlssSeq2FromOlssChan(c <-chan *OverlappingSpanSets[E]) iter.Seq2[int, *OverlappingSpanSets[E]]
Creates a channel iterator for channel of OverlappingSpanSets.
func (*SpanUtil[E]) NewSpan ¶
func (s *SpanUtil[E]) NewSpan(a, b E) (SpanBoundry[E], error)
Creates a new span, error is nil unless a is greater than b.
func (*SpanUtil[E]) NewSpanOverlapAccumulator ¶
func (s *SpanUtil[E]) NewSpanOverlapAccumulator() *SpanOverlapAccumulator[E]
Factory interface for the creation of SpanOverlapAccumulator[E]. Each set of data should have its on unique instance of an accumulator.
func (*SpanUtil[E]) NextSpan ¶
func (s *SpanUtil[E]) NextSpan(start SpanBoundry[E], list *[]SpanBoundry[E]) (SpanBoundry[E], bool)
Finds the next common overlapping SpanBoundry[E] span in list after start, If the bool value is false, then there are no more elements in the set.
How the span is generated:
The begin is generated by calling the Next method.
The end value is found via the following process:
- Find the smallest end greater than equal to the value generated by Next
- If a span begin value is greater than the Next value and less than all other end values then it will be used as the new end value for the initial span.
- Once the new begin and end values are found, a call to CreateOverlapSpan is made, with our "initial span" and "list" to create our new span.
func (*SpanUtil[E]) Ns ¶
func (s *SpanUtil[E]) Ns(a, b E) SpanBoundry[E]
Creates a new SpanBoundry[E], but does not do any error checking.
func (*SpanUtil[E]) Overlap ¶
func (s *SpanUtil[E]) Overlap(a, b SpanBoundry[E]) bool
Returns true if a overlaps with b or if be overlaps with a.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
ConsolidateOverlaps
command
|
|
|
ErrorExample
command
|
|
|
ManualConsolidation
command
|
|
|
beyondbasics
command
|
|
|
example01
command
|
|
|
multichan
command
|