<?php
// for PHP 5.3 or later
function primes($upto, $func){
if( $upto > 25000 ){ return large_primes($upto, $func); }
$upto -= 1;
for( $i = 0; $i < $upto; $i++ ){
if( $flags[$i] ){
$prime = $i + 2;
$k = $i + $prime;
while( $k < $upto ){
$flags[$k] = false;
$k += $prime;
}
$func($prime);
}
}
}
function large_primes($upto, $func){
// The Algorithm is adapted from http://w...content-available-to-author-only...k.com/~jrm/printprimes.html
// This code is a translated version of Andreas Raab's #largePrimesUpTo:do: method
// which was written for the Squeak Smalltalk environment.
$primes_up_to_2310 = array(); primes
(2310, function($p) use(&$primes_up_to_2310){ array_push($primes_up_to_2310, $p); }); $mask_bit_idx[0] = 0;
$mask_bit_idx[1] = 1;
$bit_idx = 1;
for( $i = 0; $i < 5; $i++ ){ $func($primes_up_to_2310[$i]); }
$idx = 5;
for( $n = 2; $n < 2310; $n++ ){
while( $primes_up_to_2310[$idx] < $n ){ $idx++; }
if( $n == $primes_up_to_2310[$idx] ){
$mask_bit_idx[$n] = ++$bit_idx;
} else if( $n % 2 == 0 || $n % 3 == 0 || $n % 5 == 0 || $n % 7 == 0 || $n % 11 == 0 ){
$mask_bit_idx[$n] = 0;
} else {
$mask_bit_idx[$n] = ++$bit_idx;
}
}
for( $n = 13; $n <= $upto; $n += 2 ){
if( $mask_bit = $mask_bit_idx[$n % 2310] ){
$byte_idx = floor($n / 2310) * 60 + ($mask_bit-1 >> 3); $bit_idx = 1 << ($mask_bit & 7);
if( $flags[$byte_idx] & $bit_idx ){
$func($n);
if( $n < $idx_limit ){
$idx = $n * $n;
if( !($idx & 1) ){ $idx += $n; }
while( $idx <= $upto ){
if( $mask_bit = $mask_bit_idx[$idx % 2310] ){
$byte_idx = floor($idx / 2310) * 60 + ($mask_bit-1 >> 3); $mask_bit = 255 - (1 << ($mask_bit & 7));
$flags[$byte_idx] = $flags[$byte_idx] & $mask_bit;
}
$idx += 2 * $n;
}
}
}
}
}
}
if( !$max ){ $max = 100; }
$q = $c = 0;
primes($max, function($p) use(&$q, &$c){ $q = $p; $c++; });
echo $q, " ", $c;
PD9waHAKCi8vIGZvciBQSFAgNS4zIG9yIGxhdGVyCgpmdW5jdGlvbiBwcmltZXMoJHVwdG8sICRmdW5jKXsKICAgaWYoICR1cHRvID4gMjUwMDAgKXsgcmV0dXJuIGxhcmdlX3ByaW1lcygkdXB0bywgJGZ1bmMpOyB9CiAgICR1cHRvIC09IDE7CiAgICRmbGFncyA9IGFycmF5X2ZpbGwoMCwgJHVwdG8tMSwgdHJ1ZSk7CiAgIGZvciggJGkgPSAwOyAkaSA8ICR1cHRvOyAkaSsrICl7CiAgICAgIGlmKCAkZmxhZ3NbJGldICl7CiAgICAgICAgICRwcmltZSA9ICRpICsgMjsKICAgICAgICAgJGsgPSAkaSArICRwcmltZTsKICAgICAgICAgd2hpbGUoICRrIDwgJHVwdG8gKXsKICAgICAgICAgICAgJGZsYWdzWyRrXSA9IGZhbHNlOwogICAgICAgICAgICAkayArPSAkcHJpbWU7CiAgICAgICAgIH0KICAgICAgICAgJGZ1bmMoJHByaW1lKTsKICAgICAgfQogICB9Cn0KCmZ1bmN0aW9uIGxhcmdlX3ByaW1lcygkdXB0bywgJGZ1bmMpewogICAvLyBUaGUgQWxnb3JpdGhtIGlzIGFkYXB0ZWQgZnJvbSBodHRwOi8vdy4uLmNvbnRlbnQtYXZhaWxhYmxlLXRvLWF1dGhvci1vbmx5Li4uay5jb20vfmpybS9wcmludHByaW1lcy5odG1sCiAgIC8vIFRoaXMgY29kZSBpcyBhIHRyYW5zbGF0ZWQgdmVyc2lvbiBvZiBBbmRyZWFzIFJhYWIncyAjbGFyZ2VQcmltZXNVcFRvOmRvOiBtZXRob2QKICAgLy8gd2hpY2ggd2FzIHdyaXR0ZW4gZm9yIHRoZSBTcXVlYWsgU21hbGx0YWxrIGVudmlyb25tZW50LgoKICAgJGlkeF9saW1pdCA9IGZsb29yKHNxcnQoJHVwdG8pKSArIDE7CiAgICRmbGFncyA9IGFycmF5X2ZpbGwoMCwgZmxvb3IoKCR1cHRvICsgMjMwOSkgLyAyMzEwKSAqIDYwICsgNjAsIDB4RkYpOwogICAkcHJpbWVzX3VwX3RvXzIzMTAgPSBhcnJheSgpOwogICBwcmltZXMoMjMxMCwgZnVuY3Rpb24oJHApIHVzZSgmJHByaW1lc191cF90b18yMzEwKXsgYXJyYXlfcHVzaCgkcHJpbWVzX3VwX3RvXzIzMTAsICRwKTsgfSk7CiAgICRtYXNrX2JpdF9pZHggPSBhcnJheV9maWxsKDAsIDIzMTAsIDApOwogICAkbWFza19iaXRfaWR4WzBdID0gMDsKICAgJG1hc2tfYml0X2lkeFsxXSA9IDE7CiAgICRiaXRfaWR4ID0gMTsKICAgZm9yKCAkaSA9IDA7ICRpIDwgNTsgJGkrKyApeyAkZnVuYygkcHJpbWVzX3VwX3RvXzIzMTBbJGldKTsgfQogICAkaWR4ID0gNTsKICAgZm9yKCAkbiA9IDI7ICRuIDwgMjMxMDsgJG4rKyApewogICAgICB3aGlsZSggJHByaW1lc191cF90b18yMzEwWyRpZHhdIDwgJG4gKXsgJGlkeCsrOyB9CiAgICAgIGlmKCAkbiA9PSAkcHJpbWVzX3VwX3RvXzIzMTBbJGlkeF0gKXsKICAgICAgICAgJG1hc2tfYml0X2lkeFskbl0gPSArKyRiaXRfaWR4OwogICAgICB9IGVsc2UgaWYoICRuICUgMiA9PSAwIHx8ICRuICUgMyA9PSAwIHx8ICRuICUgNSA9PSAwIHx8ICRuICUgNyA9PSAwIHx8ICRuICUgMTEgPT0gMCApewogICAgICAgICAkbWFza19iaXRfaWR4WyRuXSA9IDA7CiAgICAgIH0gZWxzZSB7CiAgICAgICAgICRtYXNrX2JpdF9pZHhbJG5dID0gKyskYml0X2lkeDsKICAgICAgfQogICB9CiAgIGZvciggJG4gPSAxMzsgJG4gPD0gJHVwdG87ICRuICs9IDIgKXsKICAgICAgaWYoICRtYXNrX2JpdCA9ICRtYXNrX2JpdF9pZHhbJG4gJSAyMzEwXSApewogICAgICAgICAkYnl0ZV9pZHggPSBmbG9vcigkbiAvIDIzMTApICogNjAgKyAoJG1hc2tfYml0LTEgPj4gMyk7CiAgICAgICAgICRiaXRfaWR4ID0gMSA8PCAoJG1hc2tfYml0ICYgNyk7CiAgICAgICAgIGlmKCAkZmxhZ3NbJGJ5dGVfaWR4XSAmICRiaXRfaWR4ICl7CiAgICAgICAgICAgICRmdW5jKCRuKTsKICAgICAgICAgICAgaWYoICRuIDwgJGlkeF9saW1pdCApewogICAgICAgICAgICAgICAkaWR4ID0gJG4gKiAkbjsKICAgICAgICAgICAgICAgaWYoICEoJGlkeCAmIDEpICl7ICRpZHggKz0gJG47IH0KICAgICAgICAgICAgICAgd2hpbGUoICRpZHggPD0gJHVwdG8gKXsKICAgICAgICAgICAgICAgICAgaWYoICRtYXNrX2JpdCA9ICRtYXNrX2JpdF9pZHhbJGlkeCAlIDIzMTBdICl7CiAgICAgICAgICAgICAgICAgICAgICRieXRlX2lkeCA9IGZsb29yKCRpZHggLyAyMzEwKSAqIDYwICsgKCRtYXNrX2JpdC0xID4+IDMpOwogICAgICAgICAgICAgICAgICAgICAkbWFza19iaXQgPSAyNTUgLSAoMSA8PCAoJG1hc2tfYml0ICYgNykpOwogICAgICAgICAgICAgICAgICAgICAkZmxhZ3NbJGJ5dGVfaWR4XSA9ICRmbGFnc1skYnl0ZV9pZHhdICYgJG1hc2tfYml0OwogICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICAgICRpZHggKz0gMiAqICRuOwogICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KICAgICAgICAgfQogICAgICB9CiAgIH0KfQoKJG1heCA9IGludHZhbCgkYXJndlsxXSk7CmlmKCAhJG1heCApeyAkbWF4ID0gMTAwOyB9CiRxID0gJGMgPSAwOwpwcmltZXMoJG1heCwgZnVuY3Rpb24oJHApIHVzZSgmJHEsICYkYyl7ICRxID0gJHA7ICRjKys7IH0pOwplY2hvICRxLCAiICIsICRjOwo=