Wrapper de int para numeros naturales grandes con slicing por bits
Project description
HugeNat
HugeNat es un wrapper ligero sobre int que mantiene la semántica de los enteros de Python para números naturales (ℕ₀) y añade indexado/slicing por bits, vistas NumPy y un núcleo listo para Numba.
Repositorio: https://github.com/nand0san/huge_nat
Instalación
pip install HugeNats
Creación rápida
import numpy as np
from hugenat import HugeNat
# Desde un entero no negativo
x = HugeNat(123456789)
# Desde limbs (uint64, little-endian: limb 0 es LSB)
limbs = np.array([0xFFFFFFFFFFFFFFFF, 0x1], dtype=np.uint64)
y = HugeNat(limbs)
# Desde una lista/tupla de enteros (se convierten a uint64 y se recortan ceros finales)
z = HugeNat([1, 2, 3])
API tipo int
int(x),bool(x),hash(x),str(x)reflejan al entero interno.- Métodos compatibles:
bit_length(),bit_count(),to_bytes(),from_bytes(). - Aritmética y bitwise devuelven siempre
HugeNaty rechazan resultados negativos en restas.
a = HugeNat(10)
b = HugeNat(7)
int(a + b) # 17
int(a * b) # 70
int(a // b) # 1
int(a % b) # 3
int(a << 3) # 80
int(a | b), int(a & b), int(a ^ b)
Indexado de bits
- Convención:
LSB = índice 0. Índices negativos son relativos abit_length(). - Fuera de rango lanza
IndexError. ~xno está definido y lanzaValueError.
x = HugeNat(0b1101101) # 109
x[0] # 1 (LSB)
x[-1] # 1 (MSB)
# x[100] # IndexError
Slicing de bits
stepen{None, 1}usa ruta rápida: normaliza como Python, recorta a[0, nbits]y recompacta para que el bitstartpase a ser el bit 0.- Cualquier otro
step(salvo 0) usa ruta general con semántica completa de slicing de listas y reempaquetado LSB-first. step == 0->ValueError.
x = HugeNat(0b1101101)
x[0:3] # bits 0..2 -> 0b101 (5)
x[2:5] # 0b110 (6)
x[0:7:2] # toma cada 2 bits -> 0b10011 (19)
x[5:0:-2] # slicing con paso negativo
Vista de bits como array
bits(order="msb->lsb" | "lsb->msb", length=None) devuelve np.ndarray de uint8.
x = HugeNat(0b1011)
np.asarray(x.bits()) # array([1, 0, 1, 1], dtype=uint8)
np.asarray(x.bits(order="lsb->msb")) # array([1, 1, 0, 1], dtype=uint8)
np.asarray(x.bits(length=8)) # padding a la izquierda: 00001011
Cadena de bits agrupados
bits_str(order="msb->lsb" | "lsb->msb", group=64, sep=" ") para depurar o mostrar.
x = HugeNat(0x0123456789ABCDEFFEDCBA9876543210)
x.bits_str(group=4) # grupos de 4 bits
x.bits_str(group=8) # grupos de 1 byte
x.bits_str(order="lsb->msb", group=8)
Bytes ida y vuelta
x = HugeNat(2**20 + 123)
length = (x.bit_length() + 7) // 8
b = x.to_bytes(length=length, byteorder="big", signed=False)
y = HugeNat.from_bytes(b, byteorder="big", signed=False)
assert int(y) == int(x)
Rotaciones de bits
Las rotaciones usan el ancho natural (bit_length()):
x = HugeNat(0b100101)
int(x.rotl(2)) # 0b010110
int(x.rotr(2)) # 0b011001
HugeNat(0).rotl(5) # -> HugeNat(0)
Núcleo Numba-friendly
to_core() devuelve siempre limbs: uint64[::1] (1D contiguo, little-endian por palabra; limb 0 contiene los bits 0..63) y nbits: int. from_core() reconstruye exactamente el mismo valor.
Ejemplo Numba (histograma/unique de nibbles de 4 bits, empezando en el LSB) con signatura estricta y retorno tipado. Observa que seen:uint8 y counts:uint32 requieren types.Tuple, no UniTuple.
import numpy as np
from numba import njit, types
x = HugeNat(2**127 + 0xF00D)
limbs, nbits = x.to_core()
# Asegurar contigüidad y tipos exactos para la signatura
limbs = np.ascontiguousarray(limbs, dtype=np.uint64)
nbits = np.int64(nbits)
RET = types.Tuple((types.Array(types.uint8, 1, "C"), types.Array(types.uint32, 1, "C")))
SIG = RET(types.Array(types.uint64, 1, "C"), types.int64)
@njit(SIG, cache=True)
def unique_nibbles_core(limbs, nbits):
counts = np.zeros(16, dtype=np.uint32)
seen = np.zeros(16, dtype=np.uint8)
if nbits <= 0 or limbs.size == 0:
return seen, counts
n_nibbles = nbits >> 2 # solo nibbles completos
for k in range(n_nibbles):
bitpos = k << 2 # desplaza 4 bits desde el LSB
limb_i = bitpos >> 6
off = bitpos & 63
x0 = limbs[limb_i]
if off <= 60:
nib = (x0 >> np.uint64(off)) & np.uint64(0xF)
else:
lo = x0 >> np.uint64(off)
hi = np.uint64(0)
if limb_i + 1 < limbs.size:
hi = limbs[limb_i + 1] << np.uint64(64 - off)
nib = (lo | hi) & np.uint64(0xF)
idx = int(nib)
counts[idx] += np.uint32(1)
seen[idx] = np.uint8(1)
return seen, counts
seen, counts = unique_nibbles_core(limbs, nbits)
unique_values = np.nonzero(seen)[0].astype(np.uint8)
# Vuelta al wrapper para seguir trabajando en Python
y = HugeNat.from_core(limbs, nbits)
assert int(y) == int(x)
unique_values, counts[unique_values]
Contrato de dominio
- Solo enteros
>= 0o arrays 1D de limbsuint64(little-endian). Valores negativos o dimensiones distintas lanzanValueError. - Los ceros de mayor peso se recortan automáticamente.
- Las restas que producirían negativos lanzan
ValueError.
Desarrollo
- Dependencias de desarrollo:
pytest,numpy. - Ejecuta la batería completa:
pytest -q.
Las demostraciones completas viven en HugeNat_demo.ipynb y cubren todos los ejemplos anteriores.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hugenats-0.1.5.tar.gz.
File metadata
- Download URL: hugenats-0.1.5.tar.gz
- Upload date:
- Size: 15.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a4b282082cbdefab18ccea9d54fbe946847cd19d608dedb1b4d69be0ee6fcf7f
|
|
| MD5 |
17239c3e48dd7b66d6e1fa9645a436de
|
|
| BLAKE2b-256 |
57f3b9a3e60afa1355e808b17ee7544e1b7e75a640efcd05a812e5fc3ebf27c3
|
File details
Details for the file hugenats-0.1.5-py3-none-any.whl.
File metadata
- Download URL: hugenats-0.1.5-py3-none-any.whl
- Upload date:
- Size: 9.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a3cf1e05d30a354f45bd76437701b7b5e2df6df3118cc1b893878cfde29835a2
|
|
| MD5 |
58ad350268b3f09ceb94cc7f7b25cbb3
|
|
| BLAKE2b-256 |
c45529295f3467883179dcd7bc39fbd1adf03517b97d51293fdbdb96664a21a0
|