Skip to main content

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.

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 HugeNat y 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 a bit_length().
  • Fuera de rango lanza IndexError.
  • ~x no está definido y lanza ValueError.
x = HugeNat(0b1101101)  # 109

x[0]    # 1 (LSB)
x[-1]   # 1 (MSB)
# x[100]  # IndexError

Slicing de bits

  • step en {None, 1} usa ruta rápida: normaliza como Python, recorta a [0, nbits] y recompacta para que el bit start pase 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 >= 0 o arrays 1D de limbs uint64 (little-endian). Valores negativos o dimensiones distintas lanzan ValueError.
  • 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hugenats-0.1.3.tar.gz (12.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

hugenats-0.1.3-py3-none-any.whl (8.4 kB view details)

Uploaded Python 3

File details

Details for the file hugenats-0.1.3.tar.gz.

File metadata

  • Download URL: hugenats-0.1.3.tar.gz
  • Upload date:
  • Size: 12.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for hugenats-0.1.3.tar.gz
Algorithm Hash digest
SHA256 dc57972ab6fa47bffb8f3fb5ded7551d3555049e2d3aebbe5e2d403c015cd23d
MD5 23282e7474e80b4be2dcd9bc1cbf144c
BLAKE2b-256 182815eb512eac6d8e951a7730fdbb34aebde87755315036f08ea36f57f039ad

See more details on using hashes here.

File details

Details for the file hugenats-0.1.3-py3-none-any.whl.

File metadata

  • Download URL: hugenats-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 8.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.12

File hashes

Hashes for hugenats-0.1.3-py3-none-any.whl
Algorithm Hash digest
SHA256 4ee7804945b9d7816958f4296d5e5532eff961d591b62f72ebb1efcf75b9db7a
MD5 365d9416eb250dc6e3f5e4ab981cc7e2
BLAKE2b-256 926daff633e64f7fd16e99f0bad9344291466fac131335fab821f4e3fada6eb4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page