github.com/pavlo67/common@v0.5.3/common/mathlib/interpolation.go (about)

     1  package mathlib
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  )
     7  
     8  const onInterpolateByTable = "on numlib.InterpolateByTable()"
     9  
    10  func InterpolateByTable(x float64, xy [][2]float64) (float64, error) {
    11  	if len(xy) < 1 {
    12  		return 0, fmt.Errorf(onInterpolateByTable + ": table is empty")
    13  	}
    14  
    15  	sort.Slice(xy, func(i, j int) bool { return xy[i][0] < xy[j][0] })
    16  	for i := 0; i < len(xy); i++ {
    17  		if x == xy[i][0] {
    18  			return xy[i][1], nil
    19  		} else if x < xy[i][0] {
    20  			if i == 0 {
    21  				return 0, fmt.Errorf(onInterpolateByTable+": x (%f) is smaller than tha first table argument (%f)", x, xy[0][0])
    22  			}
    23  
    24  			// TODO: if xy[i][0] == xy[i-1][0] && xy[i][1] != xy[i-1][1]
    25  			return xy[i-1][1] + (x-xy[i-1][0])*(xy[i][1]-xy[i-1][1])/(xy[i][0]-xy[i-1][0]), nil
    26  		}
    27  	}
    28  
    29  	return 0, fmt.Errorf(onInterpolateByTable+": x (%f) is greater than tha last table argument (%f)", x, xy[len(xy)-1][0])
    30  }
    31  
    32  const onInterpolateByTwoPoints = "on numlib.InterpolateByTwoPoints()"
    33  
    34  func InterpolateByTwoPoints(x float64, xy [2][2]float64) (float64, error) {
    35  	if xy[0][0] < xy[1][0] {
    36  		if x < xy[0][0] || x > xy[1][0] {
    37  			return 0, fmt.Errorf("onInterpolateBetweenTwoPoints: target x (%f) isn't between x0 (%f) and x1 (%f)", x, xy[0][0], xy[1][0])
    38  		}
    39  	} else {
    40  		if x > xy[0][0] || x < xy[1][0] {
    41  			return 0, fmt.Errorf("onInterpolateBetweenTwoPoints: target x (%f) isn't between x0 (%f) and x1 (%f)", x, xy[0][0], xy[1][0])
    42  		} else if xy[1][0] == xy[0][0] {
    43  			// TODO: if xy[1][1] != xy[0][1]
    44  			return xy[0][1], nil
    45  		}
    46  	}
    47  
    48  	return xy[0][1] + (x-xy[0][0])*(xy[1][1]-xy[0][1])/(xy[1][0]-xy[0][0]), nil
    49  }