github.com/biogo/store@v0.0.0-20201120204734-aad293a2328f/step/step.go (about)

     1  // Copyright ©2012 The bíogo Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package step implements a step vector type.
     6  //
     7  // A step vector can be used to represent high volume data that would be
     8  // efficiently stored by run-length encoding.
     9  package step
    10  
    11  import (
    12  	"errors"
    13  	"fmt"
    14  
    15  	"github.com/biogo/store/llrb"
    16  )
    17  
    18  var (
    19  	ErrOutOfRange    = errors.New("step: index out of range")
    20  	ErrInvertedRange = errors.New("step: inverted range")
    21  	ErrZeroLength    = errors.New("step: attempt to create zero length vector")
    22  )
    23  
    24  type (
    25  	position struct {
    26  		pos int
    27  		val Equaler
    28  	}
    29  	lower int
    30  	query int
    31  	upper int
    32  )
    33  
    34  func (p *position) Compare(c llrb.Comparable) int {
    35  	return p.pos - c.(*position).pos
    36  }
    37  func (q lower) Compare(c llrb.Comparable) (d int) {
    38  	d = int(q) - c.(*position).pos
    39  	if d == 0 {
    40  		d = -1
    41  	}
    42  	return
    43  }
    44  func (q query) Compare(c llrb.Comparable) (d int) {
    45  	switch c := c.(type) {
    46  	case *position:
    47  		d = int(q) - c.pos
    48  	case query:
    49  		d = int(q) - int(c)
    50  	}
    51  	return
    52  }
    53  func (q upper) Compare(c llrb.Comparable) (d int) {
    54  	d = int(q) - c.(*position).pos
    55  	if d == 0 {
    56  		d = 1
    57  	}
    58  	return
    59  }
    60  
    61  // An Equaler is a type that can return whether it equals another Equaler.
    62  type Equaler interface {
    63  	Equal(Equaler) bool
    64  }
    65  
    66  // An Int is an int type satisfying the Equaler interface.
    67  type Int int
    68  
    69  // Equal returns whether i equals e. Equal assumes the underlying type of e is Int.
    70  func (i Int) Equal(e Equaler) bool {
    71  	return i == e.(Int)
    72  }
    73  
    74  // A Float is a float64 type satisfying the Equaler interface.
    75  type Float float64
    76  
    77  // Equal returns whether f equals e. For the purposes of the step package here, NaN == NaN
    78  // evaluates to true. Equal assumes the underlying type of e is Float.
    79  func (f Float) Equal(e Equaler) bool {
    80  	ef := e.(Float)
    81  	if f != f && ef != ef { // For our purposes NaN == NaN.
    82  		return true
    83  	}
    84  	return f == ef
    85  }
    86  
    87  // A Vector is type that support the storage of array type data in a run-length
    88  // encoding format.
    89  type Vector struct {
    90  	Zero     Equaler // Ground state for the step vector.
    91  	Relaxed  bool    // If true, dynamic vector resize is allowed.
    92  	t        llrb.Tree
    93  	min, max *position
    94  }
    95  
    96  // New returns a new Vector with the extent defined by start and end,
    97  // and the ground state defined by zero. The Vector's extent is mutable
    98  // if the Relaxed field is set to true. If a zero length vector is requested
    99  // an error is returned.
   100  func New(start, end int, zero Equaler) (*Vector, error) {
   101  	if start >= end {
   102  		return nil, ErrZeroLength
   103  	}
   104  	v := &Vector{
   105  		Zero: zero,
   106  		min: &position{
   107  			pos: start,
   108  			val: zero,
   109  		},
   110  		max: &position{
   111  			pos: end,
   112  			val: nil,
   113  		},
   114  	}
   115  	v.t.Insert(v.min)
   116  	v.t.Insert(v.max)
   117  
   118  	return v, nil
   119  }
   120  
   121  // Start returns the index of minimum position of the Vector.
   122  func (v *Vector) Start() int { return v.min.pos }
   123  
   124  // End returns the index of lowest position beyond the end of the Vector.
   125  func (v *Vector) End() int { return v.max.pos }
   126  
   127  // Len returns the length of the represented data array, that is the distance
   128  // between the start and end of the vector.
   129  func (v *Vector) Len() int { return v.End() - v.Start() }
   130  
   131  // Count returns the number of steps represented in the vector.
   132  func (v *Vector) Count() int { return v.t.Len() - 1 }
   133  
   134  // At returns the value of the vector at position i. If i is outside the extent
   135  // of the vector an error is returned.
   136  func (v *Vector) At(i int) (Equaler, error) {
   137  	if i < v.Start() || i >= v.End() {
   138  		return nil, ErrOutOfRange
   139  	}
   140  	st := v.t.Floor(query(i)).(*position)
   141  	return st.val, nil
   142  }
   143  
   144  // StepAt returns the value and range of the step at i, where start <= i < end.
   145  // If i is outside the extent of the vector, an error is returned.
   146  func (v *Vector) StepAt(i int) (start, end int, e Equaler, err error) {
   147  	if i < v.Start() || i >= v.End() {
   148  		return 0, 0, nil, ErrOutOfRange
   149  	}
   150  	lo := v.t.Floor(query(i)).(*position)
   151  	hi := v.t.Ceil(upper(i)).(*position)
   152  	return lo.pos, hi.pos, lo.val, nil
   153  }
   154  
   155  // Set sets the value of position i to e.
   156  func (v *Vector) Set(i int, e Equaler) {
   157  	if i < v.min.pos || v.max.pos <= i {
   158  		if !v.Relaxed {
   159  			panic(ErrOutOfRange)
   160  		}
   161  
   162  		if i < v.min.pos {
   163  			if i == v.min.pos-1 {
   164  				if e.Equal(v.min.val) {
   165  					v.min.pos--
   166  				} else {
   167  					v.min = &position{pos: i, val: e}
   168  					v.t.Insert(v.min)
   169  				}
   170  			} else {
   171  				if v.min.val.Equal(v.Zero) {
   172  					v.min.pos = i + 1
   173  				} else {
   174  					v.min = &position{pos: i + 1, val: v.Zero}
   175  					v.t.Insert(v.min)
   176  				}
   177  				if e.Equal(v.Zero) {
   178  					v.min.pos--
   179  				} else {
   180  					v.min = &position{pos: i, val: e}
   181  					v.t.Insert(v.min)
   182  				}
   183  			}
   184  		} else if i >= v.max.pos {
   185  			if i == v.max.pos {
   186  				v.max.pos++
   187  				prev := v.t.Floor(query(i)).(*position)
   188  				if !e.Equal(prev.val) {
   189  					v.t.Insert(&position{pos: i, val: e})
   190  				}
   191  			} else {
   192  				mpos := v.max.pos
   193  				v.max.pos = i + 1
   194  				prev := v.t.Floor(query(i)).(*position)
   195  				if !prev.val.Equal(v.Zero) {
   196  					v.t.Insert(&position{pos: mpos, val: v.Zero})
   197  				}
   198  				if !e.Equal(v.Zero) {
   199  					v.t.Insert(&position{pos: i, val: e})
   200  				}
   201  			}
   202  		}
   203  		return
   204  	}
   205  
   206  	lo := v.t.Floor(query(i)).(*position)
   207  	if e.Equal(lo.val) {
   208  		return
   209  	}
   210  	hi := v.t.Ceil(upper(i)).(*position)
   211  
   212  	if lo.pos == i {
   213  		if hi.pos == i+1 {
   214  			if hi != v.max && e.Equal(hi.val) {
   215  				v.t.Delete(query(i))
   216  				hi.pos--
   217  				if v.min.pos == i {
   218  					v.min = hi
   219  				}
   220  			} else {
   221  				lo.val = e
   222  			}
   223  			if i > v.min.pos {
   224  				prev := v.t.Floor(query(i - 1)).(*position)
   225  				if e.Equal(prev.val) {
   226  					v.t.Delete(query(i))
   227  				}
   228  			}
   229  		} else {
   230  			lo.pos = i + 1
   231  			prev := v.t.Floor(query(i))
   232  			if prev == nil {
   233  				v.min = &position{pos: i, val: e}
   234  				v.t.Insert(v.min)
   235  			} else if !e.Equal(prev.(*position).val) {
   236  				v.t.Insert(&position{pos: i, val: e})
   237  			}
   238  		}
   239  	} else {
   240  		if hi.pos == i+1 {
   241  			if hi != v.max && e.Equal(hi.val) {
   242  				hi.pos--
   243  			} else {
   244  				v.t.Insert(&position{pos: i, val: e})
   245  			}
   246  		} else {
   247  			v.t.Insert(&position{pos: i, val: e})
   248  			v.t.Insert(&position{pos: i + 1, val: lo.val})
   249  		}
   250  	}
   251  }
   252  
   253  // SetRange sets the value of positions [start, end) to e.
   254  func (v *Vector) SetRange(start, end int, e Equaler) {
   255  	switch l := end - start; {
   256  	case l == 0:
   257  		if !v.Relaxed && (start < v.min.pos || start >= v.max.pos) {
   258  			panic(ErrOutOfRange)
   259  		}
   260  		return
   261  	case l == 1:
   262  		v.Set(start, e)
   263  		return
   264  	case l < 0:
   265  		panic(ErrInvertedRange)
   266  	}
   267  
   268  	if !v.Relaxed && (start < v.min.pos || end > v.max.pos || start == v.max.pos) {
   269  		panic(ErrOutOfRange)
   270  	}
   271  
   272  	// Do fast path complete vector replacement if possible.
   273  	if start <= v.min.pos && v.max.pos <= end {
   274  		v.t = llrb.Tree{}
   275  		*v.min = position{pos: start, val: e}
   276  		v.t.Insert(v.min)
   277  		v.max.pos = end
   278  		v.t.Insert(v.max)
   279  		return
   280  	}
   281  
   282  	// Handle cases where the given range is entirely outside the vector.
   283  	switch {
   284  	case start >= v.max.pos:
   285  		oldEnd := v.max.pos
   286  		v.max.pos = end
   287  		if start != oldEnd {
   288  			prev := v.t.Floor(query(oldEnd)).(*position)
   289  			if !prev.val.Equal(v.Zero) {
   290  				v.t.Insert(&position{pos: oldEnd, val: v.Zero})
   291  			}
   292  		}
   293  		last := v.t.Floor(query(start)).(*position)
   294  		if !e.Equal(last.val) {
   295  			v.t.Insert(&position{pos: start, val: e})
   296  		}
   297  		return
   298  	case end < v.min.pos:
   299  		if v.min.val.Equal(v.Zero) {
   300  			v.min.pos = end
   301  		} else {
   302  			v.min = &position{pos: end, val: v.Zero}
   303  			v.t.Insert(v.min)
   304  		}
   305  		fallthrough
   306  	case end == v.min.pos:
   307  		if e.Equal(v.min.val) {
   308  			v.min.pos = start
   309  		} else {
   310  			v.min = &position{pos: start, val: e}
   311  			v.t.Insert(v.min)
   312  		}
   313  		return
   314  	}
   315  
   316  	// Handle cases where the given range
   317  	last := v.t.Floor(query(end)).(*position)
   318  	deleteRangeInclusive(&v.t, start, end)
   319  	switch {
   320  	// is entirely within the existing vector;
   321  	case v.min.pos < start && end <= v.max.pos:
   322  		prev := v.t.Floor(query(start)).(*position)
   323  		if !e.Equal(prev.val) {
   324  			v.t.Insert(&position{pos: start, val: e})
   325  		}
   326  		if last.val == nil {
   327  			v.t.Insert(v.max)
   328  		} else if !e.Equal(last.val) {
   329  			v.t.Insert(&position{pos: end, val: last.val})
   330  		}
   331  
   332  	// hangs over the left end and the right end is in the vector; or
   333  	case start <= v.min.pos:
   334  		lastVal := last.val
   335  		*v.min = position{pos: start, val: e}
   336  		v.t.Insert(v.min)
   337  
   338  		if !e.Equal(lastVal) {
   339  			v.t.Insert(&position{pos: end, val: lastVal})
   340  		}
   341  
   342  	// hangs over the right end and the left end is in the vector.
   343  	case end > v.max.pos:
   344  		v.max.pos = end
   345  		v.t.Insert(v.max)
   346  
   347  		prev := v.t.Floor(query(start)).(*position)
   348  		if e.Equal(prev.val) {
   349  			return
   350  		}
   351  		if last.val == nil || !e.Equal(last.val) {
   352  			v.t.Insert(&position{pos: start, val: e})
   353  		}
   354  
   355  	default:
   356  		panic("step: unexpected case")
   357  	}
   358  }
   359  
   360  // deleteRangeInclusive deletes all steps within the given range.
   361  // Note that llrb.(*Tree).DoRange does not operate on the node matching the end of a range.
   362  func deleteRangeInclusive(t *llrb.Tree, start, end int) {
   363  	var delQ []llrb.Comparable
   364  	t.DoRange(func(c llrb.Comparable) (done bool) {
   365  		delQ = append(delQ, c)
   366  		return
   367  	}, query(start), query(end+1))
   368  	for _, p := range delQ {
   369  		t.Delete(p)
   370  	}
   371  }
   372  
   373  // An Operation is a non-mutating function that can be applied to a vector using Do
   374  // and DoRange.
   375  type Operation func(start, end int, e Equaler)
   376  
   377  // Do performs the function fn on steps stored in the Vector in ascending sort order
   378  // of start position. fn is passed the start, end and value of the step.
   379  func (v *Vector) Do(fn Operation) {
   380  	var (
   381  		la  *position
   382  		min = v.min.pos
   383  	)
   384  
   385  	v.t.Do(func(c llrb.Comparable) (done bool) {
   386  		p := c.(*position)
   387  		if p.pos != min {
   388  			fn(la.pos, p.pos, la.val)
   389  		}
   390  		la = p
   391  		return
   392  	})
   393  }
   394  
   395  // Do performs the function fn on steps stored in the Vector over the range [from, to)
   396  // in ascending sort order of start position. fn is passed the start, end and value of
   397  // the step.
   398  func (v *Vector) DoRange(from, to int, fn Operation) error {
   399  	if to < from {
   400  		return ErrInvertedRange
   401  	}
   402  	var (
   403  		la  *position
   404  		min = v.min.pos
   405  		max = v.max.pos
   406  	)
   407  	if to <= min || from >= max {
   408  		return ErrOutOfRange
   409  	}
   410  
   411  	_, end, e, _ := v.StepAt(from)
   412  	if end > to {
   413  		end = to
   414  	}
   415  	fn(from, end, e)
   416  	if end == to {
   417  		return nil
   418  	}
   419  	v.t.DoRange(func(c llrb.Comparable) (done bool) {
   420  		p := c.(*position)
   421  		if p.pos != end {
   422  			fn(la.pos, p.pos, la.val)
   423  		}
   424  		la = p
   425  		return
   426  	}, query(end), query(to))
   427  	if to > la.pos {
   428  		fn(la.pos, to, la.val)
   429  	}
   430  
   431  	return nil
   432  }
   433  
   434  // A Mutator is a function that is used by Apply and ApplyRange to alter values within
   435  // a Vector.
   436  type Mutator func(Equaler) Equaler
   437  
   438  // Convenience mutator functions. Mutator functions are used by Apply and ApplyRange
   439  // to alter step values in a value-dependent manner. These mutators assume the stored
   440  // type matches the function and will panic is this is not true.
   441  var (
   442  	IncInt   Mutator = incInt   // Increment an int value.
   443  	DecInt   Mutator = decInt   // Decrement an int value.
   444  	IncFloat Mutator = incFloat // Increment a float64 value.
   445  	DecFloat Mutator = decFloat // Decrement a float64 value.
   446  )
   447  
   448  func incInt(e Equaler) Equaler   { return e.(Int) + 1 }
   449  func decInt(e Equaler) Equaler   { return e.(Int) - 1 }
   450  func incFloat(e Equaler) Equaler { return e.(Float) + 1 }
   451  func decFloat(e Equaler) Equaler { return e.(Float) - 1 }
   452  
   453  // Apply applies the mutator function m to steps stored in the Vector in ascending sort order
   454  // of start position. Redundant steps resulting from changes in step values are erased.
   455  func (v *Vector) Apply(m Mutator) {
   456  	var (
   457  		la   Equaler
   458  		min  = v.min.pos
   459  		max  = v.max.pos
   460  		delQ []query
   461  	)
   462  
   463  	v.t.Do(func(c llrb.Comparable) (done bool) {
   464  		p := c.(*position)
   465  		if p.pos == max {
   466  			return true
   467  		}
   468  		p.val = m(p.val)
   469  		if p.pos != min && p.pos != max && p.val.Equal(la) {
   470  			delQ = append(delQ, query(p.pos))
   471  		}
   472  		la = p.val
   473  		return
   474  	})
   475  
   476  	for _, d := range delQ {
   477  		v.t.Delete(d)
   478  	}
   479  }
   480  
   481  // Apply applies the mutator function m to steps stored in the Vector in over the range
   482  // [from, to) in ascending sort order of start position. Redundant steps resulting from
   483  // changes in step values are erased.
   484  func (v *Vector) ApplyRange(from, to int, m Mutator) error {
   485  	if to < from {
   486  		return ErrInvertedRange
   487  	}
   488  	if from == to {
   489  		return nil
   490  	}
   491  	var (
   492  		la   Equaler
   493  		old  position
   494  		min  = v.min.pos
   495  		max  = v.max.pos
   496  		delQ []query
   497  	)
   498  	if !v.Relaxed && (to <= min || from >= max) {
   499  		return ErrOutOfRange
   500  	}
   501  	if v.Relaxed {
   502  		if from < min {
   503  			v.SetRange(from, min, v.Zero)
   504  		}
   505  		if max < to {
   506  			v.SetRange(max, to, v.Zero)
   507  		}
   508  	}
   509  
   510  	var end int
   511  	old.pos, end, old.val, _ = v.StepAt(from)
   512  	la = old.val
   513  	la = m(la)
   514  	if to <= end {
   515  		v.SetRange(from, to, la)
   516  		return nil
   517  	}
   518  	if !la.Equal(old.val) {
   519  		switch {
   520  		case from > min:
   521  			if !la.Equal(v.t.Floor(lower(from)).(*position).val) {
   522  				v.t.Insert(&position{from, la})
   523  			} else {
   524  				v.t.Delete(query(from))
   525  			}
   526  		case from < min:
   527  			v.SetRange(from, min, la)
   528  		default:
   529  			*v.min = position{from, la}
   530  		}
   531  	}
   532  
   533  	var tail *position
   534  	v.t.DoRange(func(c llrb.Comparable) (done bool) {
   535  		p := c.(*position)
   536  		if p.pos == max {
   537  			// We should be at v.t.Max(), but don't stop
   538  			// just in case there is more. We want to fail
   539  			// noisily if max < v.t.Max().
   540  			return
   541  		}
   542  		if p.pos == to {
   543  			tail = p
   544  			return
   545  		}
   546  		old = *p // Needed for fix-up of last step if to is not at a step boundary.
   547  		p.val = m(p.val)
   548  		if p.pos != min && p.val.Equal(la) {
   549  			delQ = append(delQ, query(p.pos))
   550  		}
   551  		la = p.val
   552  		return
   553  	}, query(end), upper(to))
   554  	for _, d := range delQ {
   555  		v.t.Delete(d)
   556  	}
   557  	if to < max {
   558  		if tail == nil {
   559  			prev := v.t.Floor(lower(to)).(*position)
   560  			if old.pos != from && !old.val.Equal(prev.val) {
   561  				v.t.Insert(&position{to, old.val})
   562  			}
   563  		} else {
   564  			prev := v.t.Floor(lower(tail.pos)).(*position)
   565  			if tail.val != nil && tail.val.Equal(prev.val) {
   566  				v.t.Delete(query(tail.pos))
   567  			}
   568  		}
   569  		return nil
   570  	}
   571  
   572  	if v.Relaxed && to > max {
   573  		v.SetRange(max, to, m(v.Zero))
   574  	}
   575  
   576  	return nil
   577  }
   578  
   579  // String returns a string representation a Vector, displaying step start
   580  // positions and values. The last step indicates the end of the vector and
   581  // always has an associated value of nil.
   582  func (v *Vector) String() string {
   583  	sb := make([]string, 0, v.t.Len())
   584  	v.t.Do(func(c llrb.Comparable) (done bool) {
   585  		p := c.(*position)
   586  		sb = append(sb, fmt.Sprintf("%d:%v", p.pos, p.val))
   587  		return
   588  	})
   589  	return fmt.Sprintf("%v", sb)
   590  }