# Path: commpy/utilities.py
# def dec2bitarray(in_number, bit_width):
#     """
#     Converts a positive integer or an array-like of positive integers to NumPy array of the specified size containing
#     bits (0 and 1).
# 
#     Parameters
#     ----------
#     in_number : int or array-like of int
#         Positive integer to be converted to a bit array.
# 
#     bit_width : int
#         Size of the output bit array.
# 
#     Returns
#     -------
#     bitarray : 1D ndarray of numpy.int8
#         Array containing the binary representation of all the input decimal(s).
# 
#     """
# 
#     if isinstance(in_number, (np.integer, int)):
#         return decimal2bitarray(in_number, bit_width).copy()
#     result = np.zeros(bit_width * len(in_number), np.int8)
#     for pox, number in enumerate(in_number):
#         result[pox * bit_width:(pox + 1) * bit_width] = decimal2bitarray(number, bit_width).copy()
#     return result
# 
# def bitarray2dec(in_bitarray):
#     """
#     Converts an input NumPy array of bits (0 and 1) to a decimal integer.
# 
#     Parameters
#     ----------
#     in_bitarray : 1D ndarray of ints
#         Input NumPy array of bits.
# 
#     Returns
#     -------
#     number : int
#         Integer representation of input bit array.
#     """
# 
#     number = 0
# 
#     for i in range(len(in_bitarray)):
#         number = number + in_bitarray[i] * pow(2, len(in_bitarray) - 1 - i)
# 
#     return number
# 
# def hamming_dist(in_bitarray_1, in_bitarray_2):
#     """
#     Computes the Hamming distance between two NumPy arrays of bits (0 and 1).
# 
#     Parameters
#     ----------
#     in_bit_array_1 : 1D ndarray of ints
#         NumPy array of bits.
# 
#     in_bit_array_2 : 1D ndarray of ints
#         NumPy array of bits.
# 
#     Returns
#     -------
#     distance : int
#         Hamming distance between input bit arrays.
#     """
# 
#     distance = np.bitwise_xor(in_bitarray_1, in_bitarray_2).sum()
# 
#     return distance
# 
# def euclid_dist(in_array1, in_array2):
#     """
#     Computes the squared euclidean distance between two NumPy arrays
# 
#     Parameters
#     ----------
#     in_array1 : 1D ndarray of floats
#         NumPy array of real values.
# 
#     in_array2 : 1D ndarray of floats
#         NumPy array of real values.
# 
#     Returns
#     -------
#     distance : float
#         Squared Euclidean distance between two input arrays.
#     """
#     distance = ((in_array1 - in_array2) * (in_array1 - in_array2)).sum()
# 
#     return distance


import functools
import math
import matplotlib.colors as mcolors
import matplotlib.patches as mpatches
import matplotlib.path as mpath
import matplotlib.pyplot as plt
import numpy as np
from warnings import warn
from matplotlib.collections import PatchCollection
from commpy.utilities import dec2bitarray, bitarray2dec, hamming_dist, euclid_dist
            # The first row is the input of each shift reg.
            shift_regs = np.empty((max_values_lign, self.k), np.int8)

            # Compute the entries in the next state table and the output table
            for current_state in range(self.number_states):
                for current_input in range(self.number_inputs):
                    current_state_array = dec2bitarray(current_state, self.total_memory)

                    # Set the first row as the input.
                    shift_regs[0] = dec2bitarray(current_input, self.k)

                    # Set the other rows based on the current_state
                    idx = 0
                    for idx_mem, mem in enumerate(memory):
                        shift_regs[1:mem+1, idx_mem] = current_state_array[idx:idx + mem]
                        idx += mem

                    # Compute the output table
                    outputs_array = np.einsum('ik,ikl->l', shift_regs, g_matrix_array) % 2
                    self.output_table[current_state, current_input] = bitarray2dec(outputs_array)

                    # Update the first line based on the feedback polynomial
                    np.einsum('ik,ilk->l', shift_regs, feedback_array, out=shift_regs[0])
                    shift_regs %= 2

                    # Update current state array and compute next state table
                    idx = 0
                    for idx_mem, mem in enumerate(memory):
                        current_state_array[idx:idx + mem] = shift_regs[:mem, idx_mem]
                        idx += mem

# Path: commpy/utilities.py
# def dec2bitarray(in_number, bit_width):
#     """
#     Converts a positive integer or an array-like of positive integers to NumPy array of the specified size containing
#     bits (0 and 1).
# 
#     Parameters
#     ----------
#     in_number : int or array-like of int
#         Positive integer to be converted to a bit array.
# 
#     bit_width : int
#         Size of the output bit array.
# 
#     Returns
#     -------
#     bitarray : 1D ndarray of numpy.int8
#         Array containing the binary representation of all the input decimal(s).
# 
#     """
# 
#     if isinstance(in_number, (np.integer, int)):
#         return decimal2bitarray(in_number, bit_width).copy()
#     result = np.zeros(bit_width * len(in_number), np.int8)
#     for pox, number in enumerate(in_number):
#         result[pox * bit_width:(pox + 1) * bit_width] = decimal2bitarray(number, bit_width).copy()
#     return result
# 
# def bitarray2dec(in_bitarray):
#     """
#     Converts an input NumPy array of bits (0 and 1) to a decimal integer.
# 
#     Parameters
#     ----------
#     in_bitarray : 1D ndarray of ints
#         Input NumPy array of bits.
# 
#     Returns
#     -------
#     number : int
#         Integer representation of input bit array.
#     """
# 
#     number = 0
# 
#     for i in range(len(in_bitarray)):
#         number = number + in_bitarray[i] * pow(2, len(in_bitarray) - 1 - i)
# 
#     return number
# 
# def hamming_dist(in_bitarray_1, in_bitarray_2):
#     """
#     Computes the Hamming distance between two NumPy arrays of bits (0 and 1).
# 
#     Parameters
#     ----------
#     in_bit_array_1 : 1D ndarray of ints
#         NumPy array of bits.
# 
#     in_bit_array_2 : 1D ndarray of ints
#         NumPy array of bits.
# 
#     Returns
#     -------
#     distance : int
#         Hamming distance between input bit arrays.
#     """
# 
#     distance = np.bitwise_xor(in_bitarray_1, in_bitarray_2).sum()
# 
#     return distance
# 
# def euclid_dist(in_array1, in_array2):
#     """
#     Computes the squared euclidean distance between two NumPy arrays
# 
#     Parameters
#     ----------
#     in_array1 : 1D ndarray of floats
#         NumPy array of real values.
# 
#     in_array2 : 1D ndarray of floats
#         NumPy array of real values.
# 
#     Returns
#     -------
#     distance : float
#         Squared Euclidean distance between two input arrays.
#     """
#     distance = ((in_array1 - in_array2) * (in_array1 - in_array2)).sum()
# 
#     return distance


# Path: commpy/channelcoding/convcode.py
import functools
import math
import matplotlib.colors as mcolors
import matplotlib.patches as mpatches
import matplotlib.path as mpath
import matplotlib.pyplot as plt
import numpy as np
from warnings import warn
from matplotlib.collections import PatchCollection
from commpy.utilities import dec2bitarray, bitarray2dec, hamming_dist, euclid_dist

            # The first row is the input of each shift reg.
            shift_regs = np.empty((max_values_lign, self.k), np.int8)

            # Compute the entries in the next state table and the output table
            for current_state in range(self.number_states):
                for current_input in range(self.number_inputs):
                    current_state_array = dec2bitarray(current_state, self.total_memory)

                    # Set the first row as the input.
                    shift_regs[0] = dec2bitarray(current_input, self.k)

                    # Set the other rows based on the current_state
                    idx = 0
                    for idx_mem, mem in enumerate(memory):
                        shift_regs[1:mem+1, idx_mem] = current_state_array[idx:idx + mem]
                        idx += mem

                    # Compute the output table
                    outputs_array = np.einsum('ik,ikl->l', shift_regs, g_matrix_array) % 2
                    self.output_table[current_state, current_input] = bitarray2dec(outputs_array)

                    # Update the first line based on the feedback polynomial
                    np.einsum('ik,ilk->l', shift_regs, feedback_array, out=shift_regs[0])
                    shift_regs %= 2

                    # Update current state array and compute next state table
                    idx = 0
                    for idx_mem, mem in enumerate(memory):
                        current_state_array[idx:idx + mem] = shift_regs[:mem, idx_mem]
                        idx += mem

                    self.next_state_table[current_state, current_input] = bitarray2dec(current_state_array)