Numo::DFloat#nearly_eq
When I use Numo::DFloat instance nearly_eq method, I found difference. Ruby 2.3.0/2.4.1 gem version is 0.9.0.9.
expect case
> x = Numo::NArray[[[ -0.36133200184253111420, -0.26743056922401642339 , -0.15902724402321133379],
[ -1.19318994409269407697, -1.44963239638332885839, -1.91713985336221814926]],
[[ -0.64073243053171402561, -1.16473945661181144118, -0.71543932177509761416],
[ -0.74846194046881686646, -0.37397217072783262015, -0.67134116188410564163]]]
> y = Numo::NArray[[[ -0.36133200184253122522, -0.26743056922401642339, -0.15902724402321133379],
[ -1.19318994409269407697, -1.44963239638332885839, -1.91713985336221814926]],
[[ -0.64073243053171424766, -1.16473945661181144118, -0.71543932177509761416],
[ -0.74846194046881708850, -0.37397217072783262015, -0.67134116188410564163]]]
> p x - y
Numo::DFloat#shape=[2,2,3]
[[[1.11022e-16, 0, 0],
[0, 0, 0]],
[[2.22045e-16, 0, 0],
[2.22045e-16, 0, 0]]]
> p x.nearly_eq(y)
Numo::Bit#shape=[2,2,3]
[[[1, 1, 1],
[1, 1, 1]],
[[1, 1, 1],
[1, 1, 1]]]
not expect case
> x = Numo::NArray[[[ -1.40903182174134045113, -0.35526599480177556423, -1.70191687578730643793],
[ -0.28021637271697175109, -1.20726809289862258012, -0.20130094472294335350]],
[[ -1.06148519722576439861, -1.51812278479952222909, -0.82032336416972229109],
[ -0.42455869150749364627, -0.24733742939520531046, -0.58033516033345322604]]]
> y = Numo::NArray[[[ -1.40903182174134067317, -0.35526599480177545320, -1.70191687578730643793],
[ -0.28021637271697186211, -1.20726809289862258012, -0.20130094472294324248]],
[[ -1.06148519722576439861, -1.51812278479952267318, -0.82032336416972218007],
[ -0.42455869150749375729, -0.24733742939520553250, -0.58033516033345311502]]]
> p x - y
Numo::DFloat#shape=[2,2,3]
[[[2.22045e-16, -1.11022e-16, 0],
[1.11022e-16, 0, -1.11022e-16]],
[[0, 4.44089e-16, -1.11022e-16],
[1.11022e-16, 2.22045e-16, -1.11022e-16]]]
> p x.nearly_eq(y)
Numo::Bit#shape=[2,2,3]
[[[1, 1, 1],
[1, 1, 1]],
[[1, 1, 1],
[1, 0, 1]]]
I expect all 1.
> x = Numo::DFloat[ -0.24733742939520531046]
> y = Numo::DFloat[ -0.24733742939520553250]
> p x - y
Numo::DFloat#shape=[1]
[2.22045e-16]
> p x.nearly_eq(y)
Numo::Bit#shape=[1]
[0]
Why return [0]?
x.nearly_eq(y) is currently defined as
(x-y).lt((x.abs+y.abs)*Numo::DFloat::EPSILON*2)
Discussion on the definition of this method is welcome.
(x-y).lt((x.abs+y.abs)*Numo::DFloat::EPSILON * 2)
numo/types/float_def.h:#define DBL_EPSILON 2.2204460492503131e-16 numo/types/dfloat.h:#define m_nearly_eq(x,y) (fabs(x-y)<=(fabs(x)+fabs(y)) * DBL_EPSILON*2)
numo/types/float_def.h:#define FLT_EPSILON 1.1920928955078125e-07 numo/types/sfloat.h:#define m_nearly_eq(x,y) (fabs(x-y)<=(fabs(x)+fabs(y)) * FLT_EPSILON*2)
In the SFloat case, I think that you should use fabsf() instead of fabs().
And, I think that this accuracy is too strict.
expect case
> x = Numo::DFloat[1]
=> Numo::DFloat#shape=[1]
[1]
> log_z = Numo::NMath.log(Numo::NMath.exp(x).sum(keepdims:true))
=> Numo::DFloat#shape=[1]
[1]
> x - log_z
=> Numo::DFloat#shape=[1]
[0]
> Numo::DFloat[0].nearly_eq(x-log_z)
=> Numo::Bit#shape=[1]
[1]
not expect case
(x - log_z) does not become 0 due to the accuracy of the floating point number, but I want you to return that the results of nearly_eq() are equal.
> x = Numo::SFloat[1]
=> Numo::SFloat#shape=[1]
[1]
> log_z = Numo::NMath.log(Numo::NMath.exp(x).sum(keepdims:true))
=> Numo::SFloat#shape=[1]
[1]
> x - log_z
=> Numo::SFloat#shape=[1]
[5.96046e-08]
> Numo::SFloat[0].nearly_eq(x-log_z)
=> Numo::Bit#shape=[1]
[0]
I expect [1].
numpy
https://docs.scipy.org/doc/numpy/reference/generated/numpy.isclose.html
numpy.isclose(a, b, rtol=1e-05, atol=1e-08, equal_nan=False)
For finite values, isclose uses the following equation to test whether two floating point values are equivalent.
absolute(a - b) <= (atol + rtol * absolute(b))
In the case of numpy, the range of accuracy can be adjusted with the parameters of atol and rtol.
I also want to adjust the accuracy range with nearly_eq().