Front page | perl.perl5.porters | Postings from September 2021

## Re: Missing sv_numeq() function?

From:
sisyphus
Date:
September 14, 2021 14:02
Subject:
Re: Missing sv_numeq() function?
Message ID:
```I've given it a run and it looks pretty good here.

I came across one interesting little anomaly:
############################
use strict;
use warnings;
use Math::BigRat;
use Test::More;

use Inline C => <<'EOC';

int is_eq(SV * n1, SV * n2) {
if(sv_numeq(n1, n2)) return 1;
return 0;
}

EOC

my \$bigq1 = Math::BigRat->new(
'3602879701896397/36028797018963968'
);
my \$bigq2 = Math::BigRat->new(
'1/10'
);

cmp_ok(\$bigq1, '!=', \$bigq2, "Rationals are unequal");
cmp_ok(is_eq(\$bigq1, \$bigq2), '!=', 1, "sv_numeq detects inequality");

done_testing
#############################

This outputs:

ok 1 - Rationals are unequal
not ok 2 - sv_numeq detects inequality
#   Failed test 'sv_numeq detects inequality'
#   at sv_numeq.pl line 23.
#          got: 1
#     expected: anything else

Both of those rationals equate to the double 0.1. (The first is an exact
rational representation of the value contained in that double; the second
rational rounds to that same double.)
I don't know if anything could be done about that.
On investigation, it seems that sv_numeq() is performing the division
that's implicit in the rationals, resulting in 2 doubles that contain the
same value (0.1). Unsurprisingly it therefore returns true.

2 additional tests (based on my initial, somewhat hopeful, expectations)
that I ran were:

cmp_ok(is_eq(0.1, \$bigq1), '==', 1, "sv_numeq agrees that 0.1 == \\$bigq1");
cmp_ok(is_eq(0.1, \$bigq2), '!=', 1, "sv_numeq agrees that 0.1 != \\$bigq2");

which resulted in:

ok 3 - sv_numeq agrees that 0.1 == \$bigq1
not ok 4 - sv_numeq agrees that 0.1 != \$bigq2
#   Failed test 'sv_numeq agrees that 0.1 != \$bigq2'
#   at sv_numeq.pl line 25.
#          got: 1
#     expected: anything else

Oh ... and I think there's a simple typo in the docs:
<quote>
"sv_numeq"
A convenient shortcut for calling "sv_numeq" with the "SV_GMAGIC"
flag.
</quote>
I suspect the second occurrence of "sv_numeq" should be "sv_numeq_flags" ?

Cheers,
Rob

On Mon, Sep 13, 2021 at 1:59 AM Paul "LeoNerd" Evans <leonerd@leonerd.org.uk>
wrote:

> On Fri, 20 Aug 2021 11:55:00 +0100
> "Paul \"LeoNerd\" Evans" <leonerd@leonerd.org.uk> wrote:
>
> > I propose adding an API function
> >
> >    BOOL sv_numeq(SV *left, SV *right);
> >
> > to cover this.
> >
>
> Update: here's an initial attempt, including docs and XS::APItests:
>
>   https://github.com/leonerd/perl5/tree/sv_numeq
>
>
> new sv_numeq() would recognise that flag, and I'd also add support to
> the existing sv_eq(). (Which, is stringy. In hindsight it should have
> been named sv_streq(), but too late now (unless we rename it maybe?))
>
>
> Perhaps it would be named something like `SV_TRYAMAGIC`. Or maybe the
> `SV_SKIP_OVERLOAD` which the various sv_2Xv_flags() functions all take).
>
> `SV_OVERLOAD` would be nice, except it's a bit messy having some
> _flags()-like functions that do overloading by default and have a flag
> to tell them not to, vs. other flagsy functions that don't but take a
> flag to tell them to.
>
>
> Unless.....
>
> Maybe I can solve all of these issues in one go, by making a new
> sv_streq_flags() which does overload by default, and put that behaviour
> in my new sv_numeq_flags() as well, then these functions can all respond
> to the same SV_SKIP_OVERLOAD flag in the same way. Then sv_eq() and
> sv_eq_flags() become wrappers of sv_streq_flags() which do pass the
> SV_SKIP_OVERLOAD flag. I think it would be nice to do overload by
> default as that's generally "the nice thing to do", and a flag to turn
> it off for specific circumstances.
>
>
> Thoughts?
>
> --
> Paul "LeoNerd" Evans
>
> leonerd@leonerd.org.uk      |  https://metacpan.org/author/PEVANS
> http://www.leonerd.org.uk/  |  https://www.tindie.com/stores/leonerd/
>

```