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 }