Sieve of Eratosthenes: Difference between revisions

Content added Content deleted
m (→‎With Wheel: Haskell - correctly accidentally merging two sections, corrected comments...)
(→‎With Wheel: A. comment is not code. B. Rosetta Code is for simple and illuminating codes first. we _add_ the better performant (and very long) ones, not replace.)
Line 5,623: Line 5,623:
Used [[Emirp_primes#List-based|here]] and [[Extensible_prime_generator#List_based|here]].
Used [[Emirp_primes#List-based|here]] and [[Extensible_prime_generator#List_based|here]].


The above example has been left to show its problems, as follows:
The above can be improved in efficiency, as follows:


1. The generation of the wheel works just to generate a small wheel list which has been directly inserted into the code as here, but is very inefficient for generation of large wheels such as the 2/3/5/7/11/13/17 wheel, which has 92160 cyclic elements; this is due to it using essentially a trial division to determine the wheel (Greatest Common Divisor - gcd - works by repeated division). A programmatic wheel generator based on sieve culling is much better as to performance and can be used without inserting the generated table.
1. The generation of large wheels such as the 2/3/5/7/11/13/17 wheel, which has 92160 cyclic elements, needs to be done based on sieve culling which is much better as to performance and can be used without inserting the generated table.


2. The above routine uses ridiculous means to re-generate the position on the wheel for the recursive base primes in the use of `dropWhile`, etc. The below improved code uses a copy of the place in the wheel for each found base prime for ease of use in generating the composite number to-be-culled chains.
2. Improving the means to re-generate the position on the wheel for the recursive base primes without the use of `dropWhile`, etc. The below improved code uses a copy of the place in the wheel for each found base prime for ease of use in generating the composite number to-be-culled chains.


<lang haskell>-- autogenerates wheel primes, first sieve prime, and gaps
<lang haskell>-- autogenerates wheel primes, first sieve prime, and gaps
Line 5,670: Line 5,670:
When compiled with -O2 optimization and -fllvm (the LLVM back end), the above code is over twice as fast as the Odds-Only version as it should be as that is about the ratio of reduced operations minus some slightly increased operation complexity, sieving the primes to a hundred million in about seven seconds on a modern middle range desktop computer. It is almost twice as fast as the "primesW" version due to the increased algorithmic efficiency!
When compiled with -O2 optimization and -fllvm (the LLVM back end), the above code is over twice as fast as the Odds-Only version as it should be as that is about the ratio of reduced operations minus some slightly increased operation complexity, sieving the primes to a hundred million in about seven seconds on a modern middle range desktop computer. It is almost twice as fast as the "primesW" version due to the increased algorithmic efficiency!


Note that the "wheelGen" code could be used to not need to do further culling at all by continuously generating wheels until the square of the "firstSievePrime| is greater than the range as there are no composites left up to that limit, but this is always slower than a SoE due to the high overhead in generating the wheels - this would take a wheel generation of 1229 (number of primes to the square root of a hundred thousand is ten thousand) to create the required wheel sieved to a hundred million; however, the theoretical (if the time to advance through the lists per element were zero, which of course it is not) asymptotic performance would be O(n) instead of O(n log (log n)) where n is the range sieved. Just another case where theory supports (slightly) reduced number of operations, but practicality means that the overheads to do this are so big as to make it useless for any reasonable range ;-) !
Note that the "wheelGen" code could be used to not need to do further culling at all by continuously generating wheels until the square of the "firstSievePrime" is greater than the range as there are no composites left up to that limit, but this is always slower than a SoE due to the high overhead in generating the wheels - this would take a wheel generation of 1229 (number of primes to the square root of a hundred thousand is ten thousand) to create the required wheel sieved to a hundred million; however, the theoretical (if the time to advance through the lists per element were zero, which of course it is not) asymptotic performance would be O(n) instead of O(n log (log n)) where n is the range sieved. Just another case where theory supports (slightly) reduced number of operations, but practicality means that the overheads to do this are so big as to make it useless for any reasonable range ;-) !


===Priority Queue based incremental sieve===
===Priority Queue based incremental sieve===