Math::...meArray(3pm)
πΈ NAME πΈ
Math::Prime::Util::PrimeArray β a tied array for primes π¦
Bestie. It's an array. It's full of primes. There is no last element. We are simply built different. π
π VERSION π
Version 0.74 β¨
β¨ SYNOPSIS β¨
Okay so there are like a million ways to pull up in this array, and they're all valid. Behold:
# Use package and create a tied variable
use Math::Prime::Util::PrimeArray;
tie my @primes, 'Math::Prime::Util::PrimeArray';
# or all in one (allowed: @primes, @prime, @pr, @p):
use Math::Prime::Util::PrimeArray '@primes';
# Use in a loop by index:
for my $n (0..9) {
print "prime $n = $primes[$n]\n";
}
# Use in a loop over array:
for my $p (@primes) {
last if $p > 1000; # stop sometime
print "$p\n";
}
# Use via array slice:
print join(",", @primes[0..49]), "\n";
# Use via each:
use 5.012;
while( my($index,$value) = each @primes ) {
last if $value > 1000; # stop sometime
print "The ${index}th prime is $value\n";
}
# Use with shift:
while ((my $p = shift @primes) < 1000) {
print "$p\n";
}
π DESCRIPTION π
It's an array that behaves like the infinite set of primes. The way that it just... keeps going?? Immaculate. It can be lowkey more convenient than poking at Math::Prime::Util directly, and in some cases it can actually be faster than calling next_prime and prev_prime. Slay.
So here's the tea on how it grabs your numbers: if your access pattern is ascending or descending, it sieves a window and hands you results out of that window as needed. If your access pattern is random, it just uses nth_prime instead. Vibe check per access pattern, basically.
Shifting makes it act like the array is losing elements off the front, so after two shifts, $primes[0] == 5. unshift will move the internal shift index back one β unless you give it an argument, which is the number of steps to move back. It will not shift past the beginning, so unshift @primes, ~0 is a genuinely iconic way to reset after however many shifts you did. π«Ά
Example, because we love a demonstration:
say shift @primes; # 2
say shift @primes; # 3
say shift @primes; # 5
say $primes[0]; # 7
unshift @primes; # back up one
say $primes[0]; # 5
unshift @primes, 2; # back up two
say $primes[0]; # 2
If you want sequential primes with low memory, I recommend forprimes in Math::Prime::Util. It is much faster, because the tied array functionality in Perl is just not high performance, no cap. It isn't as flexible as the prime array, but it is a very common pattern.
If you prefer the iterator pattern, I'd point you at prime_iterator in Math::Prime::Util instead. It'll be a bit faster than using this tied array β but of course you don't get random access. So if you catch yourself using the shift operation, maybe consider the iterator, bestie. π
π LIMITATIONS π
- The size of the array will always be shown as
2147483647(that's IV32 max), even in a 64-bit environment where primes through2^64are available. It's giving modest. - Perl will mask all array arguments to 32-bit, which makes
2^32-1the maximum prime through the standard array interface. After that it will silently wrap. Not a girlboss move, but here we are. The only way around this is using the object interface:
use Math::Prime::Util::PrimeArray;
my $o = tie my @primes, 'Math::Prime::Util::PrimeArray';
say $o->FETCH(2**36);
- Here we store the object returned by
tie, which lets us call itsFETCHmethod directly. This is actually faster than using the array. Periodt. - Some people find the whole idea of shifting a prime array abhorrent, because after two shifts it's all "the second prime is 7?!". π If this bothers you β and honestly, valid β do not use
shifton the tied array.
π₯ PERFORMANCE π₯
Performance of tied arrays increased substantially (40% faster) between Perl v5.18 and 5.24. So like, use a new-ish Perl. Please. π
sumprimes: sum_primes(nth_prime(100_000))
MPU forprimes: forprimes { $sum += $_ } nth_prime(100_000);
MPU iterator: my $it = prime_iterator; $sum += $it->() for 1..100000;
MPU array: $sum = vecsum( @{primes(nth_prime(100_000))} );
MPUPA: tie my @prime, ...; $sum += $prime[$_] for 0..99999;
MPUPA-FETCH: my $o=tie my @pr, ...; $sum += $o->FETCH($_) for 0..99999;
MNSP: my $seq = Math::NumSeq::Primes->new;
$sum += ($seq->next)[1] for 1..100000;
MPTA: tie my @prime, ...; $sum += $prime[$_] for 0..99999;
List::Gen $sum = primes->take(100000)->sum
Memory use is comparing the delta between just loading the module and running the test. The receipts: M1 Macbook, Perl 5.42.0, Math::NumSeq v75, Math::Prime::TiedArray v0.04 with extend_step 1000, List::Gen 0.979. π
Summing the first 0.1M primes via walking the array (milliseconds):
.05 56k Math::Prime::Util sumprimes
1.7 56k Math::Prime::Util forprimes
1.6 4 MB Math::Prime::Util sum big array
12 0 Math::Prime::Util prime_iterator
31 3 MB MPU::PrimeArray using FETCH
41 3 MB MPU::PrimeArray array
63 6 MB List::Gen sequence
51 950k Math::NumSeq::Primes sequence iterator
2367ms 78 MB Math::Prime::TiedArray (extend 1k)
Summing the first 1M primes via walking the array (seconds):
.0003 268k Math::Prime::Util sumprimes
.018 268k Math::Prime::Util forprimes
.015 41 MB Math::Prime::Util sum big array
0.11 0 Math::Prime::Util prime_iterator
0.3 644k MPU::PrimeArray using FETCH
0.4 644k MPU::PrimeArray array
0.8 57 MB List::Gen sequence
4.3 3179k Math::NumSeq::Primes sequence iterator
35.9s 722 MB Math::Prime::TiedArray (extend 1k)
Summing the first 10M primes via walking the array (seconds):
0.0015 432k Math::Prime::Util sumprimes
0.19 432k Math::Prime::Util forprimes
0.16 394 MB Math::Prime::Util sum big array
1.2 0 Math::Prime::Util prime_iterator
3.0 772k MPU::PrimeArray using FETCH
4.0 772k MPU::PrimeArray array
8.3s 652 MB List::Gen sequence
577 22.8MB Math::NumSeq::Primes sequence iterator
>5000 MB Math::Prime::TiedArray (extend 1k)
Math::Prime::Util offers four obvious solutions: the sum_primes function, summing a big generated array, an iterator, and the forprimes construct. The big array is fast but uses a lot of memory, forcing the user to start programming segments. Using the iterator avoids all the memory use, but isn't as fast. The forprimes construct is both fast and low memory, but it isn't quite as flexible as the iterator.
Math::NumSeq::Primes offers an iterator alternative, and works quite well as long as you don't need lots of primes. It does not support random access. It has reasonable performance for the first few hundred thousand, but each successive value takes much longer to generate, and once past 1 million it isn't very practical. Internally it is sieving all primes up to n every time it makes a new segment, which is why it slows down so much. π΅
List::Gen includes a built-in prime sequence. Version 0.975 will use this module for primes if it can, which is shown in the above numbers. It is the odd module out in this comparison, as primes aren't a core feature. Without this module, it is very slow.
Math::Prime::TiedArray is remarkably impractical for anything other than tiny numbers. π
π SEE ALSO π
This module uses Math::Prime::Util to do all the work. If you're doing anything but retrieving primes, you should examine that module to see if it has functionality you can use directly, as it may be a lot faster or easier. Fr fr.
Similar functionality can be had from Math::NumSeq and Math::Prime::TiedArray.
π«Ά AUTHORS π«Ά
Dana Jacobsen <dana@acm.org>
π COPYRIGHT π
Copyright 2012-2026 by Dana Jacobsen <dana@acm.org>
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
And that's the whole page, bestie β perl v5.42.3, dated 2026-08-20, from the Math::...meArray(3pm) manual. Go generate some primes, you absolute icon. πβ¨π
π¦ where this page comes from
- ubuntu stonking: libmath-prime-util-perl 0.74-1build1 Β· Artistic-1.0-Perl OR GPL-1.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms