Function for comparing floating point numbers I am trying to make a function for floating point numbers comparison.
The goal is to "evaluate" all operators in single function: >, >=, =, &lt;=, &lt;. 
If X>Y, then F>0. If X==Y, F==0. If X&lt;=Y, F&lt;=0 etc (where F is returned value).
I took a piece of code from numeric limits. First thing I changed, in scaling of epsilon, fabs(x+y) to fabs(x)+fabs(y) (because if x=-y, we would be comparing diff to 0; which probably would work fine, but sounds kinda stupid). I've also seen an approach using max(fabs(x), fabs(y)), can we say that one of them is better than the others?
Third parameter, DecadesOfInAccuracy, means how many digits above epsilon() should be ignored.

#include &lt;limits&gt;
#include &lt;iostream&gt;

template&lt;class T&gt;
typename std::enable_if&lt;!std::numeric_limits&lt;T&gt;::is_integer, int&gt;::type
cmp(T x, T y, unsigned int doia = 0)
{
    std::cout &lt;&lt; "X: " &lt;&lt; x &lt;&lt; std::endl;
    std::cout &lt;&lt; "Y: " &lt;&lt; y &lt;&lt; std::endl;
    std::cout &lt;&lt; "D: " &lt;&lt; fabs(x - y) &lt;&lt; std::endl;
    std::cout &lt;&lt; "M: " &lt;&lt; std::numeric_limits&lt;double&gt;::min() * pow(10, doia+1) &lt;&lt; std::endl;
    std::cout &lt;&lt; "E: " &lt;&lt; std::numeric_limits&lt;T&gt;::epsilon() * (fabs(x) + fabs(y)) * pow(10, doia + 1) &lt;&lt; std::endl;

    if (fabs(x - y) &lt; std::numeric_limits&lt;double&gt;::min() * pow(10, doia + 1))
        return 0;
    bool ltoeq = (x - y) &lt;= std::numeric_limits&lt;T&gt;::epsilon() * (fabs(x)+fabs(y)) * pow(10, doia + 1);
    bool gtoeq = (y - x) &lt;= std::numeric_limits&lt;T&gt;::epsilon() * (fabs(x) + fabs(y)) * pow(10, doia + 1);
    std::cout &lt;&lt; "L: " &lt;&lt; ltoeq &lt;&lt; std::endl;
    std::cout &lt;&lt; "G: " &lt;&lt; gtoeq &lt;&lt; std::endl;
    return gtoeq - ltoeq;
}

int main()
{
    std::cout.precision(std::numeric_limits&lt;double&gt;::max_digits10 + 5);
    double x = 0.0001000000000000001;
    double y = 0.0001;

    int res = cmp(x, y, 0);
    std::cout &lt;&lt; res &lt;&lt; std::endl &lt;&lt; std::endl;
    if (res &gt; 0)
        std::cout &lt;&lt; "X&gt;Y" &lt;&lt; std::endl;
    if (res &gt;= 0)
        std::cout &lt;&lt; "X&gt;=Y" &lt;&lt; std::endl;
    if (res == 0)
        std::cout &lt;&lt; "X==Y" &lt;&lt; std::endl;
    if (res &lt;= 0)
        std::cout &lt;&lt; "X&lt;=Y" &lt;&lt; std::endl;
    if (res &lt; 0)
        std::cout &lt;&lt; "X&lt;Y" &lt;&lt; std::endl;
    return 0;
}


It "correctly" returns equality for pairs like 0.0001000000000000001; 0.0001, 1.0-4*0.2; 0.2, 0; -0, 100000000000.0001; 100000000000.
Is there something I forgot to consider, or maybe something can be simplified? (of course except couts, which will be removed :P).
I am using VS2019 if that matters.
Is there something I forgot to consider


Overflow

fabs(x) + fabs(y) is prone to  overflow, even if mathematically epsilon() * (fabs(x) + fabs(y)) * pow(10, doia + 1) is representable as a T, resulting in incorrect results.

I'd expect cmp(T x, T y, unsigned int doia = 0) to work over the entire range of x,y.

// alternative
(fabs(x)/2 + fabs(y)/2) * (epsilon() * pow(10, doia + 1) * 2)


Not-a-number

The generation of gtoeq, ltoeq are 0 when either/both x or y are a not-a-number.  Thus code returns 0, incorrectly implying near equality.  Perhaps return something to indicate more that 3 conditions like a 4-bit (==,>,&lt;,not comparable) or a double -1,0,1,NAN.

Precision

The + 1 in doia + 1 does not well allow code to just use epsilon, but minimally must use 10 * epsilon.  Consider dropping the + 1.

Rather than an integer indicating some power-of-ten * epsilon, consider simply using the desired precision or n * epsilon().  For me I'd rather use a power-of-2.