// Exponential creates a Backoff that multiplies the interval by
// an exponentially increasing factor for each attempt.
559305
func Exponential(interval time.Duration, base float64) Backoff {
	return func(attempt int) time.Duration {
		return interval * time.Duration(math.Pow(base, float64(attempt)))
	}
}
580383
func NewConstantBackoff(backoffInterval, maximumJitterInterval time.Duration) Backoff {
	return &constantBackoff{
		backoffInterval:       int64(backoffInterval / time.Millisecond),
		maximumJitterInterval: int64(maximumJitterInterval / time.Millisecond),
	}
}
420348
func RetryBackoff(retry int, minBackoff, maxBackoff time.Duration) time.Duration {
	if retry < 0 {
		retry = 0
	}

	backoff := minBackoff << uint(retry)
	if backoff > maxBackoff || backoff < minBackoff {
		backoff = maxBackoff
	}

	if backoff == 0 {
		return 0
	}
	return time.Duration(rand.Int63n(int64(backoff)))
}
1050499
func E(z *decimal.Big) *decimal.Big {
	ctx := decimal.Context{Precision: precision(z)}
	if ctx.Precision <= constPrec {
		return ctx.Set(z, _E)
	}

	ctx.Precision += 5
	var (
		sum  = z.SetUint64(2)
		fac  = new(decimal.Big).SetUint64(1)
		term = new(decimal.Big)
		prev = new(decimal.Big)
	)

	for i := uint64(2); sum.Cmp(prev) != 0; i++ {
		// Use term as our intermediate storage for our factorial. SetUint64
		// should be marginally faster than ctx.Add(incr, incr, one), but either
		// the costly call to Quo makes it difficult to notice.
		term.SetUint64(i)
		ctx.Mul(fac, fac, term)
		ctx.Quo(term, one, fac)
		prev.Copy(sum)
		ctx.Add(sum, sum, term)
	}

	ctx.Precision -= 5
	return ctx.Set(z, sum)
}
930569
func (limiters *RateLimiters) BackOff(host string) {
	limiters.mu.Lock()
	defer limiters.mu.Unlock()

	var limiter *rate.Limiter
	if limiters.perHost == nil {
		limiters.perHost = map[string]*rate.Limiter{}
	}
	if rl, ok := limiters.perHost[host]; ok {
		limiter = rl
	} else {
		limiter = rate.NewLimiter(rate.Limit(limiters.RPS), limiters.Burst)
		limiters.perHost[host] = limiter
	}

	oldLimit := float64(limiter.Limit())
	newLimit := limiters.clip(oldLimit / backOffBy)
	if oldLimit != newLimit && limiters.Logger != nil {
		limiters.Logger.Log("info", "reducing rate limit", "host", host, "limit", strconv.FormatFloat(newLimit, 'f', 2, 64))
	}
	limiter.SetLimit(rate.Limit(newLimit))
}
724347
func DefaultBackoff(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration {
	mult := math.Pow(2, float64(attemptNum)) * float64(min)
	sleep := time.Duration(mult)
	if float64(sleep) != mult || sleep > max {
		sleep = max
	}
	return sleep
}
244560
func (p *Producer) backoff(failed int) {
	backoff := p.Backoff.Duration()

	p.Logger.WithFields(log.Fields{
		"failures": failed,
		"backoff":  backoff,
	}).Warn("put failures")

	time.Sleep(backoff)
}
397419
func (b *Backoff) duration(n uint64) (t time.Duration) {
	// Saturate pow
	pow := time.Duration(math.MaxInt64)
	if n < 63 {
		pow = 1 << n
	}

	t = b.interval * pow
	if t/pow != b.interval || t > b.maxDuration {
		t = b.maxDuration
	}

	return
}
987140
func ExponentialDelayFunction(retryDelay uint, retries uint) time.Duration {
	pow := math.Pow(float64(retryDelay), float64(retries))
	return time.Duration(pow) * time.Millisecond
}
1366309
func WithBackoffConfig(b BackoffConfig) DialOption {
	return withBackoff(backoff.Exponential{
		MaxDelay: b.MaxDelay,
	})
}
299617
func (e *exponentialBackoff) Duration(attempts uint) time.Duration {
	spread := (1 << attempts) * e.first.Nanoseconds()
	if spread <= 0 || spread > e.max {
		spread = e.max
	}
	// Adding 1 to the spread ensures that the upper bound of the range of
	// possible durations includes the maximum.
	return time.Duration(e.rand.Int63n(spread + 1))
}
353796
func (erng ExpGenerator) Exp(lambda float64) float64 {
	if !(lambda > 0.0) {
		panic(fmt.Sprintf("Invalid lambda: %.2f", lambda))
	}
	return erng.exp(lambda)
}
200091
func (f *Field) Exp(e int) byte {
	if e < 0 {
		return 0
	}
	return f.exp[e%255]
}
346239
func (b *Backoffer) Backoff(typ backoffType, err error) error {
	if strings.Contains(err.Error(), mismatchClusterID) {
		logutil.Logger(context.Background()).Fatal("critical error", zap.Error(err))
	}
	select {
	case <-b.ctx.Done():
		return errors.Trace(err)
	default:
	}

	typ.Counter().Inc()
	// Lazy initialize.
	if b.fn == nil {
		b.fn = make(map[backoffType]func(context.Context) int)
	}
	f, ok := b.fn[typ]
	if !ok {
		f = typ.createFn(b.vars)
		b.fn[typ] = f
	}

	b.totalSleep += f(b.ctx)
	b.types = append(b.types, typ)

	var startTs interface{}
	if ts := b.ctx.Value(txnStartKey); ts != nil {
		startTs = ts
	}
	logutil.Logger(context.Background()).Debug("retry later",
		zap.Error(err),
		zap.Int("totalSleep", b.totalSleep),
		zap.Int("maxSleep", b.maxSleep),
		zap.Stringer("type", typ),
		zap.Reflect("txnStartTS", startTs))

	b.errors = append(b.errors, errors.Errorf("%s at %s", err.Error(), time.Now().Format(time.RFC3339Nano)))
	if b.maxSleep > 0 && b.totalSleep >= b.maxSleep {
		errMsg := fmt.Sprintf("%s backoffer.maxSleep %dms is exceeded, errors:", typ.String(), b.maxSleep)
		for i, err := range b.errors {
			// Print only last 3 errors for non-DEBUG log levels.
			if log.GetLevel() == zapcore.DebugLevel || i >= len(b.errors)-3 {
				errMsg += "\n" + err.Error()
			}
		}
		logutil.Logger(context.Background()).Warn(errMsg)
		// Use the first backoff type to generate a MySQL error.
		return b.types[0].TError()
	}
	return nil
}
1139405
func (b *Backoff) Duration() time.Duration {
	b.setup()

	b.decayN()

	t := b.duration(b.n)

	if b.n < math.MaxUint64 {
		b.n++
	}

	if !b.noJitter {
		prngMu.Lock()
		t = time.Duration(prng.Int63n(int64(t)))
		prngMu.Unlock()
	}

	return t
}
261783
func WithBackoff(bf BackoffFunc) CallOption {
	return CallOption{applyFunc: func(o *options) {
		o.backoffFunc = BackoffFuncContext(func(ctx context.Context, attempt uint) time.Duration {
			return bf(attempt)
		})
	}}
}
384266
func NewExponentialBackOff() *backoff.ExponentialBackOff {
	b := &backoff.ExponentialBackOff{
		InitialInterval:     DefaultInitialInterval,
		RandomizationFactor: DefaultRandomizationFactor,
		Multiplier:          DefaultMultiplier,
		MaxInterval:         DefaultMaxInterval,
		MaxElapsedTime:      DefaultMaxElapsedTime,
		Clock:               backoff.SystemClock,
	}
	if b.RandomizationFactor < 0 {
		b.RandomizationFactor = 0
	} else if b.RandomizationFactor > 1 {
		b.RandomizationFactor = 1
	}
	b.Reset()
	return b
}