float64.go raw

   1  package ring
   2  
   3  type BufferFloat64 struct {
   4  	Buf    []float64
   5  	Cursor int
   6  	Full   bool
   7  }
   8  
   9  // NewBufferFloat64 creates a new ring buffer of float64 values
  10  func NewBufferFloat64(size int) *BufferFloat64 {
  11  	return &BufferFloat64{
  12  		Buf:    make([]float64, size),
  13  		Cursor: -1,
  14  	}
  15  }
  16  
  17  // Get returns the value at the given index or nil if nothing
  18  func (b *BufferFloat64) Get(index int) (out *float64) {
  19  	bl := len(b.Buf)
  20  	if index < bl {
  21  		cursor := b.Cursor + index
  22  		if cursor > bl {
  23  			cursor = cursor - bl
  24  		}
  25  		return &b.Buf[cursor]
  26  	}
  27  	return
  28  }
  29  
  30  // Len returns the length of the buffer, which grows until it fills, after which
  31  // this will always return the size of the buffer
  32  func (b *BufferFloat64) Len() (length int) {
  33  	if b.Full {
  34  		return len(b.Buf)
  35  	}
  36  	return b.Cursor
  37  }
  38  
  39  // Add a new value to the cursor position of the ring buffer
  40  func (b *BufferFloat64) Add(value float64) {
  41  	b.Cursor++
  42  	if b.Cursor == len(b.Buf) {
  43  		b.Cursor = 0
  44  		if !b.Full {
  45  			b.Full = true
  46  		}
  47  	}
  48  	b.Buf[b.Cursor] = value
  49  }
  50  
  51  // ForEach is an iterator that can be used to process every element in the
  52  // buffer
  53  func (b *BufferFloat64) ForEach(fn func(v float64) error) (e error) {
  54  	c := b.Cursor
  55  	i := c + 1
  56  	if i == len(b.Buf) {
  57  		// D.Ln("hit the end")
  58  		i = 0
  59  	}
  60  	if !b.Full {
  61  		// D.Ln("buffer not yet full")
  62  		i = 0
  63  	}
  64  	// D.Ln(b.Buf)
  65  	for ; ; i++ {
  66  		if i == len(b.Buf) {
  67  			// D.Ln("passed the end")
  68  			i = 0
  69  		}
  70  		if i == c {
  71  			// D.Ln("reached cursor again")
  72  			break
  73  		}
  74  		// D.Ln(i, b.Cursor)
  75  		if e = fn(b.Buf[i]); e != nil {
  76  			break
  77  		}
  78  	}
  79  	return
  80  }
  81