@@ -8713,7 +8713,7 @@ Perl_sv_streq_flags(pTHX_ SV *sv1, SV *sv2, const U32 flags)
87138713
87148714PERL_STATIC_INLINE bool
87158715S_sv_numcmp_common(pTHX_ SV **sv1, SV **sv2, const U32 flags,
8716- int method, bool *result) {
8716+ int method, SV * *result) {
87178717 if(flags & SV_GMAGIC) {
87188718 if(*sv1)
87198719 SvGETMAGIC(*sv1);
@@ -8727,11 +8727,10 @@ S_sv_numcmp_common(pTHX_ SV **sv1, SV **sv2, const U32 flags,
87278727 if(!*sv2)
87288728 *sv2 = &PL_sv_undef;
87298729
8730- SV *sv_result;
8730+ /* FIXME: do_ncmp doesn't handle "+0" overloads well */
87318731 if(!(flags & SV_SKIP_OVERLOAD) &&
87328732 (SvAMAGIC(*sv1) || SvAMAGIC(*sv2)) &&
8733- (sv_result = amagic_call(*sv1, *sv2, method, 0))) {
8734- *result = SvTRUE(sv_result);
8733+ (*result = amagic_call(*sv1, *sv2, method, 0))) {
87358734 return true;
87368735 }
87378736
@@ -8803,9 +8802,9 @@ Perl_sv_numeq_flags(pTHX_ SV *sv1, SV *sv2, const U32 flags)
88038802{
88048803 PERL_ARGS_ASSERT_SV_NUMEQ_FLAGS;
88058804
8806- bool result;
8805+ SV * result;
88078806 if (UNLIKELY(sv_numcmp_common(&sv1, &sv2, flags, eq_amg, &result)))
8808- return result;
8807+ return SvTRUE( result) ;
88098808
88108809 return do_ncmp(sv1, sv2) == 0;
88118810}
@@ -8816,13 +8815,86 @@ Perl_sv_numne_flags(pTHX_ SV *sv1, SV *sv2, const U32 flags)
88168815 PERL_ARGS_ASSERT_SV_NUMNE_FLAGS;
88178816
88188817
8819- bool result;
8818+ SV * result;
88208819 if (UNLIKELY(sv_numcmp_common(&sv1, &sv2, flags, ne_amg, &result)))
8821- return result;
8820+ return SvTRUE( result) ;
88228821
88238822 return do_ncmp(sv1, sv2) != 0;
88248823}
88258824
8825+ /*
8826+ =for apidoc sv_numcmp
8827+ =for apidoc_item sv_numcmp_flags
8828+
8829+ This returns an integer indicating the ordering of the two SV
8830+ arguments, coercing them to numbers if necessary, basically behaving
8831+ like the Perl code S<C<$sv1 <=> $sv2 >>.
8832+
8833+ A NULL SV is treated as C<undef>.
8834+
8835+ This will return one of the following values:
8836+
8837+ =over
8838+
8839+ =item *
8840+
8841+ C<1> - C<sv2> is numerically greater than C<sv1>
8842+
8843+ =item *
8844+
8845+ C<0> - C<sv1> and C<sv2> are numerically equal.
8846+
8847+ =item *
8848+
8849+ C<-1> - C<sv2> is numerically less than C<sv1>
8850+
8851+ =item *
8852+
8853+ C<2> - C<sv1> and C<sv2> are not numerically comparable, probably
8854+ because one of them is C<NaN>, though overloads can extend that.
8855+
8856+ =back
8857+
8858+ C<sv_numcmp> always performs 'get' magic. C<sv_numcmp_flags> performs
8859+ 'get' magic on if C<flags> has the C<SV_GMAGIC> bit set.
8860+
8861+ C<sv_numcmp> always checks for, and if present, handles C<< <=> >>
8862+ overloading. If not present, regular numerical comparison will be
8863+ used instead.
8864+ C<sv_numcmp_flags> normally does the same, but if the
8865+ C<SV_SKIP_OVERLOAD> bit is set in C<flags> any C<< <=> >> overloading
8866+ is ignored and a regular numerical comparison is done instead.
8867+
8868+ =cut
8869+ */
8870+
8871+ #define SANE_ORDERING_RESULT(val) \
8872+ ((val) < 0 ? -1 : (val) > 0 ? 1 : 0)
8873+
8874+ I32
8875+ Perl_sv_numcmp_flags(pTHX_ SV *sv1, SV *sv2, const U32 flags)
8876+ {
8877+ PERL_ARGS_ASSERT_SV_NUMCMP_FLAGS;
8878+
8879+ SV *result;
8880+ if (UNLIKELY(sv_numcmp_common(&sv1, &sv2, flags, ncmp_amg, &result))) {
8881+ /* Similar to what sort() does in amagic_ncmp() */
8882+ if (SvIOK(result) && !SvIsUV(result)) {
8883+ IV i = SvIVX(result);
8884+ return SANE_ORDERING_RESULT(i);
8885+ }
8886+ else if (!SvOK(result)) {
8887+ return 2;
8888+ }
8889+ else {
8890+ NV nv = SvNV(result);
8891+ return SANE_ORDERING_RESULT(nv);
8892+ }
8893+ }
8894+
8895+ return do_ncmp(sv1, sv2);
8896+ }
8897+
88268898/*
88278899=for apidoc sv_cmp
88288900=for apidoc_item sv_cmp_flags
0 commit comments