...

Text file src/golang.conradwood.net/go-easyops/utils/interpolator.go~

Documentation: golang.conradwood.net/go-easyops/utils

     1package main
     2
     3import (
     4	"fmt"
     5	"sort"
     6	"sync"
     7)
     8
     9/*
    10	given some reference points will interpolate a value,
    11
    12examples:
    13 1. reference points 5(50) and 10(100), interpolation: 7=70, 8=80,3=30 (0 is assumed), 11=100 (highest=max)
    14*/
    15type Interpolator struct {
    16	sync.Mutex
    17	referencepoints []*interpolator_referencepoint
    18}
    19
    20type interpolator_referencepoint struct {
    21	number float64
    22	value  float64
    23}
    24
    25func (ip *Interpolator) AddReferencePoints(points map[float64]float64) {
    26	for k, v := range points {
    27		ip.AddReferencePoint(k, v)
    28	}
    29}
    30func (ip *Interpolator) AddReferencePoint(number, value float64) {
    31	ip.Lock()
    32	defer ip.Unlock()
    33	if len(ip.referencepoints) == 0 {
    34		ip.referencepoints = append(ip.referencepoints, &interpolator_referencepoint{number: 0, value: 0})
    35	}
    36	ip.referencepoints = append(ip.referencepoints, &interpolator_referencepoint{number: number, value: value})
    37	sort.Slice(ip.referencepoints, func(i, j int) bool {
    38		return ip.referencepoints[i].number < ip.referencepoints[j].number
    39	})
    40	var last *interpolator_referencepoint
    41	for _, ir := range ip.referencepoints {
    42		if last == nil {
    43			last = ir
    44			continue
    45		}
    46		if ir.value < last.value {
    47			fmt.Printf("WARNING: interpolator values out of order: %s\n", ip.String())
    48		}
    49		last = ir
    50	}
    51}
    52func (ip *Interpolator) Interpolate(number float64) float64 {
    53	ir1, ir2 := ip.findReferences(number)
    54	if ir2 == nil {
    55		// max out
    56		//	fmt.Printf("Value %0.1f is maxed out, because highest is %s\n", number, ir1.String())
    57		return ir1.value
    58	}
    59	xa := ir1.number
    60	ya := ir1.value
    61	xb := ir2.number
    62	yb := ir2.value
    63	x := number
    64	diff := (x - xa) / (xb - xa)
    65	y := ya + (yb-ya)*diff
    66	//fmt.Printf("Value %0.1f is between %s and %s, diff=%0.1f, res=%0.1f\n", number, ir1.String(), ir2.String(), diff, y)
    67	return y
    68}
    69func (ip *Interpolator) findReferences(number float64) (*interpolator_referencepoint, *interpolator_referencepoint) {
    70	var ir1 *interpolator_referencepoint
    71	var ir2 *interpolator_referencepoint
    72	for i, ir := range ip.referencepoints {
    73		if number < ir.number {
    74			continue
    75		}
    76		ir1 = ir
    77		if i < len(ip.referencepoints)-1 {
    78			ir2 = ip.referencepoints[i+1]
    79		} else {
    80			ir2 = nil
    81		}
    82	}
    83	return ir1, ir2
    84}
    85func (ip *Interpolator) String() string {
    86	deli := ""
    87	s := ""
    88	for _, ir := range ip.referencepoints {
    89		s = s + deli + fmt.Sprintf("%f->%f", ir.number, ir.value)
    90		deli = ", "
    91	}
    92	return s
    93}
    94
    95func (ir *interpolator_referencepoint) String() string {
    96	return fmt.Sprintf("%f->%f", ir.number, ir.value)
    97}

View as plain text