1## no critic(RCS,VERSION,explicit,Module,ProhibitMagicNumbers)
2use strict;
3use warnings;
4
5use Test::More;
6use Math::Prime::FastSieve;
7
8ok( 1, 'ok(1) should never fail.' );
9
10my %small_tests = (
11    -3 => [],
12    -1 => [],
13    0  => [],
14    1  => [],
15    2  => [2],
16    3  => [ 2, 3 ],
17    4  => [ 2, 3 ],
18    5  => [ 2, 3, 5 ],
19    6  => [ 2, 3, 5 ],
20    7  => [ 2, 3, 5, 7 ],
21    11 => [ 2, 3, 5, 7, 11 ],
22    18 => [ 2, 3, 5, 7, 11, 13, 17 ],
23    19 => [ 2, 3, 5, 7, 11, 13, 17, 19 ],
24    20 => [ 2, 3, 5, 7, 11, 13, 17, 19 ],
25);
26
27my %big_tests = (
28    1000       => 168,
29    5_000_000  => 348_513,
30    50_000_000 => 3_001_134,
31);
32
33# Test a small sieve.
34my $obj_param = 20;
35my $sieve = new_ok( 'Math::Prime::FastSieve::_Sieve', [$obj_param] );
36
37# Test $sieve->primes():
38
39note 'Testing $sieve->primes():';
40
41{
42    my %test_data = (
43        20 => [ 2, 3, 5, 7, 11, 13, 17, 19 ],
44        19 => [ 2, 3, 5, 7, 11, 13, 17, 19 ],
45        5  => [ 2, 3, 5 ],
46        3  => [ 2, 3 ],
47        2  => [2],
48        1  => [],
49        0  => [],
50        -1 => [],
51        21 => [],
52    );
53    foreach my $param ( sort { $a <=> $b } keys %test_data ) {
54        local $" = ', ';
55        my $expect = $test_data{$param};
56        is_deeply( $sieve->primes($param),
57            $expect,
58            "\$sieve->primes( $param ) returns listref of [ @{$expect} ]." );
59    }
60}
61
62note 'Testing $sieve->is_deeply()';
63{
64    my @test_data = (
65        [ [ 2, 7 ], [ 2, 3, 5, 7 ] ],
66        [ [ 3, 9 ], [ 3, 5, 7 ] ],
67        [ [ 1, 9 ], [ 2, 3, 5, 7 ] ],
68        [ [ 0, 9 ], [ 2, 3, 5, 7 ] ],
69        [ [ -1, 9 ],  [] ],               # Out of range returns [ ].
70        [ [ 12, 20 ], [ 13, 17, 19 ] ],
71        [ [ 17, 21 ], [] ],               # Out of range returns [ ].
72        [ [ -1, 21 ], [] ],               # Out of range returns [ ].
73        [ [ 14, 16 ], [] ],               # No primes in this range.
74    );
75    foreach my $test (@test_data) {
76        local $" = ', ';
77        is_deeply(
78            $sieve->ranged_primes( @{ $test->[0] } ),
79            $test->[1],
80            "\$sieve->ranged_primes( @{$test->[0]} ) "
81              . "returns [ @{$test->[1]} ]."
82              . (
83                @{ $test->[1] }
84                ? q{}
85                : ' (Out of range or none found within range.)'
86              )
87        );
88    }
89}
90
91note 'Testing $sieve->isprime()';
92{
93    my %test_data = (
94        -1 => 0,    # Out of range.
95        0  => 0,
96        1  => 0,
97        2  => 1,
98        3  => 1,
99        5  => 1,
100        19 => 1,
101        20 => 0,
102        21 => 0,    # Out of range.
103    );
104    foreach my $param ( sort { $a <=> $b } keys %test_data ) {
105        my $expect = $test_data{$param};
106        if ($expect) {
107            ok( $sieve->isprime($param),
108                "\$sieve->isprime( $param ): $param is prime." );
109        }
110        else {
111            ok( !$sieve->isprime($param),
112                    "\$sieve->isprime( $param ): $param isn't prime"
113                  . ' or is out of range.' );
114        }
115    }
116}
117
118note 'testing $sieve->nearest_le().';
119{
120    my %test_data = (
121        -1 => 0,
122        1  => 0,
123        2  => 2,
124        3  => 3,
125        4  => 3,
126        5  => 5,
127        6  => 5,
128        19 => 19,
129        20 => 19,
130        21 => 0,
131    );
132    foreach my $param ( sort { $a <=> $b } keys %test_data ) {
133        my $expect = $test_data{$param};
134        is(
135            $sieve->nearest_le($param),
136            $expect,
137            "\$sieve->nearest_le( $param ): "
138              . (
139                $expect == 0
140                ? "0: $param is out of range."
141                : "$expect is nearest prime <= $param."
142              )
143        );
144    }
145}
146
147note 'testing $sieve->nearest_ge().';
148{
149    my %test_data = (
150        -1 => 2,    # Out of range, but we can ignore that.
151        0  => 2,
152        1  => 2,
153        2  => 2,
154        3  => 3,
155        4  => 5,
156        5  => 5,
157        6  => 7,
158        19 => 19,
159        20 => 0,    # No primes >= 20 within sieve range.
160        21 => 0,    # Out of range.
161    );
162    foreach my $param ( sort { $a <=> $b } keys %test_data ) {
163        my $expect = $test_data{$param};
164        is(
165            $sieve->nearest_ge($param),
166            $expect,
167            "\$sieve->nearest_ge( $param ): "
168              . (
169                $expect == 0
170                ? "0: No primes in sieve >= $param. "
171                : "$expect is nearest prime >= $param."
172              )
173        );
174    }
175}
176
177note 'Testing $sieve->count_sieve()';
178{
179    my %test_data = (
180        -3        => 0,
181        -1        => 0,
182        0         => 0,
183        1         => 0,
184        2         => 1,
185        3         => 2,
186        4         => 2,
187        5         => 3,
188        6         => 3,
189        7         => 4,
190        11        => 5,
191        18        => 7,
192        19        => 8,
193        20        => 8,
194        1000      => 168,
195        5_000_000 => 348_513,
196    );
197    foreach my $param ( sort { $a <=> $b } keys %test_data ) {
198        my $expect = $test_data{$param};
199        is( Math::Prime::FastSieve::_Sieve->new($param)->count_sieve(), $expect,
200                "\$sieve->count_sieve(): Accurate count of $expect "
201              . "for a sieve of 1 .. $param." );
202    }
203}
204
205note 'Testing $sieve->count_le()';
206{
207    my %test_data = (
208        -3 => 0,
209        -1 => 0,
210        0  => 0,
211        1  => 0,
212        2  => 1,
213        3  => 2,
214        4  => 2,
215        5  => 3,
216        18 => 7,
217        19 => 8,
218        20 => 8,
219    );
220    foreach my $param ( sort { $a <=> $b } keys %test_data ) {
221        my $expect = $test_data{$param};
222        is( $sieve->count_le($param),
223            $expect,
224            "\$sieve->count_le( $param ): Accurate count of $expect " );
225    }
226}
227
228note 'Testing $sieve->nth_prime().';
229{
230    my %test_data = (
231        -1 => 0,    # Out of range.
232        0  => 0,    # Out of range.
233        1  => 2,
234        2  => 3,
235        3  => 5,
236        8  => 19,
237        9  => 0,    # Out of range.
238    );
239    foreach my $param ( sort { $a <=> $b } keys %test_data ) {
240        my $expect = $test_data{$param};
241        is( $sieve->nth_prime($param), $expect,
242                "\$sieve->nth_prime( $param ): The prime in the cardinal "
243              . "position ${param} is $expect. "
244              . ( !$expect ? '(Out of range.)' : q{} ) );
245    }
246}
247
248done_testing();
249