Last active
August 29, 2015 14:01
-
-
Save marionette-of-u/b3a93becc32dfe968f29 to your computer and use it in GitHub Desktop.
enum_prime_number.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <algorithm> | |
| #include <vector> | |
| #include <deque> | |
| #include <iostream> | |
| #include <utility> | |
| #include <limits> | |
| #include <array> | |
| #include <functional> | |
| #include <cstdint> | |
| #include <cmath> | |
| #include <cstdio> | |
| namespace project_60{ | |
| template<class UInt = std::uint32_t, class DoubleUInt = std::uint64_t, class DoubleInt = std::int64_t, DoubleUInt BitNum = sizeof(UInt) * 8> | |
| struct quint{ | |
| template<DoubleUInt Count> | |
| struct make_bitmask{ | |
| static const DoubleUInt value = (static_cast<DoubleUInt>(1) << Count) | make_bitmask<Count - static_cast<DoubleUInt>(1)>::value; | |
| }; | |
| template<> | |
| struct make_bitmask<0>{ | |
| static const DoubleUInt value = static_cast<DoubleUInt>(1); | |
| }; | |
| static const DoubleUInt base_mask = make_bitmask<BitNum - 1>::value; | |
| UInt data[4]; | |
| quint(){ | |
| for(int i = 0; i < 4; ++i){ data[i] = 0; } | |
| } | |
| quint(const quint &other){ | |
| for(int i = 0; i < 4; ++i){ data[i] = other.data[i]; } | |
| } | |
| quint(quint &&other){ | |
| for(int i = 0; i < 4; ++i){ data[i] = other.data[i]; } | |
| } | |
| ~quint() = default; | |
| quint(int x){ | |
| data[0] = static_cast<UInt>(x); | |
| data[1] = data[2] = data[3] = 0; | |
| } | |
| quint(UInt x){ | |
| data[0] = x; | |
| data[1] = data[2] = data[3] = 0; | |
| } | |
| quint &operator =(const quint &other){ | |
| for(int i = 0; i < 4; ++i){ data[i] = other.data[i]; } | |
| return *this; | |
| } | |
| bool operator <(const quint &other) const{ | |
| for(int i = 3; i > -1; --i){ | |
| if(data[i] < other.data[i]){ return true; } | |
| } | |
| return false; | |
| } | |
| bool operator >(const quint &other) const{ | |
| return other < *this; | |
| } | |
| bool operator <=(const quint &other) const{ | |
| for(int i = 3; i > -1; --i){ | |
| if(data[i] < other.data[i]){ return true; } | |
| if(data[i] > other.data[i]){ return false; } | |
| } | |
| return true; | |
| } | |
| bool operator >=(const quint &other) const{ | |
| return other <= *this; | |
| } | |
| bool operator ==(const quint &other) const{ | |
| for(int i = 0; i < 4; ++i){ | |
| if(data[i] != other.data[i]){ return false; } | |
| } | |
| return true; | |
| } | |
| bool operator !=(const quint &other) const{ | |
| return !(*this == other); | |
| } | |
| quint add(const quint &other) const{ | |
| quint result; | |
| DoubleUInt c = 0; | |
| for(int i = 0; i < 4; ++i){ | |
| DoubleUInt v = static_cast<DoubleUInt>(data[i]) + static_cast<DoubleUInt>(other.data[i]) + c; | |
| result.data[i] = static_cast<UInt>(v & base_mask); | |
| c = v >> BitNum; | |
| } | |
| return result; | |
| } | |
| quint sub(const quint &other) const{ | |
| quint result; | |
| for(int i = 0; i < 4; ++i){ result.data[i] = ~other.data[i]; } | |
| DoubleUInt c = 1; | |
| for(int i = 0; i < 4; ++i){ | |
| DoubleUInt v = static_cast<DoubleUInt>(data[i]) + static_cast<DoubleUInt>(result.data[i]) + c; | |
| result.data[i] = static_cast<UInt>(v & base_mask); | |
| c = v >> BitNum; | |
| } | |
| return result; | |
| } | |
| quint mul(const quint &other) const{ | |
| UInt extended_data[8] = { 0 }; | |
| for(int i = 0; i < 4; ++i){ | |
| for(int j = 0; j < 4; ++j){ | |
| DoubleUInt c = static_cast<DoubleUInt>(data[i]) * static_cast<DoubleUInt>(other.data[j]); | |
| for(int k = 0; i + j + k < 4; ++k){ | |
| DoubleUInt v = static_cast<DoubleUInt>(extended_data[i + j + k]) + c; | |
| extended_data[i + j + k] = static_cast<UInt>(v & base_mask); | |
| c = v >> BitNum; | |
| } | |
| } | |
| } | |
| quint result; | |
| for(int i = 0; i < 4; ++i){ | |
| result.data[i] = extended_data[i]; | |
| } | |
| return result; | |
| } | |
| quint div(const quint &other) const{ | |
| quint r = *this, result; | |
| int n = degree(), m = other.degree(), i = n - m; | |
| UInt u = other.data[m - 1]; | |
| while(i >= 0){ | |
| int rd = r.degree(); | |
| if(rd == m + i){ | |
| result.data[i] = r.data[rd - 1] / u; | |
| r = r.sub(other.mul(result.data[i])); | |
| }else{ | |
| result.data[i] = 0; | |
| } | |
| --i; | |
| } | |
| return result; | |
| } | |
| quint rem(const quint &other) const{ | |
| return sub(other.mul(div(other))); | |
| } | |
| int degree() const{ | |
| int i; | |
| for(i = 4; i > 0; --i){ | |
| if(data[i - 1] > 0){ break; } | |
| } | |
| return i; | |
| } | |
| UInt lc() const{ return data[degree() - 1]; } | |
| }; | |
| template<class UInt, class DoubleUInt, class DoubleInt, DoubleUInt BitNum> | |
| quint<UInt, DoubleUInt, DoubleInt, BitNum> operator +( | |
| const quint<UInt, DoubleUInt, DoubleInt, BitNum> &lhs, | |
| const quint<UInt, DoubleUInt, DoubleInt, BitNum> &rhs | |
| ){ return lhs.add(rhs); } | |
| template<class UInt, class DoubleUInt, class DoubleInt, DoubleUInt BitNum> | |
| quint<UInt, DoubleUInt, DoubleInt, BitNum> operator -( | |
| const quint<UInt, DoubleUInt, DoubleInt, BitNum> &lhs, | |
| const quint<UInt, DoubleUInt, DoubleInt, BitNum> &rhs | |
| ){ return lhs.sub(rhs); } | |
| template<class UInt, class DoubleUInt, class DoubleInt, DoubleUInt BitNum> | |
| quint<UInt, DoubleUInt, DoubleInt, BitNum> operator *( | |
| const quint<UInt, DoubleUInt, DoubleInt, BitNum> &lhs, | |
| const quint<UInt, DoubleUInt, DoubleInt, BitNum> &rhs | |
| ){ return lhs.mul(rhs); } | |
| template<class UInt, class DoubleUInt, class DoubleInt, DoubleUInt BitNum> | |
| quint<UInt, DoubleUInt, DoubleInt, BitNum> operator /( | |
| const quint<UInt, DoubleUInt, DoubleInt, BitNum> &lhs, | |
| const quint<UInt, DoubleUInt, DoubleInt, BitNum> &rhs | |
| ){ return lhs.div(rhs); } | |
| template<class UInt, class DoubleUInt, class DoubleInt, DoubleUInt BitNum> | |
| quint<UInt, DoubleUInt, DoubleInt, BitNum> operator %( | |
| const quint<UInt, DoubleUInt, DoubleInt, BitNum> &lhs, | |
| const quint<UInt, DoubleUInt, DoubleInt, BitNum> &rhs | |
| ){ return lhs.rem(rhs); } | |
| #define PROJECT_60_QUINT_OPERATOR_OVERLOAD_FOR_BUILT_IN_TYPE(built_in_type, symbol, fn) \ | |
| template<class UInt, class DoubleUInt, class DoubleInt, DoubleUInt BitNum> \ | |
| quint<UInt, DoubleUInt, DoubleInt, BitNum> operator symbol( \ | |
| const quint<UInt, DoubleUInt, DoubleInt, BitNum> &lhs, \ | |
| const built_in_type &rhs \ | |
| ){ return lhs.fn(quint<UInt, DoubleUInt, DoubleInt, BitNum>(static_cast<unsigned>(rhs))); } \ | |
| template<class UInt, class DoubleUInt, class DoubleInt, DoubleUInt BitNum> \ | |
| quint<UInt, DoubleUInt, DoubleInt, BitNum> operator symbol( \ | |
| const built_in_type &lhs, \ | |
| const quint<UInt, DoubleUInt, DoubleInt, BitNum> &rhs \ | |
| ){ return quint<UInt, DoubleUInt, DoubleInt, BitNum>(static_cast<unsigned>(lhs)).fn(rhs); } | |
| PROJECT_60_QUINT_OPERATOR_OVERLOAD_FOR_BUILT_IN_TYPE(int, +, add); | |
| PROJECT_60_QUINT_OPERATOR_OVERLOAD_FOR_BUILT_IN_TYPE(int, -, sub); | |
| PROJECT_60_QUINT_OPERATOR_OVERLOAD_FOR_BUILT_IN_TYPE(int, *, mul); | |
| PROJECT_60_QUINT_OPERATOR_OVERLOAD_FOR_BUILT_IN_TYPE(int, /, div); | |
| PROJECT_60_QUINT_OPERATOR_OVERLOAD_FOR_BUILT_IN_TYPE(int, %, rem); | |
| PROJECT_60_QUINT_OPERATOR_OVERLOAD_FOR_BUILT_IN_TYPE(unsigned, +, add); | |
| PROJECT_60_QUINT_OPERATOR_OVERLOAD_FOR_BUILT_IN_TYPE(unsigned, -, sub); | |
| PROJECT_60_QUINT_OPERATOR_OVERLOAD_FOR_BUILT_IN_TYPE(unsigned, *, mul); | |
| PROJECT_60_QUINT_OPERATOR_OVERLOAD_FOR_BUILT_IN_TYPE(unsigned, /, div); | |
| PROJECT_60_QUINT_OPERATOR_OVERLOAD_FOR_BUILT_IN_TYPE(unsigned, %, rem); | |
| template<class UInt, class DoubleUInt, class DoubleInt, DoubleUInt BitNum> | |
| std::ostream &operator <<( | |
| std::ostream &os, | |
| const quint<UInt, DoubleUInt, DoubleInt, BitNum> &rhs | |
| ){ | |
| UInt sum = 0; | |
| for(int i = 0; i < 4; ++i){ sum |= rhs.data[i]; } | |
| if(sum == 0){ | |
| os << '0'; | |
| return os; | |
| } | |
| char stack[40] = { 0 }; | |
| int stack_count = 0; | |
| quint<UInt, DoubleUInt, DoubleInt, BitNum> t = rhs; | |
| while( | |
| [&](const quint<UInt, DoubleUInt, DoubleInt, BitNum> &v){ | |
| sum = 0; for(int i = 0; i < 4; ++i){ sum |= v.data[i]; } return sum > 0; | |
| }(t) | |
| ){ | |
| char a[4] = { 0 }; | |
| std::sprintf(a, "%d", t.rem(10).data[0]); | |
| t = t / 10; | |
| stack[stack_count++] = a[0]; | |
| } | |
| while(stack_count){ | |
| char a[2] = { stack[stack_count--], '\0' }; | |
| os << a; | |
| } | |
| return os; | |
| } | |
| //using qint = quint<std::uint32_t, std::uint64_t, std::int64_t, 32>; | |
| using qint = std::uint_fast32_t; | |
| struct end_of_elf{}; | |
| std::vector<qint> prime_table, composite_prime_table; | |
| void elf(std::size_t limit_num){ | |
| std::vector<qint> &prime_table(prime_table); | |
| prime_table.reserve(limit_num); | |
| composite_prime_table.reserve(limit_num / 2); | |
| std::size_t skip_idx = 0; | |
| qint line_limit = 1, n_line_limit, next; | |
| auto search = [&]( | |
| const qint &x, | |
| std::size_t idx_range_first, | |
| std::size_t idx_range_last, | |
| std::function<void(const qint&)> push_back | |
| ){ | |
| for(std::size_t i = idx_range_first; i < idx_range_last; ++i){ | |
| const qint &y = prime_table[i]; | |
| if(y * y > x){ | |
| push_back(x); | |
| if(prime_table.size() >= limit_num){ | |
| throw end_of_elf(); | |
| } | |
| break; | |
| } | |
| if((x % y) == 0){ break; } | |
| } | |
| }; | |
| std::function<void(std::size_t, std::size_t, qint)> composite_search; | |
| composite_search = [&]( | |
| std::size_t idx_range_first, | |
| std::size_t prime_idx, | |
| qint x | |
| ){ | |
| { | |
| qint y = x * prime_table[prime_idx]; | |
| { | |
| qint z = y + n_line_limit; | |
| if(z > next){ return; } | |
| search( | |
| z, | |
| idx_range_first, | |
| prime_table.size(), | |
| [&](const qint &p){ | |
| auto iter = std::lower_bound(composite_prime_table.begin(), composite_prime_table.end(), p); | |
| if(iter == composite_prime_table.end() || *iter != p){ | |
| composite_prime_table.insert(iter, p); | |
| } | |
| } | |
| ); | |
| } | |
| composite_search(idx_range_first, prime_idx, y); | |
| } | |
| if(prime_idx + 1 < prime_table.size()){ | |
| composite_search(idx_range_first, prime_idx + 1, x); | |
| composite_search(idx_range_first, prime_idx + 1, prime_table[prime_idx + 1]); | |
| } | |
| }; | |
| // bootstrap prime numbers for line-limit, p_1 = 2, p_2 = 3. | |
| prime_table.push_back(qint(2)); | |
| prime_table.push_back(qint(3)); | |
| // bootstrap prime number, for next line-limit, p_3 = 5. | |
| prime_table.push_back(qint(5)); | |
| for(; skip_idx < prime_table.size() - 1; ++skip_idx){ | |
| line_limit = line_limit * prime_table[skip_idx]; | |
| } | |
| for(; ; ){ | |
| next = line_limit * prime_table[skip_idx]; | |
| std::size_t s = prime_table.size(), composite_counter = 0; | |
| auto push_back = [&](const qint &x){ | |
| while(composite_counter < composite_prime_table.size() && composite_prime_table[composite_counter] < x){ | |
| search( | |
| composite_prime_table[composite_counter++], | |
| skip_idx, | |
| prime_table.size(), | |
| [&](const qint &y){ prime_table.push_back(y); } | |
| ); | |
| } | |
| if(composite_counter < composite_prime_table.size() && composite_prime_table[composite_counter] == x){ | |
| ++composite_counter; | |
| } | |
| prime_table.push_back(x); | |
| }; | |
| for(n_line_limit = line_limit; n_line_limit < next; n_line_limit = n_line_limit + line_limit){ | |
| search(n_line_limit + 1, skip_idx, prime_table.size(), push_back); | |
| for(std::size_t a = skip_idx; a < s; ++a){ | |
| composite_search(a, a, prime_table[a]); | |
| search(n_line_limit + prime_table[a], skip_idx, prime_table.size(), push_back); | |
| } | |
| } | |
| composite_prime_table.clear(); | |
| ++skip_idx; | |
| line_limit = next; | |
| next = line_limit * prime_table[skip_idx]; | |
| } | |
| return; | |
| } | |
| } | |
| #include <boost/timer.hpp> | |
| int main(){ | |
| boost::timer t; | |
| try{ | |
| project_60::elf(512); | |
| }catch(project_60::end_of_elf){ | |
| // end... | |
| } | |
| std::cout << project_60::prime_table.back() << std::endl; | |
| std::cout << t.elapsed() << std::endl; | |
| char a; | |
| std::cin >> a; | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment