A performant NumPy extension for Galois fields and their applications
—
Package configuration options and type system for enhanced development experience. This module provides global settings for output formatting and comprehensive type hints for improved code clarity and IDE support.
Global print options for controlling how field arrays and polynomials are displayed, with both permanent settings and temporary context managers.
def set_printoptions(**kwargs):
"""
Set global print options for field arrays.
Parameters:
- coeffs (str, optional): Coefficient display format
- "int": Display as integers (default)
- "poly": Display as polynomial representation
- "power": Display as powers of primitive element
- details (bool, optional): Show detailed field information, default True
- precision (int, optional): Precision for floating point display
- threshold (int, optional): Array size threshold for summarization
- edgeitems (int, optional): Number of edge items in summarized arrays
- linewidth (int, optional): Character width for line wrapping
- suppress (bool, optional): Suppress small floating point values
"""
def get_printoptions():
"""
Get current global print options.
Returns:
dict: Current print option settings
"""
def printoptions(**kwargs):
"""
Context manager for temporary print option changes.
Parameters: Same as set_printoptions()
Returns:
Context manager that temporarily modifies print options
Example:
with galois.printoptions(coeffs="poly"):
print(field_array) # Uses polynomial representation
# Reverts to previous settings after context
"""Comprehensive type system providing type hints and aliases for improved code clarity, IDE support, and static type checking.
# Import the typing module
import galois.typing
# Core type aliases for field elements and arrays
ElementLike = Union[int, np.integer, FieldArray]
"""Type alias for objects that can be coerced to field elements."""
IterableLike = Union[Iterable[ElementLike], Iterable[Iterable[ElementLike]]]
"""Type alias for iterable objects that can be coerced to field arrays."""
ArrayLike = Union[FieldArray, IterableLike, ElementLike]
"""Type alias for objects that can be coerced to field arrays."""
ShapeLike = Union[int, Sequence[int]]
"""Type alias for objects that can be coerced to array shapes."""
DTypeLike = Union[np.dtype, type, str]
"""Type alias for objects that can be coerced to NumPy dtypes."""
PolyLike = Union[Poly, ArrayLike, str, int]
"""Type alias for objects that can be coerced to polynomials."""import galois
import numpy as np
# Create a finite field
GF = galois.GF(2**4)
x = GF([1, 2, 3, 4, 5])
# Default integer representation
print("Default (int) representation:")
print(x)
# Change to polynomial representation
galois.set_printoptions(coeffs="poly")
print("\nPolynomial representation:")
print(x)
# Change to power representation
galois.set_printoptions(coeffs="power")
print("\nPower representation:")
print(x)
# Reset to default
galois.set_printoptions(coeffs="int")
print("\nBack to integer representation:")
print(x)import galois
GF = galois.GF(3**3)
poly = galois.Poly([1, 2, 0, 1], field=GF)
array = GF([5, 10, 15, 20])
print("Default settings:")
print(f"Polynomial: {poly}")
print(f"Array: {array}")
# Temporary change to polynomial representation
with galois.printoptions(coeffs="poly"):
print("\nInside context (poly representation):")
print(f"Polynomial: {poly}")
print(f"Array: {array}")
print("\nAfter context (back to default):")
print(f"Polynomial: {poly}")
print(f"Array: {array}")
# Multiple temporary changes
with galois.printoptions(coeffs="power", details=False):
print("\nPower representation without details:")
print(f"Array: {array}")import galois
from galois.typing import ElementLike, ArrayLike, PolyLike
from typing import Union
import numpy as np
def create_field_array(data: ArrayLike, field_order: int) -> galois.FieldArray:
"""
Create field array with proper type hints.
Args:
data: Input data coercible to field array
field_order: Order of the finite field
Returns:
Field array over GF(field_order)
"""
GF = galois.GF(field_order)
return GF(data)
def polynomial_from_input(coeffs: PolyLike, field: type = None) -> galois.Poly:
"""
Create polynomial from various input types.
Args:
coeffs: Polynomial coefficients (various formats accepted)
field: Finite field class
Returns:
Polynomial over specified field
"""
if isinstance(coeffs, str):
# Handle string representation
return galois.Poly.Str(coeffs, field=field)
elif isinstance(coeffs, int):
# Handle integer representation
return galois.Poly.Int(coeffs, field=field)
else:
# Handle array-like coefficients
return galois.Poly(coeffs, field=field)
# Usage examples with type checking
GF16 = galois.GF(16)
# These all satisfy ArrayLike
array1 = create_field_array([1, 2, 3], 16) # List input
array2 = create_field_array(np.array([4, 5, 6]), 16) # NumPy array input
array3 = create_field_array(GF16([7, 8, 9]), 16) # Field array input
# These all satisfy PolyLike
poly1 = polynomial_from_input([1, 0, 1], GF16) # List coefficients
poly2 = polynomial_from_input("x^2 + 1", GF16) # String representation
poly3 = polynomial_from_input(5, GF16) # Integer representation
print(f"Arrays created: {array1}, {array2}, {array3}")
print(f"Polynomials created: {poly1}, {poly2}, {poly3}")import galois
import numpy as np
# Create larger field for demonstration
GF = galois.GF(2**8)
# Create large array to test threshold settings
large_array = GF.Random(20)
# Default printing
print("Default printing:")
print(large_array)
# Modify threshold and edge items
galois.set_printoptions(threshold=10, edgeitems=2)
print("\nWith threshold=10, edgeitems=2:")
print(large_array)
# Show field details
galois.set_printoptions(details=True)
print(f"\nWith details=True:")
print(f"Field info: {GF}")
# Polynomial representation with custom formatting
galois.set_printoptions(coeffs="poly", linewidth=50)
poly_array = GF([1, 2, 3, 4, 5, 6, 7, 8])
print(f"\nPolynomial representation with linewidth=50:")
print(poly_array)
# Get current settings
current_options = galois.get_printoptions()
print(f"\nCurrent print options: {current_options}")
# Reset to defaults
galois.set_printoptions(coeffs="int", threshold=1000, edgeitems=3, details=True, linewidth=75)import galois
from galois.typing import *
from typing import List, Tuple, Optional
def batch_encode_messages(
messages: List[ArrayLike],
field_order: int,
code_params: Tuple[int, int]
) -> List[galois.FieldArray]:
"""
Batch encode multiple messages using Reed-Solomon code.
Args:
messages: List of message arrays
field_order: Finite field order
code_params: (n, k) code parameters
Returns:
List of encoded codewords
"""
n, k = code_params
rs = galois.ReedSolomon(n, k)
encoded = []
for msg in messages:
# Convert to proper field array
field_msg = rs.field(msg)
codeword = rs.encode(field_msg)
encoded.append(codeword)
return encoded
def analyze_polynomial(
poly_input: PolyLike,
field_class: Optional[type] = None
) -> dict:
"""
Analyze polynomial properties with flexible input handling.
Args:
poly_input: Polynomial in various formats
field_class: Field class for polynomial
Returns:
Dictionary of analysis results
"""
# Convert input to polynomial
if isinstance(poly_input, galois.Poly):
poly = poly_input
else:
poly = galois.Poly(poly_input, field=field_class)
# Perform analysis
analysis = {
"degree": poly.degree,
"is_monic": poly.is_monic(),
"is_irreducible": poly.is_irreducible(),
"coefficients": poly.coeffs,
"field": poly.field.name,
}
return analysis
# Example usage with proper types
messages = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
encoded_batch = batch_encode_messages(messages, 16, (15, 9))
print(f"Encoded {len(encoded_batch)} messages")
# Analyze different polynomial inputs
poly_analysis1 = analyze_polynomial([1, 0, 1, 1]) # List coefficients
poly_analysis2 = analyze_polynomial("x^3 + x + 1") # String format
print(f"Analysis 1: {poly_analysis1}")
print(f"Analysis 2: {poly_analysis2}")Install with Tessl CLI
npx tessl i tessl/pypi-galois