█▀▀▀▀▀█ ▄ █ ▀█▄▄██▀▀▄ █▀▀▀▀▀█ █ ███ █ ▄▄▄ █▄█▄▄▄▀█▀ █ ███ █ █ ▀▀▀ █ ▄█ ▄▄▀▄▄█▄█▀▀ █ ▀▀▀ █ ▀▀▀▀▀▀▀ ▀▄█▄▀ ▀▄▀ ▀ █ ▀▀▀▀▀▀▀ ██▀██ ▀▀▀▀▄▀▄█ ▄█▄▄▄█▄█▄▀ ▀▄ ▄████▀ ▀ ▄ ██▄▀ ▀▀ ▀▀▄ ▄ ▀ ▀▀▄▀ ▄▀▀ ▀▀█ ▄█▄▄▄▄▄▄▄▀▀ ▄ ▀█▄██▀▄ ▀ █▀▀ ▀▄ ▄█▄█ ▄▀▀▄ ▄██ ▄▀██▄ ▀█▀█▀▄██▄▄▄▄█▄▀█ ▄ █ ▀ ██▀▀ █▄ ▄ █▀█▀ ▄██▄█ ▀▄ ▀ ▀▀ ▀▀██▄█ ▀█ ▀▀▀█▀▀▀█▄███ █▀▀▀▀▀█ ▀▀▄ █▀▄▀▀▀███ ▀ █▀▀▄▄ █ ███ █ █▄▀▄ ▀█▀▀▀▀▄▀▀▀▀▀▄█▄█ █ ▀▀▀ █ █ ▄ ▀▀ █▀▄▀▀███▀█ ▀▀▀▀▀▀▀ ▀▀ ▀▀▀ ▀▀▀▀▀ ▀ ▀ ▀
import math
def sieve(n):
numbers = list(range(2, n + 1))
for i in range(2, int(math.sqrt(n))):
if numbers[i - 2] != 0:
for j in range(i * i, n + 1, i):
numbers[j - 2] = 0
return [x for x in numbers if x != 0]
>>> sieve(5)
[2, 3, 5]
>>> sieve(20)
[2, 3, 5, 7, 11, 13, 17, 19]
static PyObject *sieve_impl(PyObject *self, PyObject *max_n) {
size_t n;
if ((n = PyLong_AsSize_t(max_n)) == (size_t)-1 && PyErr_Occurred()) { return NULL; }
// Populate the C array
int *sieve = malloc((n - 1) * sizeof(int));
if (sieve == NULL) {
PyErr_NoMemory(); // raise MemoryError()
return NULL;
}
for (size_t i = 2; i < n + 1; ++i) { sieve[i - 2] = (int)i; }
// Sieve out composite numbers
size_t lim = (size_t)sqrt((double)n);
for (size_t i = 2; i < lim; ++i) {
if (sieve[i - 2] != 0) {
for (size_t j = (i * i); j < (n + 1); j += i) {
sieve[j - 2] = 0;
}
}
}
// Convert to Python list
size_t num_primes = 0; // Calculate total size of list
for (size_t i = 0; i < n - 1; ++i) { if (sieve[i]) { num_primes++; } }
PyObject *rv = PyList_New(num_primes);
if (rv == NULL) { goto cleanup; }
PyObject *obj = NULL;
size_t j = 0;
for (size_t i = 0; i < n - 1; ++i) {
if (!sieve[i]) { continue; }
if ((obj = PyLong_FromLong(sieve[i])) == NULL || // int -> Py int
PyList_SetItem(rv, j++, obj)) { // rv[i] = obj
Py_DECREF(rv); rv = NULL; // On error, remove list
goto cleanup;
}
}
cleanup:
free(sieve);
return rv;
}
n | Python | C (Extensión) | Razón |
1 | 387.5 ns | 54.6 ns | 7 |
100 | 5.9 μs | 254 ns | 23 |
1000 | 72.6 μs | 2.31 μs | 31 |
100000 | 10 ms | 290 μs | 34 |
1000000 | 132 ms | 3.91 ms | 34 |
Python 🤝 Rust
/// Usa la criba de Eratóstenes para calcular los números primos
/// menores o iguales a `n`
#[pyfunction]
fn sieve(n: usize) -> Vec<u32> {
let mut sieve: Vec<u32> = (2..=(n as u32)).collect();
let lim: usize = (n as f64).sqrt() as usize;
for i in 2..=lim {
if sieve[i - 2] != 0 {
let mut j = i * i;
while j < n + 1 {
sieve[j - 2] = 0;
j += i;
}
}
}
sieve.retain(|&x| x != 0);
sieve
}
/// Esta es la documentación del módulo
#[pymodule]
fn charla_flisol_rust(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(sieve, m)?)?;
Ok(())
}
n | Python | C | PyO3 |
---|---|---|---|
1 | 387.5 ns | 54.6 ns | 91.2 ns |
100 | 5.9 µs | 254 ns | 287 ns |
1000 | 72.6 µs | 2.31 µs | 2.12 µs |
100000 | 10 ms | 290 µs | 264 µs |
1000000 | 132 ms | 3.91 ms | 3.69 ms |