#include <cstddef>
#include <iostream>
template<bool debug>
constexpr bool any_factors( std::size_t target, std::size_t start, std::size_t step ) {
if (debug)
{
std::cout << "Target: " << target << ", start:" << start*6 << ", step:" << step << "\n";
}
if (start*start*36 > target)
{
if (debug)
{
std::cout << "start*start> target, returning false\n";
}
return false;
}
if (step==1)
{
bool one_mod_6 = target%(start*6+1) == 0;
bool five_mod_6 = target%(start*6+5) == 0;
if (debug)
{
std::cout << "target%6k+1=" << one_mod_6 << "\n";
std::cout << "target%6k+5=" << five_mod_6 << "\n";
}
return one_mod_6 || five_mod_6;
}
bool first_half = any_factors<debug>(target, start, step/2);
bool second_half = any_factors<debug>(target, start+ step/2, (step+1)/2);
if (debug)
{
std::cout << "Halves are " << first_half << second_half << "\n;";
}
return first_half || second_half;
}
template<bool debug=false>
constexpr bool is_prime( std::size_t target ) {
// handle 2, 3 and 5:
return
target == 2 || target == 3 || target == 5 ||
(
target%2 != 0
&& target%3 != 0
&& target%5 != 0
&& !any_factors<debug>( target, 1, (target+5)/6 )
); // can make that upper bound a bit tighter, but I don't care
}
constexpr bool is_prime_dbg( std::size_t target ) {
return is_prime<true>(target);
}
int main() {
// 100103
std::cout << "5:" << is_prime(5) << "\n";
std::cout << "10:" << is_prime(10) << "\n";
std::cout << "13:" << is_prime(13) << "\n";
std::cout << "91:" << is_prime(91) << "\n";
std::cout << "97:" << is_prime(97) << "\n";
std::cout << "19*19:" << is_prime(19*19) << "\n";
std::cout << "100103:" << is_prime(100103) << "\n";
}
I2luY2x1ZGUgPGNzdGRkZWY+CiNpbmNsdWRlIDxpb3N0cmVhbT4KCnRlbXBsYXRlPGJvb2wgZGVidWc+CmNvbnN0ZXhwciBib29sIGFueV9mYWN0b3JzKCBzdGQ6OnNpemVfdCB0YXJnZXQsIHN0ZDo6c2l6ZV90IHN0YXJ0LCBzdGQ6OnNpemVfdCBzdGVwICkgewogIGlmIChkZWJ1ZykKICB7CglzdGQ6OmNvdXQgPDwgIlRhcmdldDogIiA8PCB0YXJnZXQgPDwgIiwgc3RhcnQ6IiA8PCBzdGFydCo2IDw8ICIsIHN0ZXA6IiA8PCBzdGVwIDw8ICJcbiI7CiAgfQogIGlmIChzdGFydCpzdGFydCozNiA+IHRhcmdldCkKICB7CgkgIGlmIChkZWJ1ZykKCSAgewoJICAJc3RkOjpjb3V0IDw8ICJzdGFydCpzdGFydD4gdGFyZ2V0LCByZXR1cm5pbmcgZmFsc2VcbiI7CgkgIH0KCSAgcmV0dXJuIGZhbHNlOwogIH0KICBpZiAoc3RlcD09MSkKICB7CiAgICBib29sIG9uZV9tb2RfNiA9IHRhcmdldCUoc3RhcnQqNisxKSA9PSAwOwogICAgYm9vbCBmaXZlX21vZF82ID0gdGFyZ2V0JShzdGFydCo2KzUpID09IDA7CiAgICBpZiAoZGVidWcpCiAgICB7CiAgICAJc3RkOjpjb3V0IDw8ICJ0YXJnZXQlNmsrMT0iIDw8IG9uZV9tb2RfNiA8PCAiXG4iOwogICAgCXN0ZDo6Y291dCA8PCAidGFyZ2V0JTZrKzU9IiA8PCBmaXZlX21vZF82IDw8ICJcbiI7CiAgICB9CiAgICByZXR1cm4gb25lX21vZF82IHx8IGZpdmVfbW9kXzY7CiAgfQoKICBib29sIGZpcnN0X2hhbGYgPSBhbnlfZmFjdG9yczxkZWJ1Zz4odGFyZ2V0LCBzdGFydCwgc3RlcC8yKTsKICBib29sIHNlY29uZF9oYWxmID0gYW55X2ZhY3RvcnM8ZGVidWc+KHRhcmdldCwgc3RhcnQrIHN0ZXAvMiwgKHN0ZXArMSkvMik7CiAgCiAgaWYgKGRlYnVnKQogIHsKCXN0ZDo6Y291dCA8PCAiSGFsdmVzIGFyZSAiIDw8IGZpcnN0X2hhbGYgPDwgc2Vjb25kX2hhbGYgPDwgIlxuOyI7CiAgfQogIHJldHVybiBmaXJzdF9oYWxmIHx8IHNlY29uZF9oYWxmOyAgCn0KdGVtcGxhdGU8Ym9vbCBkZWJ1Zz1mYWxzZT4KY29uc3RleHByIGJvb2wgaXNfcHJpbWUoIHN0ZDo6c2l6ZV90IHRhcmdldCApIHsKICAvLyBoYW5kbGUgMiwgMyBhbmQgNToKICByZXR1cm4gCiAgICB0YXJnZXQgPT0gMiB8fCB0YXJnZXQgPT0gMyB8fCB0YXJnZXQgPT0gNSB8fAogICAgKAogICAgICB0YXJnZXQlMiAhPSAwCiAgICAgICYmIHRhcmdldCUzICE9IDAKICAgICAgJiYgdGFyZ2V0JTUgIT0gMAogICAgICAmJiAhYW55X2ZhY3RvcnM8ZGVidWc+KCB0YXJnZXQsIDEsICh0YXJnZXQrNSkvNiApCiAgICApOyAvLyBjYW4gbWFrZSB0aGF0IHVwcGVyIGJvdW5kIGEgYml0IHRpZ2h0ZXIsIGJ1dCBJIGRvbid0IGNhcmUKfQpjb25zdGV4cHIgYm9vbCBpc19wcmltZV9kYmcoIHN0ZDo6c2l6ZV90IHRhcmdldCApIHsKICAgIHJldHVybiBpc19wcmltZTx0cnVlPih0YXJnZXQpOwp9CmludCBtYWluKCkgewogICAgLy8gMTAwMTAzIAogICAgc3RkOjpjb3V0IDw8ICI1OiIgPDwgaXNfcHJpbWUoNSkgPDwgIlxuIjsKICAgIHN0ZDo6Y291dCA8PCAiMTA6IiA8PCBpc19wcmltZSgxMCkgPDwgIlxuIjsKICAgIHN0ZDo6Y291dCA8PCAiMTM6IiA8PCBpc19wcmltZSgxMykgPDwgIlxuIjsKICAgIHN0ZDo6Y291dCA8PCAiOTE6IiA8PCBpc19wcmltZSg5MSkgPDwgIlxuIjsKICAgIHN0ZDo6Y291dCA8PCAiOTc6IiA8PCBpc19wcmltZSg5NykgPDwgIlxuIjsKICAgIHN0ZDo6Y291dCA8PCAiMTkqMTk6IiA8PCBpc19wcmltZSgxOSoxOSkgPDwgIlxuIjsKICAgIHN0ZDo6Y291dCA8PCAiMTAwMTAzOiIgPDwgaXNfcHJpbWUoMTAwMTAzKSA8PCAiXG4iOwp9