github.com/qioalice/ekago/v3@v3.3.2-0.20221202205325-5c262d586ee4/ekamath/stat.go (about)

     1  // Copyright © 2020-2022. All rights reserved.
     2  // Author: Ilya Stroy.
     3  // Contacts: iyuryevich@pm.me, https://github.com/qioalice
     4  // License: https://opensource.org/licenses/MIT
     5  
     6  package ekamath
     7  
     8  import (
     9  	"fmt"
    10  
    11  	"github.com/qioalice/ekago/v3/ekaext"
    12  )
    13  
    14  type Stat[T ekaext.Numeric] interface {
    15  	fmt.Stringer
    16  
    17  	Min() T
    18  	Max() T
    19  	Avg() T
    20  	N() int
    21  	Count(v T)
    22  	Clear()
    23  }
    24  
    25  ////////////////////////////////////////////////////////////////////////////////
    26  
    27  type _StatImpl[T ekaext.Numeric] struct {
    28  	min, max, avg T
    29  	n             int
    30  	isCumulative  bool
    31  }
    32  
    33  func (s *_StatImpl[T]) Min() T { return s.min }
    34  func (s *_StatImpl[T]) Max() T { return s.max }
    35  func (s *_StatImpl[T]) N() int { return s.n }
    36  
    37  func (s *_StatImpl[T]) Avg() T {
    38  
    39  	if s.isCumulative {
    40  		return s.avg / T(s.n)
    41  	} else {
    42  		return s.avg
    43  	}
    44  }
    45  
    46  func (s *_StatImpl[T]) Count(v T) {
    47  
    48  	if s.n == 0 {
    49  		s.min, s.max, s.avg, s.n = v, v, v, 1
    50  		return
    51  	}
    52  
    53  	s.min = Min(s.min, v)
    54  	s.max = Max(s.max, v)
    55  
    56  	if !s.isCumulative {
    57  		s.avg = v - s.avg/T(s.n+1) + s.avg
    58  	} else {
    59  		s.avg += v
    60  	}
    61  }
    62  
    63  func (s *_StatImpl[T]) Clear() {
    64  	s.min, s.max, s.avg, s.n = 0, 0, 0, 0
    65  }
    66  
    67  func (s *_StatImpl[T]) String() string {
    68  	return fmt.Sprintf("<[%d] Min: %v, Max: %v, Avg: %v>",
    69  		s.N(), s.Min(), s.Max(), s.Avg())
    70  }
    71  
    72  ////////////////////////////////////////////////////////////////////////////////
    73  
    74  func NewStatCumulative[T ekaext.Numeric]() Stat[T] {
    75  	return &_StatImpl[T]{isCumulative: true}
    76  }
    77  
    78  func NewStatIterative[T ekaext.Numeric]() Stat[T] {
    79  	return &_StatImpl[T]{isCumulative: false}
    80  }