func (p LinearPacer) hits(t time.Duration) float64 {
	if t < 0 {
		return 0
	}
	a := p.Slope
	b := p.StartAt.hitsPerNs() * 1e9
	x := t.Seconds()
	return (a*math.Pow(x, 2))/2 + b*x
}
hits returns the number of hits that have been sent during an attack
lasting t nanoseconds. It returns a float so we can tell exactly how
much we've missed our target by when solving numerically in Pace.
package vegeta
import (
	"fmt"
	"math"
	"time"
)
type Pacer interface {
	Pace(elapsed time.Duration, hits uint64) (wait time.Duration, stop bool)
	Rate(elapsed time.Duration) float64
}
type PacerFunc func(time.Duration, uint64) (time.Duration, bool)
func (pf PacerFunc) Pace(elapsed time.Duration, hits uint64) (time.Duration, bool) {
	return pf(elapsed, hits)
}
type ConstantPacer struct {
	Freq int            
	Per  time.Duration  
}
type Rate = ConstantPacer
var _ Pacer = ConstantPacer{}
func (cp ConstantPacer) String() string {
	return fmt.Sprintf("Constant{%d hits/%s}", cp.Freq, cp.Per)
}
func (cp ConstantPacer) Pace(elapsed time.Duration, hits uint64) (time.Duration, bool) {
	switch {
	case cp.Per == 0 || cp.Freq == 0:
		return 0, false  
	case cp.Per < 0 || cp.Freq < 0:
		return 0, true
	}
	expectedHits := uint64(cp.Freq) * uint64(elapsed/cp.Per)
	if hits < expectedHits {
		return 0, false
	}
	interval := uint64(cp.Per.Nanoseconds() / int64(cp.Freq))
	if math.MaxInt64/interval < hits {
		return 0, true
	}
	delta := time.Duration((hits + 1) * interval)
	return delta - elapsed, false
}
func (cp ConstantPacer) Rate(elapsed time.Duration) float64 {
	return cp.hitsPerNs() * 1e9
}
func (cp ConstantPacer) hitsPerNs() float64 {
	return float64(cp.Freq) / float64(cp.Per)
}
const (
	MeanUp float64 = 0
	Peak = math.Pi / 2
	MeanDown = math.Pi
	Trough = 3 * math.Pi / 2
)
type SinePacer struct {
	Period time.Duration
	Mean Rate
	Amp Rate
	StartAt float64
}
var _ Pacer = SinePacer{}
func (sp SinePacer) String() string {
	return fmt.Sprintf("Sine{%s ± %s / %s, offset %g𝛑}", sp.Mean, sp.Amp, sp.Period, sp.StartAt/math.Pi)
}
func (sp SinePacer) invalid() bool {
	return sp.Period <= 0 || sp.Mean.hitsPerNs() <= 0 || sp.Amp.hitsPerNs() >= sp.Mean.hitsPerNs()
}
func (sp SinePacer) Pace(elapsedTime time.Duration, elapsedHits uint64) (time.Duration, bool) {
	if sp.invalid() {
		return 0, true
	}
	expectedHits := sp.hits(elapsedTime)
	if elapsedHits < uint64(expectedHits) {
		return 0, false
	}
	nsPerHit := math.Round(1 / sp.hitsPerNs(elapsedTime))
	hitsToWait := float64(elapsedHits+1) - expectedHits
	nextHitIn := time.Duration(nsPerHit * hitsToWait)
	for i := 0; i < 5; i++ {
		hitsAtGuess := sp.hits(elapsedTime + nextHitIn)
		err := float64(elapsedHits+1) - hitsAtGuess
		if math.Abs(err) < 1e-3 {
			return nextHitIn, false
		}
		nextHitIn = time.Duration(float64(nextHitIn) / (hitsAtGuess - float64(elapsedHits)))
	}
	return nextHitIn, false
}
func (sp SinePacer) Rate(elapsed time.Duration) float64 {
	return sp.hitsPerNs(elapsed) * 1e9
}
func (sp SinePacer) ampHits() float64 {
	return (sp.Amp.hitsPerNs() * float64(sp.Period)) / (2 * math.Pi)
}
func (sp SinePacer) radians(t time.Duration) float64 {
	return sp.StartAt + float64(t)*2*math.Pi/float64(sp.Period)
}
func (sp SinePacer) hitsPerNs(t time.Duration) float64 {
	return sp.Mean.hitsPerNs() + sp.Amp.hitsPerNs()*math.Sin(sp.radians(t))
}
func (sp SinePacer) hits(t time.Duration) float64 {
	if t <= 0 || sp.invalid() {
		return 0
	}
	return sp.Mean.hitsPerNs()*float64(t) + sp.ampHits()*(math.Cos(sp.StartAt)-math.Cos(sp.radians(t)))
}
type LinearPacer struct {
	StartAt Rate
	Slope   float64
}
func (p LinearPacer) Pace(elapsed time.Duration, hits uint64) (time.Duration, bool) {
	switch {
	case p.StartAt.Per == 0 || p.StartAt.Freq == 0:
		return 0, false  
	case p.StartAt.Per < 0 || p.StartAt.Freq < 0:
		return 0, true
	}
	expectedHits := p.hits(elapsed)
	if hits == 0 || hits < uint64(expectedHits) {
		return 0, false
	}
	rate := p.Rate(elapsed)
	interval := math.Round(1e9 / rate)
	if n := uint64(interval); n != 0 && math.MaxInt64/n < hits {
		return 0, true
	}
	delta := float64(hits+1) - expectedHits
	wait := time.Duration(interval * delta)
	return wait, false
}
func (p LinearPacer) Rate(elapsed time.Duration) float64 {
	a := p.Slope
	x := elapsed.Seconds()
	b := p.StartAt.hitsPerNs() * 1e9
	return a*x + b
}