Behavior of mpf_eq near zero
Alejandro Mallea
janoma at gmail.com
Thu Apr 9 18:31:52 UTC 2015
Hi all,
My name is Alejandro. I'm new here and I hope you can help me out with this.
I'm using mpf_eq to compare near-zero values with zero, passing a
predefined tolerance value. I'm expecting a non-zero return value,
since the values I'm comparing are "approximately equal" [1] under my
tolerance. However, I keep getting zero.
Looking at the code in mpf/eq.c, I realize there's an optimization for
early return at the beginning, comparing the signs first. Since one of
the parameters is zero (and the other is not), either u->_mp_size or
v->_mp_size is equal to zero and the function will return 0, even
though the values are close under the given tolerance.
This also raises a question about the semantics for the comparison of
two near-zero values of different sign, since the optimization will
rule out that they could be equal.
Here are two reduced cases that highlight these issues.
mpf_t small, zero;
mpf_init_set_d(small, 0.0001);
mpf_init_set_d(zero, 0);
int compare = mpf_eq(small, zero, 1);
Here I'm expecting a non-zero value for compare, but that's not the case.
mpf_t pos, neg;
mpf_init_set_d(pos, 1e-10);
mpf_init_set_d(neg, -1e-10);
int compare = mpf_eq(pos, neg, 1);
Again, I'm expecting to find they are equal under the given precision
(1 bit), but mpf_eq returns 0.
The documentation says that mpf_eq(op1, op2, op3) "returns non-zero if
the first op3 bits of op1 and op2 are equal", which makes me think
equality is dangerously tied to the internal representation ("the
first op3 bits"), but then it says "i.e., test if op1 and op2 are
approximately equal.", but that is not happening in this case.
Also, I see that zero is represented by _mp_size and _mp_exp both set
to zero [2], in which case _mp_d is not only unused but most likely
uninitialized, therefore useless for a "first op3 bits" comparison.
Am I doing something wrong? Do you agree the current behavior in those
cases is not what it should be?
As an alternative, I could use mpf_cmp to compare with a predefined
epsilon value representing my tolerance, but I still I wanted to ask
your opinion about this, because it seems to me mpf_eq is not working
as it should in all cases on account of an apparently innocent
optimization.
Thanks in advance for your guidance and help.
Regards,
Alejandro
[1] https://gmplib.org/manual/Float-Comparison.html
[2] https://gmplib.org/manual/Float-Internals.html
More information about the gmp-discuss
mailing list