RetryHelper
using System;
using System.Runtime.CompilerServices;
namespace Polly.Retry
{
    [NullableContext(1)]
    [Nullable(0)]
    internal static class RetryHelper
    {
        private const double JitterFactor = 0.5;
        private const double ExponentialFactor = 2;
        private static readonly double MaxTimeSpanTicks = (double)TimeSpan.MaxValue.Ticks - 1000;
        public static bool IsValidDelay(TimeSpan delay)
        {
            return delay >= TimeSpan.Zero;
        }
        public static TimeSpan GetRetryDelay(DelayBackoffType type, bool jitter, int attempt, TimeSpan baseDelay, TimeSpan? maxDelay, ref double state, Func<double> randomizer)
        {
            try {
                TimeSpan retryDelayCore = GetRetryDelayCore(type, jitter, attempt, baseDelay, ref state, randomizer);
                if (maxDelay.HasValue) {
                    TimeSpan valueOrDefault = maxDelay.GetValueOrDefault();
                    if (retryDelayCore > valueOrDefault)
                        return maxDelay.Value;
                }
                return retryDelayCore;
            } catch (OverflowException) {
                return maxDelay ?? TimeSpan.MaxValue;
            }
        }
        private static TimeSpan GetRetryDelayCore(DelayBackoffType type, bool jitter, int attempt, TimeSpan baseDelay, ref double state, Func<double> randomizer)
        {
            if (!(baseDelay == TimeSpan.Zero)) {
                if (!jitter) {
                    switch (type) {
                    case DelayBackoffType.Constant:
                        return baseDelay;
                    case DelayBackoffType.Linear:
                        return (double)(attempt + 1) * baseDelay;
                    case DelayBackoffType.Exponential:
                        return Math.Pow(2, (double)attempt) * baseDelay;
                    default:
                        throw new ArgumentOutOfRangeException("type", type, "The retry backoff type is not supported.");
                    }
                }
                switch (type) {
                case DelayBackoffType.Constant:
                    return ApplyJitter(baseDelay, randomizer);
                case DelayBackoffType.Linear:
                    return ApplyJitter(TimeSpan.FromMilliseconds((double)(attempt + 1) * baseDelay.TotalMilliseconds), randomizer);
                case DelayBackoffType.Exponential:
                    return DecorrelatedJitterBackoffV2(attempt, baseDelay, ref state, randomizer);
                default:
                    throw new ArgumentOutOfRangeException("type", type, "The retry backoff type is not supported.");
                }
            }
            return baseDelay;
        }
        private static TimeSpan (int attempt, TimeSpan baseDelay, ref double prev, Func<double> randomizer)
        {
            long ticks = baseDelay.Ticks;
            double num = (double)attempt + randomizer();
            double num2 = Math.Pow(2, num) * Math.Tanh(Math.Sqrt(4 * num));
            if (double.IsInfinity(num2)) {
                prev = num2;
                return TimeSpan.FromTicks((long)MaxTimeSpanTicks);
            }
            double num3 = num2 - prev;
            prev = num2;
            return TimeSpan.FromTicks((long)Math.Min(num3 * 0.7142857142857143 * (double)ticks, MaxTimeSpanTicks));
        }
        private static TimeSpan ApplyJitter(TimeSpan delay, Func<double> randomizer)
        {
            double num = delay.TotalMilliseconds * 0.5 / 2;
            double num2 = delay.TotalMilliseconds * 0.5 * randomizer() - num;
            return TimeSpan.FromMilliseconds(delay.TotalMilliseconds + num2);
        }
    }
}