| 
 | 1 | +{  | 
 | 2 | + "cells": [  | 
 | 3 | + {  | 
 | 4 | + "cell_type": "code",  | 
 | 5 | + "execution_count": 1,  | 
 | 6 | + "metadata": {  | 
 | 7 | + "collapsed": true  | 
 | 8 | + },  | 
 | 9 | + "outputs": [],  | 
 | 10 | + "source": [  | 
 | 11 | + "%load_ext Cython"  | 
 | 12 | + ]  | 
 | 13 | + },  | 
 | 14 | + {  | 
 | 15 | + "cell_type": "markdown",  | 
 | 16 | + "metadata": {},  | 
 | 17 | + "source": [  | 
 | 18 | + "## algorithm"  | 
 | 19 | + ]  | 
 | 20 | + },  | 
 | 21 | + {  | 
 | 22 | + "cell_type": "code",  | 
 | 23 | + "execution_count": 2,  | 
 | 24 | + "metadata": {  | 
 | 25 | + "collapsed": true  | 
 | 26 | + },  | 
 | 27 | + "outputs": [],  | 
 | 28 | + "source": [  | 
 | 29 | + "%%cython\n",  | 
 | 30 | + "\n",  | 
 | 31 | + "from libc.stdlib cimport malloc, free\n",  | 
 | 32 | + "\n",  | 
 | 33 | + "DEF LIMIT = 1024 * 31\n",  | 
 | 34 | + "DEF PRIME = 1024 * 4\n",  | 
 | 35 | + "DEF SIEVE = 1024 * 32\n",  | 
 | 36 | + "\n",  | 
 | 37 | + "cdef inline int imin(int a, int b) nogil:\n",  | 
 | 38 | + " return a if a < b else b\n",  | 
 | 39 | + "\n",  | 
 | 40 | + "cdef inline int memset(char *p, int n) nogil:\n",  | 
 | 41 | + " cdef:\n",  | 
 | 42 | + " short *q = <short *>p\n",  | 
 | 43 | + " int i, j = 0\n",  | 
 | 44 | + "\n",  | 
 | 45 | + " for i in range((n + 1) >> 1):\n",  | 
 | 46 | + " j += q[i]\n",  | 
 | 47 | + " q[i] = 0x0100\n",  | 
 | 48 | + "\n",  | 
 | 49 | + " return j >> 8\n",  | 
 | 50 | + "\n",  | 
 | 51 | + "cdef int naive_sieve(char *sieve, int *primes, int *offsets, int n) nogil:\n",  | 
 | 52 | + " cdef int i, j\n",  | 
 | 53 | + "\n",  | 
 | 54 | + " memset(sieve, n)\n",  | 
 | 55 | + "\n",  | 
 | 56 | + " for i in range(3, n, 2):\n",  | 
 | 57 | + " if sieve[i]:\n",  | 
 | 58 | + " j = i * i\n",  | 
 | 59 | + " while j < n:\n",  | 
 | 60 | + " sieve[j] = 0\n",  | 
 | 61 | + " j += i << 1\n",  | 
 | 62 | + "\n",  | 
 | 63 | + " primes[0] = i\n",  | 
 | 64 | + " offsets[0] = j\n",  | 
 | 65 | + " primes += 1\n",  | 
 | 66 | + " offsets += 1\n",  | 
 | 67 | + "\n",  | 
 | 68 | + " primes[0] = 0\n",  | 
 | 69 | + " offsets[0] = 0\n",  | 
 | 70 | + "\n",  | 
 | 71 | + " return memset(sieve, n)\n",  | 
 | 72 | + "\n",  | 
 | 73 | + "cdef int segmented_sieve(char *sieve, int *primes, int *offsets, int k, int n) nogil:\n",  | 
 | 74 | + " cdef int i\n",  | 
 | 75 | + "\n",  | 
 | 76 | + " while primes[0]:\n",  | 
 | 77 | + " i = offsets[0] - k\n",  | 
 | 78 | + " while i < n:\n",  | 
 | 79 | + " sieve[i] = 0\n",  | 
 | 80 | + " i += primes[0] << 1\n",  | 
 | 81 | + " offsets[0] = i + k\n",  | 
 | 82 | + "\n",  | 
 | 83 | + " primes += 1\n",  | 
 | 84 | + " offsets += 1\n",  | 
 | 85 | + "\n",  | 
 | 86 | + " return memset(sieve, n)\n",  | 
 | 87 | + "\n",  | 
 | 88 | + "cpdef int eratosthenes(int n) nogil:\n",  | 
 | 89 | + " cdef:\n",  | 
 | 90 | + " char *sieve\n",  | 
 | 91 | + " int *primes\n",  | 
 | 92 | + " int *offsets\n",  | 
 | 93 | + " int k, total\n",  | 
 | 94 | + "\n",  | 
 | 95 | + " if n > LIMIT * LIMIT:\n",  | 
 | 96 | + " return -1\n",  | 
 | 97 | + "\n",  | 
 | 98 | + " sieve = <char *>malloc(SIEVE)\n",  | 
 | 99 | + " primes = <int *>malloc(PRIME * sizeof(int))\n",  | 
 | 100 | + " offsets = <int *>malloc(PRIME * sizeof(int))\n",  | 
 | 101 | + "\n",  | 
 | 102 | + " total = naive_sieve(sieve, primes, offsets, imin(n, LIMIT))\n",  | 
 | 103 | + "\n",  | 
 | 104 | + " memset(sieve, SIEVE)\n",  | 
 | 105 | + " k = LIMIT\n",  | 
 | 106 | + " n -= LIMIT\n",  | 
 | 107 | + "\n",  | 
 | 108 | + " while n > 0:\n",  | 
 | 109 | + " total += segmented_sieve(sieve, primes, offsets, k, imin(n, SIEVE))\n",  | 
 | 110 | + " k += SIEVE\n",  | 
 | 111 | + " n -= SIEVE\n",  | 
 | 112 | + "\n",  | 
 | 113 | + " free(sieve)\n",  | 
 | 114 | + " free(primes)\n",  | 
 | 115 | + " free(offsets)\n",  | 
 | 116 | + "\n",  | 
 | 117 | + " return total"  | 
 | 118 | + ]  | 
 | 119 | + },  | 
 | 120 | + {  | 
 | 121 | + "cell_type": "markdown",  | 
 | 122 | + "metadata": {},  | 
 | 123 | + "source": [  | 
 | 124 | + "## run"  | 
 | 125 | + ]  | 
 | 126 | + },  | 
 | 127 | + {  | 
 | 128 | + "cell_type": "code",  | 
 | 129 | + "execution_count": 3,  | 
 | 130 | + "metadata": {},  | 
 | 131 | + "outputs": [  | 
 | 132 | + {  | 
 | 133 | + "name": "stdout",  | 
 | 134 | + "output_type": "stream",  | 
 | 135 | + "text": [  | 
 | 136 | + "primes below 10**1: 4\n",  | 
 | 137 | + "primes below 10**2: 25\n",  | 
 | 138 | + "primes below 10**3: 168\n",  | 
 | 139 | + "primes below 10**4: 1229\n",  | 
 | 140 | + "primes below 10**5: 9592\n",  | 
 | 141 | + "primes below 10**6: 78498\n",  | 
 | 142 | + "primes below 10**7: 664579\n",  | 
 | 143 | + "primes below 10**8: 5761455\n",  | 
 | 144 | + "primes below 10**9: 50847534\n"  | 
 | 145 | + ]  | 
 | 146 | + }  | 
 | 147 | + ],  | 
 | 148 | + "source": [  | 
 | 149 | + "for i in range(1, 10):\n",  | 
 | 150 | + " print('primes below 10**%d: %d' % (i, eratosthenes(10**i)))"  | 
 | 151 | + ]  | 
 | 152 | + },  | 
 | 153 | + {  | 
 | 154 | + "cell_type": "markdown",  | 
 | 155 | + "metadata": {},  | 
 | 156 | + "source": [  | 
 | 157 | + "## timeit"  | 
 | 158 | + ]  | 
 | 159 | + },  | 
 | 160 | + {  | 
 | 161 | + "cell_type": "code",  | 
 | 162 | + "execution_count": 4,  | 
 | 163 | + "metadata": {},  | 
 | 164 | + "outputs": [  | 
 | 165 | + {  | 
 | 166 | + "name": "stdout",  | 
 | 167 | + "output_type": "stream",  | 
 | 168 | + "text": [  | 
 | 169 | + "10000 loops, best of 3: 56.6 µs per loop\n",  | 
 | 170 | + "1000 loops, best of 3: 574 µs per loop\n",  | 
 | 171 | + "100 loops, best of 3: 6.07 ms per loop\n",  | 
 | 172 | + "10 loops, best of 3: 68.4 ms per loop\n",  | 
 | 173 | + "1 loop, best of 3: 863 ms per loop\n"  | 
 | 174 | + ]  | 
 | 175 | + }  | 
 | 176 | + ],  | 
 | 177 | + "source": [  | 
 | 178 | + "%timeit eratosthenes(1024 * 31)\n",  | 
 | 179 | + "%timeit eratosthenes(10**6)\n",  | 
 | 180 | + "%timeit eratosthenes(10**7)\n",  | 
 | 181 | + "%timeit eratosthenes(10**8)\n",  | 
 | 182 | + "%timeit eratosthenes(10**9)"  | 
 | 183 | + ]  | 
 | 184 | + },  | 
 | 185 | + {  | 
 | 186 | + "cell_type": "code",  | 
 | 187 | + "execution_count": null,  | 
 | 188 | + "metadata": {  | 
 | 189 | + "collapsed": true  | 
 | 190 | + },  | 
 | 191 | + "outputs": [],  | 
 | 192 | + "source": []  | 
 | 193 | + }  | 
 | 194 | + ],  | 
 | 195 | + "metadata": {  | 
 | 196 | + "kernelspec": {  | 
 | 197 | + "display_name": "Python 3",  | 
 | 198 | + "language": "python",  | 
 | 199 | + "name": "python3"  | 
 | 200 | + },  | 
 | 201 | + "language_info": {  | 
 | 202 | + "codemirror_mode": {  | 
 | 203 | + "name": "ipython",  | 
 | 204 | + "version": 3  | 
 | 205 | + },  | 
 | 206 | + "file_extension": ".py",  | 
 | 207 | + "mimetype": "text/x-python",  | 
 | 208 | + "name": "python",  | 
 | 209 | + "nbconvert_exporter": "python",  | 
 | 210 | + "pygments_lexer": "ipython3",  | 
 | 211 | + "version": "3.6.1"  | 
 | 212 | + }  | 
 | 213 | + },  | 
 | 214 | + "nbformat": 4,  | 
 | 215 | + "nbformat_minor": 2  | 
 | 216 | +}  | 
0 commit comments