using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StatisticalDistribution.SpecialFunctions
{
    class Number
    {
        public static readonly double PositiveRelativeAccuracy = PositiveEpsilonOf(1.0);
        public static readonly double DefaultRelativeAccuracy = 10 * PositiveRelativeAccuracy;


        public static bool AlmostZero(double a) { return Math.Abs(a) < DefaultRelativeAccuracy; }
        public static bool AlmostEqual(double a, double b) { return AlmostEqualNorm(a, b, a - b, DefaultRelativeAccuracy); }
        public static bool AlmostEqualNorm(double a, double b, double diff, double maximumRelativeError)
        {
            if((a == 0 && Math.Abs(b) < maximumRelativeError) || (b == 0 && Math.Abs(a) < maximumRelativeError)) { return true; }
            return Math.Abs(diff) < maximumRelativeError * Math.Max(Math.Abs(a), Math.Abs(b));
        }
        public static double PositiveEpsilonOf(double value) { return 2 * EpsilonOf(value); }
        public static double EpsilonOf(double value)
        {
            if (Double.IsInfinity(value) || Double.IsNaN(value)) { return Double.NaN; }

            long signed64 = BitConverter.DoubleToInt64Bits(value);
            if (signed64 == 0)
            {
                signed64++;
                return BitConverter.Int64BitsToDouble(signed64) - value;
            }
            if (signed64-- < 0)
            {
                return BitConverter.Int64BitsToDouble(signed64) - value;
            }
            return value - BitConverter.Int64BitsToDouble(signed64);
        }
    }
}
