[libmath-prime-util-perl] 74/181: more XS tweaks
Partha P. Mukherjee
ppm-guest at moszumanska.debian.org
Thu May 21 18:51:08 UTC 2015
This is an automated email from the git hooks/post-receive script.
ppm-guest pushed a commit to annotated tag v0.36
in repository libmath-prime-util-perl.
commit 9ed115df4c6e23e220170d6bfc220446313f2600
Author: bulk88 <bulk88 at hotmail.com>
Date: Tue Dec 31 04:28:52 2013 -0500
more XS tweaks
in _validate_int, croak and warn use perl's printf implementation which is
Perl_sv_vcatpvfn_flags. You can pass a SV*. This is more compact machine
code for the rare error braches, also by making the croaks identical, they
optimize to 1 asm branch
in XSUB prime_memfree, my VC 2003 32 bit CC didn't realize ix on 0 and 1
didn't return anything, also 0 was stored in a non-vol register ret even
though in some cases it will never be used. Just make things explicit with
gotos. Since its a PPCODE, a jump to the end does a PUTBACK which leaves
0 ret SVs.
in prime_precalc, make tailcall/"jmp" friendly
in _XS_factor_exp, remove multiple stack extends
in _XS_lucas_sequence, we take in 4 args or xsubpp's croak execs, but
return 3, no EXTEND needed
in factor, don't call GIMME_V, which contains function calls, more than
once
---
XS.xs | 42 +++++++++++++++++++++++++-----------------
1 file changed, 25 insertions(+), 17 deletions(-)
diff --git a/XS.xs b/XS.xs
index 7b5578d..3072b6f 100644
--- a/XS.xs
+++ b/XS.xs
@@ -89,19 +89,20 @@ static int _validate_int(pTHX_ SV* n, int negok)
int ret, isneg = 0;
/* TODO: magic, grok_number, etc. */
+ /* fix multiple magic aware Sv*V getters */
if (SvGAMAGIC(n)) return 0; /* Leave while we still can */
if (!SvOK(n)) croak("Parameter must be defined");
if (SvIOK(n)) { /* If defined as number, use that */
if (SvIsUV(n) || SvIV(n) >= 0) return 1;
if (negok) return -1;
- else croak("Parameter '%s' must be a positive integer", SvPV_nolen(n));
+ else croak("Parameter '" SVf "' must be a positive integer", n);
}
if (SvROK(n) && !sv_isa(n, "Math::BigInt")) return 0;
ptr = SvPV(n, len); /* Includes stringifying bigints */
- if (len == 0 || ptr == 0) croak("Parameter '' must be a positive integer");
+ if (len == 0 || ptr == 0) croak("Parameter '" SVf "' must be a positive integer", n);
if (ptr[0] == '-') { /* Read negative sign */
if (negok) { isneg = 1; ptr++; len--; }
- else croak("Parameter '%s' must be a positive integer", ptr);
+ else croak("Parameter '" SVf "' must be a positive integer", n);
}
if (ptr[0] == '+') { ptr++; len--; } /* Allow a single plus sign */
while (len > 0 && *ptr == '0') /* Strip all leading zeros */
@@ -110,7 +111,7 @@ static int _validate_int(pTHX_ SV* n, int negok)
return 0;
for (i = 0; i < len; i++) /* Ensure all characters are digits */
if (!isDIGIT(ptr[i]))
- croak("Parameter '%s' must be a positive integer", ptr);
+ croak("Parameter '" SVf "' must be a positive integer", n);
if (isneg == 1) /* Negative number (ignore overflow) */
return -1;
ret = isneg ? -1 : 1;
@@ -161,15 +162,17 @@ prime_memfree()
_XS_get_callgmp = 3
_get_prime_cache_size = 4
PPCODE:
- UV ret = 0;
+ UV ret;
switch (ix) {
- case 0: prime_memfree(); break;
- case 1: _prime_memfreeall(); break;
+ case 0: prime_memfree(); goto return_nothing;
+ case 1: _prime_memfreeall(); goto return_nothing;
case 2: ret = _XS_get_verbose(); break;
case 3: ret = _XS_get_callgmp(); break;
- case 4: ret = get_prime_cache(0,0); break;
+ case 4:
+ default: ret = get_prime_cache(0,0); break;
}
- if (ix > 1) XSRETURN_UV(ret);
+ XSRETURN_UV(ret);
+ return_nothing:
void
prime_precalc(IN UV n)
@@ -177,12 +180,15 @@ prime_precalc(IN UV n)
_XS_set_verbose = 1
_XS_set_callgmp = 2
PPCODE:
+ PUTBACK; /* SP is never used again, the 3 next func calls are
+ tailcall friendly since this XSUB has nothing to do after the 3 calls
+ return */
switch (ix) {
case 0: prime_precalc(n); break;
case 1: _XS_set_verbose(n); break;
default: _XS_set_callgmp(n); break;
}
-
+ return; /* skip implicit PUTBACK */
void
_XS_prime_count(IN UV low, IN UV high = 0)
@@ -302,11 +308,12 @@ _XS_factor_exp(IN UV n)
} else {
/* Return ( [p1,e1], [p2,e2], [p3,e3], ... ) */
if (n == 1) XSRETURN_EMPTY;
+ EXTEND(SP, nfactors);
for (i = 0; i < nfactors; i++) {
AV* av = newAV();
av_push(av, newSVuv(factors[i]));
av_push(av, newSVuv(exponents[i]));
- XPUSHs( sv_2mortal(newRV_noinc( (SV*) av )) );
+ PUSHs( sv_2mortal(newRV_noinc( (SV*) av )) );
}
}
@@ -410,9 +417,9 @@ _XS_lucas_sequence(IN UV n, IN IV P, IN IV Q, IN UV k)
UV U, V, Qk;
PPCODE:
lucas_seq(&U, &V, &Qk, n, P, Q, k);
- XPUSHs(sv_2mortal(newSVuv( U )));
- XPUSHs(sv_2mortal(newSVuv( V )));
- XPUSHs(sv_2mortal(newSVuv( Qk )));
+ PUSHs(sv_2mortal(newSVuv( U )));
+ PUSHs(sv_2mortal(newSVuv( V )));
+ PUSHs(sv_2mortal(newSVuv( Qk )));
int
_XS_is_prime(IN UV n)
@@ -494,21 +501,22 @@ next_prime(IN SV* svn)
void
factor(IN SV* svn)
PPCODE:
+ U32 gimme_v = GIMME_V;
int status = _validate_int(aTHX_ svn, 0);
if (status == 1) {
UV factors[MPU_MAX_FACTORS+1];
UV n = my_svuv(svn);
int i, nfactors = factor(n, factors);
- if (GIMME_V == G_SCALAR) {
+ if (gimme_v == G_SCALAR) {
PUSHs(sv_2mortal(newSVuv(nfactors)));
- } else if (GIMME_V == G_ARRAY) {
+ } else if (gimme_v == G_ARRAY) {
EXTEND(SP, nfactors);
for (i = 0; i < nfactors; i++) {
PUSHs(sv_2mortal(newSVuv( factors[i] )));
}
}
} else {
- _vcallsubn(aTHX_ GIMME_V, "Math::Prime::Util::_generic_factor", 1);
+ _vcallsubn(aTHX_ gimme_v, "Math::Prime::Util::_generic_factor", 1);
return; /* skip implicit PUTBACK */
}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-perl/packages/libmath-prime-util-perl.git
More information about the Pkg-perl-cvs-commits
mailing list