This is an automated email from the git hooks/post-receive script. ppm-guest pushed a commit to annotated tag v0.32 in repository libmath-prime-util-perl.
commit 156c807a3ed1842140d6f94f1041d527d8c83b83 Author: Dana Jacobsen <d...@acm.org> Date: Mon Sep 30 18:33:16 2013 -0700 Cache random function for less overhead --- Changes | 6 +- lib/Math/Prime/Util.pm | 294 +++++++++++++++++++++++++++++++--------------- lib/Math/Prime/Util/PP.pm | 2 +- 3 files changed, 204 insertions(+), 98 deletions(-) diff --git a/Changes b/Changes index 7e34d7a..d6d7489 100644 --- a/Changes +++ b/Changes @@ -16,8 +16,8 @@ Revision history for Perl module Math::Prime::Util - Input validation accepts bigint objects and converts them to scalars entirely in XS. - - random_nbit_prime now uses Fouque and Tibouchi A1. Slightly better - uniformity and typically a bit faster. + - random_nbit_prime now uses Fouque and Tibouchi A1 for 65+ bits. + Slightly better uniformity and typically a bit faster. - Use MPU::GMP::pn_primorial if we have it. @@ -47,7 +47,7 @@ Revision history for Perl module Math::Prime::Util - Bytes::Random::Secure is loaded only when random prime functionality is used. Shaves a few milliseconds and bytes off of startup. - - Speedup for Perl (no GMP) primality and random nbit primes. + - Speedups for Perl (no GMP) primality and random primes. - factor() can be called in scalar context to give the number of prime factors. The XS function was ignoring the context, and now diff --git a/lib/Math/Prime/Util.pm b/lib/Math/Prime/Util.pm index 49e7008..9f3698b 100644 --- a/lib/Math/Prime/Util.pm +++ b/lib/Math/Prime/Util.pm @@ -210,8 +210,9 @@ sub prime_set_config { } elsif ($param eq 'nobigint') { $_Config{'nobigint'} = ($value) ? 1 : 0; } elsif ($param eq 'irand') { - croak "irand must supply a sub" unless ref($value) eq 'CODE'; + croak "irand must supply a sub" unless (!defined $value) || (ref($value) eq 'CODE'); $_Config{'irand'} = $value; + _clear_randf(); # Force a new randf to be generated } elsif ($param =~ /^(assume[_ ]?)?[ge]?rh$/ || $param =~ /riemann\s*h/) { $_Config{'assume_rh'} = ($value) ? 1 : 0; } elsif ($param eq 'verbose') { @@ -427,8 +428,8 @@ sub primes { # random_nbit_prime random_maurer_prime # n-bits no GMP w/ MPU::GMP no GMP w/ MPU::GMP # ---------- -------- ----------- -------- ----------- -# 24-bit 27uS same same same -# 64-bit 97uS same same same +# 24-bit 22uS same same same +# 64-bit 94uS same same same # 128-bit 0.017s 0.0020s 0.098s 0.056s # 256-bit 0.033s 0.0033s 0.25s 0.15s # 512-bit 0.066s 0.0093s 0.65s 0.30s @@ -445,8 +446,8 @@ sub primes { # 1.92 system rand # 2.62 Math::Random::MT::Auto # 12.0 Math::Random::Secure w/ISAAC::XS -# 12.6 Bytes::Random::Secure OO w/ISAAC::XS <==== our default -# 31.1 Bytes::Random::Secure OO +# 12.6 Bytes::Random::Secure OO w/ISAAC::XS <==== our +# 31.1 Bytes::Random::Secure OO <==== default # 44.5 Bytes::Random::Secure function w/ISAAC::XS # 44.8 Math::Random::Secure # 71.5 Bytes::Random::Secure function @@ -496,7 +497,9 @@ sub primes { # Returns a function that will get a uniform random number # between 0 and $max inclusive. $max can be a bigint. my $_BRS; - sub _get_rand_func { + my $_RANDF; + my $_RANDF_NBIT; + sub _set_randf { # First define a function $irandf that returns a 32-bit integer. This # corresponds to the irand function of many CPAN modules: # Math::Random::MT @@ -504,61 +507,11 @@ sub primes { # Math::Random::Xorshift # Math::Random::Secure # (but not Math::Random::MT::Auto which will return 64-bits) - # - # See if they passed one in via prime_set_config(irand=> \&irand). - # If not, make a Bytes::Random::Secure object with non-blocking seed, and - # use its irand method. - # - # This gives us a good starting point to make arbitrary size random - # numbers. Bytes::Random::Secure will get us excellent quality 32-bit - # numbers on any platform, which means we can avoid possible nightmares - # with bad system rand functions. - my $irandf = $_Config{'irand'}; - if (!defined $irandf) { - require Bytes::Random::Secure; - $_BRS = Bytes::Random::Secure->new(NonBlocking=>1) unless defined $_BRS; - $irandf = sub { return $_BRS->irand(); }; - } - # OK, now we have a function irandf. Use it. - my $randf = sub { - my($max) = @_; - return 0 if $max <= 0; - my $range = $max+1; - my $U; - if (ref($range) eq 'Math::BigInt') { - my $zero = $range->copy->bzero; - my $rbits = length($range->as_bin) - 2; # bits in range - my $rwords = int($rbits/32) + (($rbits % 32) ? 1 : 0); - # Generate more bits so we rarely have to loop. - my $rmax = Math::BigInt->bone->blsft($rwords*32)->bdec(); - my $remainder = $rmax % $range; - do { - $U = $range->copy->from_hex - ("0x" . join '', map { sprintf("%08X", $irandf->()) } 1 .. $rwords); - } while $U >= ($rmax - $remainder); - } elsif ($range <= 4294967295) { - my $remainder = 4294967295 % $range; - do { - $U = $irandf->(); - } while $U >= (4294967295 - $remainder); - } else { - croak "randf given max out of bounds: $max" if $range > ~0; - my $remainder = 18446744073709551615 % $range; - do { - $U = ($irandf->() << 32) + $irandf->(); - } while $U >= (18446744073709551615 - $remainder); - } - return $U % $range; - }; - return $randf; - } - # Returns a function that gets an nbit random number - sub _get_nbit_rand_func { my $irandf = $_Config{'irand'}; - if (!defined $irandf) { + if (!defined $irandf) { # Default irand: BRS nonblocking require Bytes::Random::Secure; $_BRS = Bytes::Random::Secure->new(NonBlocking=>1) unless defined $_BRS; - return sub { + $_RANDF_NBIT = sub { my($bits) = @_; return 0 if $bits <= 0; return ($_BRS->irand() >> (32-$bits)) @@ -570,8 +523,35 @@ sub primes { $n->brsft( 8*$bytes - $bits ) unless ($bits % 8) == 0; return $n; }; - } else { - return sub { + $_RANDF = sub { + my($max) = @_; + my $range = $max+1; + my $U; + if (ref($range) eq 'Math::BigInt') { + my $bits = length($range->as_bin) - 2; # bits in range + my $bytes = int(($bits+7)/8); + # Generate more bits so we rarely have to loop. + my $rmax = Math::BigInt->bone->blsft($bytes*8)->bdec(); + my $remainder = $rmax % $range; + do { + $U = Math::BigInt->from_hex('0x' . $_BRS->bytes_hex($bytes)); + } while $U >= ($rmax - $remainder); + } elsif ($range <= 4294967295) { + my $remainder = 4294967295 % $range; + do { + $U = $_BRS->irand(); + } while $U >= (4294967295 - $remainder); + } else { + croak "randf given max out of bounds: $max" if $range > ~0; + my $remainder = 18446744073709551615 % $range; + do { + $U = ($_BRS->irand() << 32) + $_BRS->irand(); + } while $U >= (18446744073709551615 - $remainder); + } + return $U % $range; + }; + } else { # Custom irand + $_RANDF_NBIT = sub { my($bits) = @_; return 0 if $bits <= 0; return ($irandf->() >> (32-$bits)) @@ -584,30 +564,72 @@ sub primes { $n->brsft( 32*$words - $bits ) unless ($bits % 32) == 0; return $n; }; + $_RANDF = sub { + my($max) = @_; + return 0 if $max <= 0; + my $range = $max+1; + my $U; + if (ref($range) eq 'Math::BigInt') { + my $zero = $range->copy->bzero; + my $rbits = length($range->as_bin) - 2; # bits in range + my $rwords = int($rbits/32) + (($rbits % 32) ? 1 : 0); + # Generate more bits so we rarely have to loop. + my $rmax = Math::BigInt->bone->blsft($rwords*32)->bdec(); + my $remainder = $rmax % $range; + do { + $U = $range->copy->from_hex + ("0x" . join '', map { sprintf("%08X", $irandf->()) } 1 .. $rwords); + } while $U >= ($rmax - $remainder); + } elsif ($range <= 4294967295) { + my $remainder = 4294967295 % $range; + do { + $U = $irandf->(); + } while $U >= (4294967295 - $remainder); + } else { + croak "randf given max out of bounds: $max" if $range > ~0; + my $remainder = 18446744073709551615 % $range; + do { + $U = ($irandf->() << 32) + $irandf->(); + } while $U >= (18446744073709551615 - $remainder); + } + return $U % $range; + }; } } + sub _clear_randf { + undef $_RANDF; + undef $_RANDF_NBIT; + undef $_BRS; + } + sub _get_randf { + _set_randf() unless defined $_RANDF; + return $_RANDF; + } + sub _get_randf_nbit { + _set_randf() unless defined $_RANDF_NBIT; + return $_RANDF_NBIT; + } # Sub to call with low and high already primes and verified range. my $_random_prime = sub { my($low,$high) = @_; my $prime; - # irandf->($n) gives numbers in the range [0, $n]. - my $irandf = _get_rand_func(); + _set_randf() unless defined $_RANDF; #{ my $bsize = 100; my @bins; my $counts = 10000000; # for my $c (1..$counts) { $bins[ $irandf->($bsize-1) ]++; } # for my $b (0..$bsize) {printf("%4d %8.5f%%\n", $b, $bins[$b]/$counts);} } - # low and high are both primes, and low < high. + # low and high are both odds, and low < high. - # This is fast for small values, low memory, perfectly uniform, and consumes - # the absolute minimum amount of randomness needed. But it isn't feasible - # with large values. - if ($high <= 131072 && $high <= $_XS_MAXVAL) { + # This is fast for small values, low memory, perfectly uniform, and + # consumes the minimum amount of randomness needed. But it isn't feasible + # with large values. Also note that low must be a prime. + if ($high <= 262144 && $high <= $_XS_MAXVAL) { my $li = _XS_prime_count(2, $low); my $irange = _XS_prime_count($low, $high); - my $rand = $irandf->($irange-1); + my $rand = $_RANDF->($irange-1); return _XS_nth_prime($li + $rand); } @@ -628,13 +650,13 @@ sub primes { my $loop_limit = 2000 * 1000; # To protect against broken rand if ($low > 11) { while ($loop_limit-- > 0) { - $prime = $low + 2 * $irandf->($oddrange-1); + $prime = $low + 2 * $_RANDF->($oddrange-1); next if !($prime % 3) || !($prime % 5) || !($prime % 7) || !($prime % 11); return $prime if is_prob_prime($prime); } } else { while ($loop_limit-- > 0) { - $prime = $low + 2 * $irandf->($oddrange-1); + $prime = $low + 2 * $_RANDF->($oddrange-1); next if $prime > 11 && (!($prime % 3) || !($prime % 5) || !($prime % 7) || !($prime % 11)); return 2 if $prime == 1; # Remember the special case for 2. return $prime if is_prob_prime($prime); @@ -715,7 +737,7 @@ sub primes { } $nparts-- if ($nparts * $binsize) == $oddrange; - my $rpart = $irandf->($nparts); + my $rpart = $_RANDF->($nparts); my $primelow = $low + 2 * $binsize * $rpart; my $partsize = ($rpart < $nparts) ? $binsize @@ -732,7 +754,7 @@ sub primes { # Simply things for non-bigints. if (ref($low) ne 'Math::BigInt') { while ($loop_limit-- > 0) { - my $rand = $irandf->($partsize-1); + my $rand = $_RANDF->($partsize-1); $prime = $primelow + $rand + $rand; croak "random prime failure, $prime > $high" if $prime > $high; if ($prime <= 23) { @@ -758,7 +780,7 @@ sub primes { _make_big_gcds() if $_big_gcd_use < 0; while ($loop_limit-- > 0) { - my $rand = $irandf->($partsize-1); + my $rand = $_RANDF->($partsize-1); # Check wheel-30 mod my $rand30 = $rand % 30; next if $w30[($primelow30 + 2*$rand30) % 30] @@ -794,6 +816,25 @@ sub primes { # Cache of tight bounds for each digit. Helps performance a lot. my @_random_ndigit_ranges = (undef, [2,7], [11,97] ); my @_random_nbit_ranges = (undef, undef, [2,3],[5,7] ); + my %_random_cache_small; + + # For fixed small ranges with XS, e.g. 6-digit, 18-bit + sub _random_xscount_prime { + my($low,$high) = @_; + my($istart, $irange); + my $cachearef = $_random_cache_small{$low,$high}; + if (defined $cachearef) { + ($istart, $irange) = @$cachearef; + } else { + my $beg = ($low <= 2) ? 2 : next_prime($low-1); + my $end = ($high < ~0) ? prev_prime($high + 1) : prev_prime($high); + ($istart, $irange) = ( _XS_prime_count(2, $beg), _XS_prime_count($beg, $end) ); + $_random_cache_small{$low,$high} = [$istart, $irange]; + } + _set_randf() unless defined $_RANDF; + my $rand = $_RANDF->($irange-1); + return _XS_nth_prime($istart + $rand); + } sub random_prime { my $low = (@_ == 2) ? shift : 2; @@ -815,6 +856,9 @@ sub primes { my($digits) = @_; _validate_num($digits, 1) || _validate_positive_integer($digits, 1); + return _random_xscount_prime( int(10 ** ($digits-1)), int(10 ** $digits) ) + if $digits <= 6 && int(10**$digits) <= $_XS_MAXVAL; + my $bigdigits = $digits >= $_Config{'maxdigits'}; croak "Large random primes not supported on old Perl" if $] < 5.008 && $_Config{'maxbits'} > 32 && !$bigdigits && $digits > 15; if ($bigdigits && $_Config{'nobigint'}) { @@ -858,6 +902,18 @@ sub primes { my($bits) = @_; _validate_num($bits, 2) || _validate_positive_integer($bits, 2); + _set_randf() unless defined $_RANDF_NBIT; + + # Very small size, use the nth-prime method + if ($bits <= 18 && int(2**$bits) <= $_XS_MAXVAL) { + if ($bits <= 4) { + return (2,3)[$_RANDF_NBIT->(1)] if $bits == 2; + return (5,7)[$_RANDF_NBIT->(1)] if $bits == 3; + return (11,13)[$_RANDF_NBIT->(1)] if $bits == 4; + } + return _random_xscount_prime( 1 << ($bits-1), 1 << $bits ); + } + croak "Mid-size random primes not supported on broken old Perl" if $] < 5.008 && $bits > 49 && $_Config{'maxbits'} > 32 && $bits <= $_Config{'maxbits'}; @@ -886,12 +942,11 @@ sub primes { # slow, then A2 would look more promising. # if (1 && $bits > 64) { - my $nrandf = _get_nbit_rand_func(); my $l = ($_Config{'maxbits'} > 32 && $bits > 79) ? 63 : 31; $l = 49 if $l == 63 && $] < 5.008; # Fix for broken Perl 5.6 $l = $bits-2 if $bits-2 < $l; - my $brand = $nrandf->($bits-$l-2); + my $brand = $_RANDF_NBIT->($bits-$l-2); $brand = Math::BigInt->new("$brand") unless ref($brand) eq 'Math::BigInt'; my $b = $brand->blsft(1)->binc(); @@ -909,7 +964,7 @@ sub primes { _make_big_gcds() if $_big_gcd_use < 0; my $loop_limit = 1_000_000; while ($loop_limit-- > 0) { - my $a = (1 << $l) + $nrandf->($l); + my $a = (1 << $l) + $_RANDF_NBIT->($l); # $a % s == $premod[s] => $p % s == 0 => p will be composite next if $a % 3 == $premod[ 3] || $a % 5 == $premod[ 5] || $a % 7 == $premod[ 7] || $a % 11 == $premod[11] @@ -942,23 +997,17 @@ sub primes { # gets very slow as the bit size increases, but that is why we have the # method above for bigints. if (1) { - my $nrandf = _get_nbit_rand_func(); - if ($bits <= 4) { - return (2,3)[$nrandf->(1)] if $bits == 2; - return (5,7)[$nrandf->(1)] if $bits == 3; - return (11,13)[$nrandf->(1)] if $bits == 4; - } my $loop_limit = 2_000_000; if ($bits > $_Config{'maxbits'}) { my $p = Math::BigInt->bone->blsft($bits-1)->binc(); while ($loop_limit-- > 0) { - my $n = Math::BigInt->new(''.$nrandf->($bits-2))->blsft(1)->badd($p); + my $n = Math::BigInt->new(''.$_RANDF_NBIT->($bits-2))->blsft(1)->badd($p); return $n if is_prob_prime($n); } } else { my $p = (1 << ($bits-1)) + 1; while ($loop_limit-- > 0) { - my $n = $p + ($nrandf->($bits-2) << 1); + my $n = $p + ($_RANDF_NBIT->($bits-2) << 1); return $n if is_prob_prime($n); } } @@ -1038,13 +1087,13 @@ sub primes { # Ignore Maurer's g and c that controls how much trial division is done. my $r = Math::BigFloat->new("0.5"); # relative size of the prime q my $m = 20; # makes sure R is big enough - my $irandf = _get_rand_func(); + _set_randf() unless defined $_RANDF; # Generate a random prime q of size $r*$k, where $r >= 0.5. Try to # cleverly select r to match the size of a typical random factor. if ($k > 2*$m) { do { - my $s = Math::BigFloat->new($irandf->(2147483647))->bdiv(2147483648); + my $s = Math::BigFloat->new($_RANDF->(2147483647))->bdiv(2147483648); $r = Math::BigFloat->new(2)->bpow($s-1); } while ($k*$r >= $k-$m); } @@ -1063,7 +1112,7 @@ sub primes { my $loop_limit = 1_000_000 + $k * 1_000; while ($loop_limit-- > 0) { # R is a random number between $I+1 and 2*$I - my $R = $I + 1 + $irandf->( $I - 1 ); + my $R = $I + 1 + $_RANDF->( $I - 1 ); #my $n = 2 * $R * $q + 1; my $n = Math::BigInt->new(2)->bmul($R)->bmul($q)->binc(); # We constructed a promising looking $n. Now test it. @@ -1128,7 +1177,7 @@ sub primes { eval { require Math::BigInt; Math::BigInt->import(try=>'GMP,Pari'); 1; } or do { croak "Cannot load Math::BigInt"; }; } - my $irandf = _get_rand_func(); + _set_randf() unless defined $_RANDF; my $l = (($t+1) >> 1) - 2; my $lp = int($t/2) - 20; @@ -1142,7 +1191,7 @@ sub primes { $il++ if $rem > 0; $il = $il->as_int(); my $iu = Math::BigInt->new(2)->bpow($l)->bsub(2)->bdiv(2*$qpp)->as_int(); - my $istart = $il + $irandf->($iu - $il); + my $istart = $il + $_RANDF->($iu - $il); for (my $i = $istart; $i <= $iu; $i++) { # Search for q my $q = 2 * $i * $qpp + 1; next unless is_prob_prime($q); @@ -1151,7 +1200,7 @@ sub primes { $jl++ if $rem > 0; $jl = $jl->as_int(); my $ju = Math::BigInt->new(2)->bpow($t)->bdec()->bsub($pp)->bdiv(2*$q*$qp)->as_int(); - my $jstart = $jl + $irandf->($ju - $jl); + my $jstart = $jl + $_RANDF->($ju - $jl); for (my $j = $jstart; $j <= $ju; $j++) { # Search for p my $p = $pp + 2 * $j * $q * $qp; return $p if is_prob_prime($p); @@ -2009,7 +2058,7 @@ sub miller_rabin_random { } my $brange = $n-3; - my $irandf = _get_rand_func(); + my $irandf = _get_randf(); # Do one first before doing batches return 0 unless is_strong_pseudoprime($n, $irandf->($brange)+2 ); $k--; @@ -2516,7 +2565,7 @@ __END__ =encoding utf8 -=for stopwords forprimes Möbius Deléglise totient moebius mertens znorder irand primesieve uniqued k-tuples von SoE pari yafu fonction qui compte le nombre nombres voor PhD superset sqrt(N) gcd(A^M k-th (10001st +=for stopwords forprimes Möbius Deléglise totient moebius mertens znorder irand primesieve uniqued k-tuples von SoE pari yafu fonction qui compte le nombre nombres voor PhD superset sqrt(N) gcd(A^M k-th (10001st primegen libtommath =head1 NAME @@ -4687,6 +4736,63 @@ minimal installation requirements. =head1 PERFORMANCE +First, for those looking for the state of the art non-Perl solutions: + +=over 4 + +=item Primality testing + +L<PFGW|http://sourceforge.net/projects/openpfgw/> is the fastest primality +testing software I'm aware of once past 2000 or so digits, has fast trial +division, and is especially fast on many special forms. It does not have +a BPSW test however, and there are quite a few counterexamples for a given +base of its PRP test, so for primality testing it is most useful for fast +filtering of very large candidates. A test such as the BPSW test in this +module is then recommended. + +=item Primality proofs + +L<Primo|http://www.ellipsa.eu/> is the best method for open source primality +proving for inputs over 1000 digits. Primo also does well below that size, +but other good alternatives are +L<WraithX APRCL|http://sourceforge.net/projects/mpzaprcl/>, +the APRCL from the modern L<Pari|http://pari.math.u-bordeaux.fr/> package, +or the standalone ECPP from this module with large polynomial set. + +=item Factoring + +L<yafu|http://sourceforge.net/projects/yafu/>, +L<msieve|http://sourceforge.net/projects/msieve/>, and +L<gmp-ecm|http://ecm.gforge.inria.fr/> are all good choices for large +inputs. The factoring code in this module (and all other CPAN modules) is +very limited compared to those. + +=item Primes + +L<primesieve|http://code.google.com/p/primesieve/> is the fastest publically +available code I am aware of. It is much faster than any of the alternatives, +and even more so when run multi-threaded. Tomás Oliveira e Silva's private +code may be faster for very large values, but it isn't available for testing. + +Note that the Sieve of Atkin is I<not> faster than the Sieve of Eratosthenes +when both are well implemented. The only Sieve of Atkin that is even +competitive is Bernstein's super optimized I<primegen>, which runs about +10% faster than the simple SoE in this module, slower than Pari and yafu's +SoE implementations, and 2x slower than primesieve. + +=item Prime Counts and Nth Prime + +Up to a limit, extensive use of tables plus a good segmented sieve will +produce the fastest results, but the number of tables needed to maintain +good performance grows exponentially. The code in this module approaches +the best publically available results, with the notable exception of +Christian Bau's L-M-O implementation. The author of primesieve is also +working on an L-M-O implementation. None of these are state of the art +compared to private research methods. + +=back + + =head2 PRIME COUNTS Counting the primes to C<10^10> (10 billion), with time in seconds. @@ -4869,8 +4975,8 @@ L<Math::Random::ISAAC::XS> installed. bits random +testing rand_prov Maurer CPMaurer ----- -------- -------- --------- -------- -------- - 64 0.0001 +0.000003 0.0002 0.0001 0.022 - 128 0.0020 +0.00016 0.011 0.063 0.057 + 64 0.0001 +0.000008 0.0002 0.0001 0.022 + 128 0.0020 +0.00023 0.011 0.063 0.057 256 0.0034 +0.0004 0.058 0.13 0.16 512 0.0097 +0.0012 0.28 0.28 0.41 1024 0.060 +0.0060 0.65 0.65 2.19 diff --git a/lib/Math/Prime/Util/PP.pm b/lib/Math/Prime/Util/PP.pm index 31f835c..b339999 100644 --- a/lib/Math/Prime/Util/PP.pm +++ b/lib/Math/Prime/Util/PP.pm @@ -1986,7 +1986,7 @@ sub ecm_factor { $q = $k; } my @b2primes = ($B2 > $B1) ? @{primes($B1+1, $B2)} : (); - my $irandf = Math::Prime::Util::_get_rand_func(); + my $irandf = Math::Prime::Util::_get_randf(); foreach my $curve (1 .. $ncurves) { my $sigma = $irandf->($n-1-6) + 6; -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-perl/packages/libmath-prime-util-perl.git _______________________________________________ Pkg-perl-cvs-commits mailing list Pkg-perl-cvs-commits@lists.alioth.debian.org http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-perl-cvs-commits