func (ps Points) XInRange(x float64) bool {
	minX := ps[0].X()
	maxX := ps[0].X()
	for _, p := range ps[1:] {
		if p.X() < minX {
			minX = p.X()
		}
		if p.X() > maxX {
			maxX = p.X()
		}
	}
	return minX <= x && x <= maxX
}
XInRange tests if an X value is in the range of X
values of the set.
package numerics
import (
	"fmt"
	"math"
	"sort"
)
type Point struct {
	x float64
	y float64
}
func NewPoint(x, y float64) *Point {
	return &Point{x, y}
}
func (p Point) IsInf() bool {
	return math.IsInf(p.x, 0) || math.IsInf(p.y, 0)
}
func (p Point) IsNaN() bool {
	return math.IsNaN(p.x) || math.IsNaN(p.y)
}
func (p Point) X() float64 {
	return p.x
}
func (p Point) Y() float64 {
	return p.y
}
func (p Point) DistanceTo(op *Point) float64 {
	dx := p.x - op.x
	dy := p.y - op.y
	return math.Sqrt(dx*dx + dy*dy)
}
func (p Point) VectorTo(op *Point) *Vector {
	return NewVector(op.X()-p.x, op.Y()-p.y)
}
func (p Point) String() string {
	return fmt.Sprintf("(%f, %f)", p.x, p.y)
}
func MiddlePoint(a, b *Point) *Point {
	return NewPoint((a.x+b.x)/2, (a.y+b.y)/2)
}
func PointVector(a, b *Point) *Vector {
	return a.VectorTo(b)
}
type Points []*Point
func NewPoints(p ...*Point) Points {
	if len(p) > 0 {
		return p
	}
	return []*Point{}
}
func (ps Points) XAt(idx int) float64 {
	return ps[idx].X()
}
func (ps Points) YAt(idx int) float64 {
	return ps[idx].Y()
}
func (ps Points) XDifference(idxA, idxB int) float64 {
	return ps[idxA].X() - ps[idxB].X()
}
func (ps Points) YDifference(idxA, idxB int) float64 {
	return ps[idxA].Y() - ps[idxB].Y()
}