Completed
Pull Request — master (#1)
by Pol
04:26 queued 01:57
created

PrimeSieveOfAtkin::findPrimes()   D

Complexity

Conditions 17
Paths 90

Size

Total Lines 41
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 306

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 41
ccs 0
cts 36
cp 0
rs 4.9807
cc 17
eloc 25
nc 90
nop 1
crap 306

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace drupol\phpermutations\Iterators;
4
5
use drupol\phpermutations\Combinatorics;
6
7
/**
8
 * Class PrimeSieveOfAtkin.
9
 *
10
 * @package drupol\phpermutations\Iterators
11
 */
12
class PrimeSieveOfAtkin extends Combinatorics implements \Iterator, \Countable {
13
14
  /**
15
   * The minimum limit.
16
   *
17
   * @var int
18
   */
19
  protected $min;
20
21
  /**
22
   * The maximum limit.
23
   *
24
   * @var int
25
   */
26
  protected $max;
27
28
  /**
29
   * The key.
30
   *
31
   * @var int
32
   */
33
  protected $key;
34
35
  /**
36
   * The primes array.
37
   *
38
   * @var array
39
   */
40
  protected $primesData;
41
42
  /**
43
   * The primes array.
44
   *
45
   * @var array
46
   */
47
  protected $primes;
48
49
  /**
50
   * The primes array converted.
51
   *
52
   * @var array
53
   */
54
  protected $data;
55
56
  /**
57
   * @var int
58
   */
59
  private $last;
0 ignored issues
show
Unused Code introduced by
The property $last is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
60
61
  private $count;
0 ignored issues
show
Unused Code introduced by
The property $count is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
62
63
  /**
64
   * PrimeSieveOfAtkin constructor.
65
   */
66
  public function __construct() {
67
    $this->primesData = new \ArrayObject(array(2 => 1, 3 => 1));
0 ignored issues
show
Documentation Bug introduced by
It seems like new \ArrayObject(array(2 => 1, 3 => 1)) of type object<ArrayObject> is incompatible with the declared type array of property $primesData.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
68
    $this->primes = array(2, 3);
69
    $this->setMinLimit(0);
70
    $this->max = PHP_INT_MAX;
71
  }
72
73
  private function generateNextPrime() {
74
    $candidate = $limit = end($this->primes);
75
76
    do {
77
      $candidate += 2;
78
      $primes = $this->findPrimes($candidate);
79
    } while (!isset($primes[$this->key()]));
80
81
    return array_keys($primes);
82
  }
83
84
  /**
85
   * @param $index
86
   */
87
  private function toggle(&$primes, $index) {
88
    if (!isset($primes[$index])) {
89
      $primes[$index] = FALSE;
90
    }
91
92
    $primes[$index] ^= TRUE;
0 ignored issues
show
Coding Style introduced by
TRUE, FALSE and NULL must be lowercase; expected true, but found TRUE.
Loading history...
93
  }
94
95
  /**
96
   * {@inheritdoc}
97
   */
98
  public function current() {
99
    if (!isset($this->primes[$this->key()])) {
100
      $this->primes = $this->generateNextPrime();
101
    }
102
    return $this->primes[$this->key()];
103
  }
104
105
  /**
106
   * {@inheritdoc}
107
   */
108
  public function valid() {
109
    return ($this->current() < $this->getMaxLimit());
110
  }
111
112
  public function findPrimes($limit) {
0 ignored issues
show
Complexity introduced by
This operation has 800 execution paths which exceeds the configured maximum of 200.

A high number of execution paths generally suggests many nested conditional statements and make the code less readible. This can usually be fixed by splitting the method into several smaller methods.

You can also find more information in the “Code” section of your repository.

Loading history...
113
    $sqrt = sqrt($limit);
114
    $isPrime = array();
115
    for ($i = 1; $i <= $sqrt; $i++) {
116
      for ($j = 1; $j <= $sqrt; $j++) {
117
        $n = 4 * pow($i, 2) + pow($j, 2);
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $n. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
118
        if ($n <= $limit && ($n % 12 == 1 || $n % 12 == 5)) {
119
          $this->toggle($isPrime, $n);
120
        }
121
        $n = 3 * pow($i, 2) + pow($j, 2);
122
        if ($n <= $limit && $n % 12 == 7) {
123
          $this->toggle($isPrime, $n);
124
        }
125
        $n = 3 * pow($i, 2) - pow($j, 2);
126
        if ($i > $j && $n <= $limit && $n % 12 == 11) {
127
          $this->toggle($isPrime, $n);
128
        }
129
      }
130
    }
131
132
    for ($n = 5; $n <= $sqrt; $n++) {
133
      if (isset($isPrime[$n])) {
134
        $s = pow($n, 2);
0 ignored issues
show
Comprehensibility introduced by
Avoid variables with short names like $s. Configured minimum length is 3.

Short variable names may make your code harder to understand. Variable names should be self-descriptive. This check looks for variable names who are shorter than a configured minimum.

Loading history...
135
136
        for ($k = $s; $k <= $limit; $k += $s) {
137
          $isPrime[$k] = FALSE;
138
        }
139
      }
140
    }
141
142
    $primes[2] = 2;
143
    $primes[3] = 3;
144
145
    for ($i = 0; $i < $limit; $i++) {
146
      if (isset($isPrime[$i]) && $isPrime[$i]) {
147
        $primes[$i] = $i;
148
      }
149
    }
150
151
    return $primes;
152
  }
153
154
  /**
155
   * {@inheritdoc}
156
   */
157
  public function rewind() {
158
    $this->key = 0;
159
  }
160
161
  /**
162
   * {@inheritdoc}
163
   */
164
  public function key() {
165
    return $this->key;
166
  }
167
168
  /**
169
   * {@inheritdoc}
170
   */
171
  public function next() {
172
    ++$this->key;
173
  }
174
175
  /**
176
   * Count elements of an object.
177
   *
178
   * @return int
179
   *   The number of element.
180
   */
181
  public function count() {
182
    return count($this->toArray());
183
  }
184
185
  /**
186
   * Convert the iterator into an array.
187
   *
188
   * @return array
189
   *   The elements.
190
   */
191
  public function toArray() {
192
    $data = array();
193
194
    for ($this->rewind(); $this->valid(); $this->next()) {
195
      $data[] = $this->current();
196
    }
197
198
    return $data;
199
  }
200
201
  /**
202
   * Set the maximum limit.
203
   *
204
   * @param int $max
205
   *   The limit.
206
   */
207
  public function setMaxLimit($max) {
208
    $this->max = $max;
209
    $this->primes = array_keys($this->findPrimes($this->max));
210
  }
211
212
  /**
213
   * Get the maximum limit.
214
   *
215
   * @return int
216
   *   The limit.
217
   */
218
  public function getMaxLimit() {
219
    return $this->max;
220
  }
221
222
  /**
223
   * Set the minimum limit.
224
   *
225
   * @param int $min
226
   *   The limit.
227
   */
228
  public function setMinLimit($min) {
229
    $this->min = $min;
230
  }
231
232
  /**
233
   * Get the minimum limit.
234
   *
235
   * @return int
236
   *   The limit.
237
   */
238
  public function getMinLimit() {
239
    return $this->min <= 2 ? 2 : intval($this->min);
240
  }
241
242
  /**
243
   * Get a rough estimation of how many prime numbers there are.
244
   *
245
   * @return float
246
   *   The number of primes.
247
   */
248
  public function pi() {
0 ignored issues
show
Coding Style introduced by
This method's name is shorter than the configured minimum length of 3 characters.

Even though PHP does not care about the name of your methods, it is generally a good practice to choose method names which can be easily understood by other human readers.

Loading history...
249
    return $this->getMaxLimit() / log($this->getMaxLimit());
250
  }
251
252
}
253