Looking at a function f(x) and reference function ref_f(x) considered to be true (golden sample, the reference)
As definition the absolute difference is abs(f(x) - ref_f(x)) or absolute forward error.
(The forward error is a measure of the difference between the approximation and the true value of a function.)
(The forward error of the algorithm is the difference between the result and the solution.)
To be meaningful the resulted value should be finite, and plottable.
- If absolute difference is nan or inf the result should be real max
Also there are some issues with IEEE754 limitations NAN and Inf values that should considered:
- If both functions are equal to NAN than, there is no difference between functions, so the error might be zero.
- If both functions are equal to Inf than, there is no difference between functions, so the error might be zero, but if inf has different signs the error is max.
- nextafter() and nexttoward() float numbers should generate the correct difference (eps)
- rounding issues
- guard digits
- cancellation
Is there a MATALAB implementation (build in) for this function ?
like fae, abs_err, absDifErr ..
Math 515 Fall, 2012 Brief Notes on Conditioning, Stability and Finite Precision Arithmetic
Tried an implementation like (is this the fastest way?) :
function [absErr] = absDifErr_single(V1, V2)
if and( isfinite(V1), isfinite(V2))
absErr = abs(V1 - V2);
if ~isfinite(absErr)
absErr = realmax('single');
end
else
if or( isfinite(V1), isfinite(V2))
absErr = realmax('single');
else
if isinf(V1)
if isinf(V2)
if sign(V1)==sign(V2)
absErr = 0;
else
absErr = realmax('single');
end
else
absErr = realmax('single');
end
else
if isinf(V2)
absErr = realmax('single');
else
absErr = 0;
end
end
end
end
end
Tried a test on it:
close all
clear all
tic
disp(['abs(+nan - +nan) ' num2str(abs(+nan - +nan)) ', Absolute difference error ' num2str(absDifErr_single(+nan, +nan)) ])
disp(['abs(-nan - -nan) ' num2str(abs(-nan - -nan)) ', Absolute difference error ' num2str(absDifErr_single(-nan, -nan)) ])
disp(['abs(+nan - -nan) ' num2str(abs(+nan - -nan)) ', Absolute difference error ' num2str(absDifErr_single(+nan, -nan)) ])
disp(['abs(-nan - +nan) ' num2str(abs(-nan - +nan)) ', Absolute difference error ' num2str(absDifErr_single(-nan, +nan)) ])
disp(['abs(+inf - +inf) ' num2str(abs(+inf - +inf)) ', Absolute difference error ' num2str(absDifErr_single(+inf, +inf)) ])
disp(['abs(-inf - -inf) ' num2str(abs(-inf - -inf)) ', Absolute difference error ' num2str(absDifErr_single(-inf, -inf)) ])
disp(['abs(+inf - -inf) ' num2str(abs(+inf - -inf)) ', Absolute difference error ' num2str(absDifErr_single(+inf, -inf)) ])
disp(['abs(-inf - +inf) ' num2str(abs(-inf - +inf)) ', Absolute difference error ' num2str(absDifErr_single(-inf, +inf)) ])
disp(['abs(+inf - +nan) ' num2str(abs(+inf - +nan)) ', Absolute difference error ' num2str(absDifErr_single(+inf, +nan)) ])
disp(['abs(-inf - -nan) ' num2str(abs(-inf - -nan)) ', Absolute difference error ' num2str(absDifErr_single(-inf, -nan)) ])
disp(['abs(+inf - -nan) ' num2str(abs(+inf - -nan)) ', Absolute difference error ' num2str(absDifErr_single(+inf, -nan)) ])
disp(['abs(-inf - +nan) ' num2str(abs(-inf - +nan)) ', Absolute difference error ' num2str(absDifErr_single(-inf, +nan)) ])
disp(['abs(+nan - +inf) ' num2str(abs(+nan - +inf)) ', Absolute difference error ' num2str(absDifErr_single(+nan, +inf)) ])
disp(['abs(-nan - -inf) ' num2str(abs(-nan - -inf)) ', Absolute difference error ' num2str(absDifErr_single(-nan, -inf)) ])
disp(['abs(+nan - -inf) ' num2str(abs(+nan - -inf)) ', Absolute difference error ' num2str(absDifErr_single(+nan, -inf)) ])
disp(['abs(-nan - +inf) ' num2str(abs(-nan - +inf)) ', Absolute difference error ' num2str(absDifErr_single(-nan, +inf)) ])
disp(['abs(+nan - +5) ' num2str(abs(+nan - +5)) ', Absolute difference error ' num2str(absDifErr_single(+nan, +5)) ])
disp(['abs(-nan - -5) ' num2str(abs(-nan - -5)) ', Absolute difference error ' num2str(absDifErr_single(-nan, -5)) ])
disp(['abs(+nan - -5) ' num2str(abs(+nan - -5)) ', Absolute difference error ' num2str(absDifErr_single(+nan, -5)) ])
disp(['abs(-nan - +5) ' num2str(abs(-nan - +5)) ', Absolute difference error ' num2str(absDifErr_single(-nan, +5)) ])
disp(['abs(+5 - +nan) ' num2str(abs(+5 - +nan)) ', Absolute difference error ' num2str(absDifErr_single(+5, +nan)) ])
disp(['abs(-5 - -nan) ' num2str(abs(-5 - -nan)) ', Absolute difference error ' num2str(absDifErr_single(-5, -nan)) ])
disp(['abs(+5 - -nan) ' num2str(abs(+5 - -nan)) ', Absolute difference error ' num2str(absDifErr_single(+5, -nan)) ])
disp(['abs(-5 - +nan) ' num2str(abs(-5 - +nan)) ', Absolute difference error ' num2str(absDifErr_single(-5, +nan)) ])
disp(['abs(+inf - +5) ' num2str(abs(+inf - +5)) ', Absolute difference error ' num2str(absDifErr_single(+inf, +5)) ])
disp(['abs(-inf - -5) ' num2str(abs(-inf - -5)) ', Absolute difference error ' num2str(absDifErr_single(-inf, -5)) ])
disp(['abs(+inf - -5) ' num2str(abs(+inf - -5)) ', Absolute difference error ' num2str(absDifErr_single(+inf, -5)) ])
disp(['abs(-inf - +5) ' num2str(abs(-inf - +5)) ', Absolute difference error ' num2str(absDifErr_single(-inf, +5)) ])
disp(['abs(+5 - +inf) ' num2str(abs(+5 - +inf)) ', Absolute difference error ' num2str(absDifErr_single(+5, +inf)) ])
disp(['abs(-5 - -inf) ' num2str(abs(-5 - -inf)) ', Absolute difference error ' num2str(absDifErr_single(-5, -inf)) ])
disp(['abs(+5 - -inf) ' num2str(abs(+5 - -inf)) ', Absolute difference error ' num2str(absDifErr_single(+5, -inf)) ])
disp(['abs(-5 - +inf) ' num2str(abs(-5 - +inf)) ', Absolute difference error ' num2str(absDifErr_single(-5, +inf)) ])
disp(['abs(+5 - +5) ' num2str(abs(+5 - +5)) ', Absolute difference error ' num2str(absDifErr_single(+5, +5)) ])
disp(['abs(-5 - -5) ' num2str(abs(-5 - -5)) ', Absolute difference error ' num2str(absDifErr_single(-5, -5)) ])
disp(['abs(+5 - -5) ' num2str(abs(+5 - -5)) ', Absolute difference error ' num2str(absDifErr_single(+5, -5)) ])
disp(['abs(-5 - +5) ' num2str(abs(-5 - +5)) ', Absolute difference error ' num2str(absDifErr_single(-5, +5)) ])
a = typecast(uint32(hex2dec('40a00000')),'single');
b = typecast(uint32(hex2dec('40a00001')),'single');
disp(['abs(+5 - +5next) ' num2str(abs(+a - +b)) ', Absolute difference error ' num2str(absDifErr_single(+a, +b)) ])
disp(['abs(-5 - -5next) ' num2str(abs(-a - -b)) ', Absolute difference error ' num2str(absDifErr_single(-a, -b)) ])
disp(['abs(+5 - -5next) ' num2str(abs(+a - -b)) ', Absolute difference error ' num2str(absDifErr_single(+a, -b)) ])
disp(['abs(-5 - +5next) ' num2str(abs(-a - +b)) ', Absolute difference error ' num2str(absDifErr_single(-a, +b)) ])
a = typecast(uint32(hex2dec('40a00000')),'single');
b = typecast(uint32(hex2dec('409fffff')),'single');
disp(['abs(+5 - +5after) ' num2str(abs(+a - +b)) ', Absolute difference error ' num2str(absDifErr_single(+a, +b)) ])
disp(['abs(-5 - -5after) ' num2str(abs(-a - -b)) ', Absolute difference error ' num2str(absDifErr_single(-a, -b)) ])
disp(['abs(+5 - -5after) ' num2str(abs(+a - -b)) ', Absolute difference error ' num2str(absDifErr_single(+a, -b)) ])
disp(['abs(-5 - +5after) ' num2str(abs(-a - +b)) ', Absolute difference error ' num2str(absDifErr_single(-a, +b)) ])
disp(['abs(+5 - +6) ' num2str(abs(+5 - +6)) ', Absolute difference error ' num2str(absDifErr_single(+5, +6)) ])
disp(['abs(-5 - -6) ' num2str(abs(-5 - -6)) ', Absolute difference error ' num2str(absDifErr_single(-5, -6)) ])
disp(['abs(+5 - -6) ' num2str(abs(+5 - -6)) ', Absolute difference error ' num2str(absDifErr_single(+5, -6)) ])
disp(['abs(-5 - +6) ' num2str(abs(-5 - +6)) ', Absolute difference error ' num2str(absDifErr_single(-5, +6)) ])
a = realmax('single');
disp(['abs(+rM - +rM) ' num2str(abs(+a - +a)) ', Absolute difference error ' num2str(absDifErr_single(+a, +a)) ])
disp(['abs(-rM - -rM) ' num2str(abs(-a - -a)) ', Absolute difference error ' num2str(absDifErr_single(-a, -a)) ])
disp(['abs(+rM - -rM) ' num2str(abs(+a - -a)) ', Absolute difference error ' num2str(absDifErr_single(+a, -a)) ])
disp(['abs(-rM - +rM) ' num2str(abs(-a - +a)) ', Absolute difference error ' num2str(absDifErr_single(-a, +a)) ])
a = realmin('single');
disp(['abs(+rm - +rm) ' num2str(abs(+a - +a)) ', Absolute difference error ' num2str(absDifErr_single(+a, +a)) ])
disp(['abs(-rm - -rm) ' num2str(abs(-a - -a)) ', Absolute difference error ' num2str(absDifErr_single(-a, -a)) ])
disp(['abs(+rm - -rm) ' num2str(abs(+a - -a)) ', Absolute difference error ' num2str(absDifErr_single(+a, -a)) ])
disp(['abs(-rm - +rm) ' num2str(abs(-a - +a)) ', Absolute difference error ' num2str(absDifErr_single(-a, +a)) ])
a = realmax('single');
b = realmin('single');
disp(['abs(+rM - +rm) ' num2str(abs(+a - +b)) ', Absolute difference error ' num2str(absDifErr_single(+a, +b)) ])
disp(['abs(-rM - -rm) ' num2str(abs(-a - -b)) ', Absolute difference error ' num2str(absDifErr_single(-a, -b)) ])
disp(['abs(+rM - -rm) ' num2str(abs(+a - -b)) ', Absolute difference error ' num2str(absDifErr_single(+a, -b)) ])
disp(['abs(-rM - +rm) ' num2str(abs(-a - +b)) ', Absolute difference error ' num2str(absDifErr_single(-a, +b)) ])
b = realmax('single');
a = realmin('single');
disp(['abs(+rm - +rM) ' num2str(abs(+a - +b)) ', Absolute difference error ' num2str(absDifErr_single(+a, +b)) ])
disp(['abs(-rm - -rM) ' num2str(abs(-a - -b)) ', Absolute difference error ' num2str(absDifErr_single(-a, -b)) ])
disp(['abs(+rm - -rM) ' num2str(abs(+a - -b)) ', Absolute difference error ' num2str(absDifErr_single(+a, -b)) ])
disp(['abs(-rm - +rM) ' num2str(abs(-a - +b)) ', Absolute difference error ' num2str(absDifErr_single(-a, +b)) ])
a = single(0);
disp(['abs(+0 - +0) ' num2str(abs(+a - +a)) ', Absolute difference error ' num2str(absDifErr_single(+a, +a)) ])
disp(['abs(-0 - -0) ' num2str(abs(-a - -a)) ', Absolute difference error ' num2str(absDifErr_single(-a, -a)) ])
disp(['abs(+0 - -0) ' num2str(abs(+a - -a)) ', Absolute difference error ' num2str(absDifErr_single(+a, -a)) ])
disp(['abs(-0 - +0) ' num2str(abs(-a - +a)) ', Absolute difference error ' num2str(absDifErr_single(-a, +a)) ])
a = single(0);
disp(['abs(+nan - +0) ' num2str(abs(+nan - +a)) ', Absolute difference error ' num2str(absDifErr_single(+nan, +a)) ])
disp(['abs(-nan - -0) ' num2str(abs(-nan - -a)) ', Absolute difference error ' num2str(absDifErr_single(-nan, -a)) ])
disp(['abs(+nan - -0) ' num2str(abs(+nan - -a)) ', Absolute difference error ' num2str(absDifErr_single(+nan, -a)) ])
disp(['abs(-nan - +0) ' num2str(abs(-nan - +a)) ', Absolute difference error ' num2str(absDifErr_single(-nan, +a)) ])
a = single(0);
disp(['abs(+inf - +0) ' num2str(abs(+inf - +a)) ', Absolute difference error ' num2str(absDifErr_single(+inf, +a)) ])
disp(['abs(-inf - -0) ' num2str(abs(-inf - -a)) ', Absolute difference error ' num2str(absDifErr_single(-inf, -a)) ])
disp(['abs(+inf - -0) ' num2str(abs(+inf - -a)) ', Absolute difference error ' num2str(absDifErr_single(+inf, -a)) ])
disp(['abs(-inf - +0) ' num2str(abs(-inf - +a)) ', Absolute difference error ' num2str(absDifErr_single(-inf, +a)) ])
toc
Outputs:
abs(+nan - +nan) NaN, Absolute difference error 0
abs(-nan - -nan) NaN, Absolute difference error 0
abs(+nan - -nan) NaN, Absolute difference error 0
abs(-nan - +nan) NaN, Absolute difference error 0
abs(+inf - +inf) NaN, Absolute difference error 0
abs(-inf - -inf) NaN, Absolute difference error 0
abs(+inf - -inf) Inf, Absolute difference error 3.402823466385289e+38
abs(-inf - +inf) Inf, Absolute difference error 3.402823466385289e+38
abs(+inf - +nan) NaN, Absolute difference error 3.402823466385289e+38
abs(-inf - -nan) NaN, Absolute difference error 3.402823466385289e+38
abs(+inf - -nan) NaN, Absolute difference error 3.402823466385289e+38
abs(-inf - +nan) NaN, Absolute difference error 3.402823466385289e+38
abs(+nan - +inf) NaN, Absolute difference error 3.402823466385289e+38
abs(-nan - -inf) NaN, Absolute difference error 3.402823466385289e+38
abs(+nan - -inf) NaN, Absolute difference error 3.402823466385289e+38
abs(-nan - +inf) NaN, Absolute difference error 3.402823466385289e+38
abs(+nan - +5) NaN, Absolute difference error 3.402823466385289e+38
abs(-nan - -5) NaN, Absolute difference error 3.402823466385289e+38
abs(+nan - -5) NaN, Absolute difference error 3.402823466385289e+38
abs(-nan - +5) NaN, Absolute difference error 3.402823466385289e+38
abs(+5 - +nan) NaN, Absolute difference error 3.402823466385289e+38
abs(-5 - -nan) NaN, Absolute difference error 3.402823466385289e+38
abs(+5 - -nan) NaN, Absolute difference error 3.402823466385289e+38
abs(-5 - +nan) NaN, Absolute difference error 3.402823466385289e+38
abs(+inf - +5) Inf, Absolute difference error 3.402823466385289e+38
abs(-inf - -5) Inf, Absolute difference error 3.402823466385289e+38
abs(+inf - -5) Inf, Absolute difference error 3.402823466385289e+38
abs(-inf - +5) Inf, Absolute difference error 3.402823466385289e+38
abs(+5 - +inf) Inf, Absolute difference error 3.402823466385289e+38
abs(-5 - -inf) Inf, Absolute difference error 3.402823466385289e+38
abs(+5 - -inf) Inf, Absolute difference error 3.402823466385289e+38
abs(-5 - +inf) Inf, Absolute difference error 3.402823466385289e+38
abs(+5 - +5) 0, Absolute difference error 0
abs(-5 - -5) 0, Absolute difference error 0
abs(+5 - -5) 10, Absolute difference error 10
abs(-5 - +5) 10, Absolute difference error 10
abs(+5 - +5next) 4.7684e-07, Absolute difference error 4.7684e-07
abs(-5 - -5next) 4.7684e-07, Absolute difference error 4.7684e-07
abs(+5 - -5next) 10, Absolute difference error 10
abs(-5 - +5next) 10, Absolute difference error 10
abs(+5 - +5after) 4.7684e-07, Absolute difference error 4.7684e-07
abs(-5 - -5after) 4.7684e-07, Absolute difference error 4.7684e-07
abs(+5 - -5after) 10, Absolute difference error 10
abs(-5 - +5after) 10, Absolute difference error 10
abs(+5 - +6) 1, Absolute difference error 1
abs(-5 - -6) 1, Absolute difference error 1
abs(+5 - -6) 11, Absolute difference error 11
abs(-5 - +6) 11, Absolute difference error 11
abs(+rM - +rM) 0, Absolute difference error 0
abs(-rM - -rM) 0, Absolute difference error 0
abs(+rM - -rM) Inf, Absolute difference error 3.402823466385289e+38
abs(-rM - +rM) Inf, Absolute difference error 3.402823466385289e+38
abs(+rm - +rm) 0, Absolute difference error 0
abs(-rm - -rm) 0, Absolute difference error 0
abs(+rm - -rm) 2.351e-38, Absolute difference error 2.351e-38
abs(-rm - +rm) 2.351e-38, Absolute difference error 2.351e-38
abs(+rM - +rm) 3.402823466385289e+38, Absolute difference error 3.402823466385289e+38
abs(-rM - -rm) 3.402823466385289e+38, Absolute difference error 3.402823466385289e+38
abs(+rM - -rm) 3.402823466385289e+38, Absolute difference error 3.402823466385289e+38
abs(-rM - +rm) 3.402823466385289e+38, Absolute difference error 3.402823466385289e+38
abs(+rm - +rM) 3.402823466385289e+38, Absolute difference error 3.402823466385289e+38
abs(-rm - -rM) 3.402823466385289e+38, Absolute difference error 3.402823466385289e+38
abs(+rm - -rM) 3.402823466385289e+38, Absolute difference error 3.402823466385289e+38
abs(-rm - +rM) 3.402823466385289e+38, Absolute difference error 3.402823466385289e+38
abs(+0 - +0) 0, Absolute difference error 0
abs(-0 - -0) 0, Absolute difference error 0
abs(+0 - -0) 0, Absolute difference error 0
abs(-0 - +0) 0, Absolute difference error 0
abs(+nan - +0) NaN, Absolute difference error 3.402823466385289e+38
abs(-nan - -0) NaN, Absolute difference error 3.402823466385289e+38
abs(+nan - -0) NaN, Absolute difference error 3.402823466385289e+38
abs(-nan - +0) NaN, Absolute difference error 3.402823466385289e+38
abs(+inf - +0) Inf, Absolute difference error 3.402823466385289e+38
abs(-inf - -0) Inf, Absolute difference error 3.402823466385289e+38
abs(+inf - -0) Inf, Absolute difference error 3.402823466385289e+38
abs(-inf - +0) Inf, Absolute difference error 3.402823466385289e+38
Elapsed time is 0.088918 seconds.
These values seems strange 0x40a00000 vs 0x40a00001
abs(+5 - +5next) 4.7684e-07, Absolute difference error 4.7684e-07
abs(-5 - -5next) 4.7684e-07, Absolute difference error 4.7684e-07
abs(+5 - -5next) 10, Absolute difference error 10
abs(-5 - +5next) 10, Absolute difference error 10
abs(+5 - +5after) 4.7684e-07, Absolute difference error 4.7684e-07
abs(-5 - -5after) 4.7684e-07, Absolute difference error 4.7684e-07
abs(+5 - -5after) 10, Absolute difference error 10
abs(-5 - +5after) 10, Absolute difference error 10
Symmetrical form: max( abs(f(x) - ref_f(x)) , abs(ref_f(x) - f(x)) ) is better, (is commutative) ?
I wonder that for special data math (like ARM cores) that do not support subnormals and/or
INF/NAN are treated like big numbers how this absDifErr can be parametrized ?