# Path: commpy/channelcoding/convcode.py
# def conv_encode(message_bits, trellis, termination = 'term', puncture_matrix=None):
#     """
#     Encode bits using a convolutional code.
#     Parameters
#     ----------
#     message_bits : 1D ndarray containing {0, 1}
#         Stream of bits to be convolutionally encoded.
#     trellis: pre-initialized Trellis structure.
#     termination: {'cont', 'term'}, optional
#         Create ('term') or not ('cont') termination bits.
#     puncture_matrix: 2D ndarray containing {0, 1}, optional
#         Matrix used for the puncturing algorithm
#     Returns
#     -------
#     coded_bits : 1D ndarray containing {0, 1}
#         Encoded bit stream.
#     """
# 
#     k = trellis.k
#     n = trellis.n
#     total_memory = trellis.total_memory
#     rate = float(k)/n
#     
#     code_type = trellis.code_type
# 
#     if puncture_matrix is None:
#         puncture_matrix = np.ones((trellis.k, trellis.n))
# 
#     number_message_bits = np.size(message_bits)
#     
#     if termination == 'cont':
#         inbits = message_bits
#         number_inbits = number_message_bits
#         number_outbits = int(number_inbits/rate)
#     else:
#         # Initialize an array to contain the message bits plus the truncation zeros
#         if code_type == 'rsc':
#             inbits = message_bits
#             number_inbits = number_message_bits
#             number_outbits = int((number_inbits + k * total_memory)/rate)
#         else:
#             number_inbits = number_message_bits + total_memory + total_memory % k
#             inbits = np.zeros(number_inbits, 'int')
#             # Pad the input bits with M zeros (L-th terminated truncation)
#             inbits[0:number_message_bits] = message_bits
#             number_outbits = int(number_inbits/rate)
# 
#     outbits = np.zeros(number_outbits, 'int')
#     if puncture_matrix is not None:
#         p_outbits = np.zeros(number_outbits, 'int')
#     else:
#         p_outbits = np.zeros(int(number_outbits*
#             puncture_matrix[0:].sum()/np.size(puncture_matrix, 1)), 'int')
#     next_state_table = trellis.next_state_table
#     output_table = trellis.output_table
# 
#     # Encoding process - Each iteration of the loop represents one clock cycle
#     current_state = 0
#     j = 0
# 
#     for i in range(int(number_inbits/k)): # Loop through all input bits
#         current_input = bitarray2dec(inbits[i*k:(i+1)*k])
#         current_output = output_table[current_state][current_input]
#         outbits[j*n:(j+1)*n] = dec2bitarray(current_output, n)
#         current_state = next_state_table[current_state][current_input]
#         j += 1
# 
#     if code_type == 'rsc' and termination == 'term':
#         term_bits = dec2bitarray(current_state, trellis.total_memory)
#         term_bits = term_bits[::-1]
#         for i in range(trellis.total_memory):
#             current_input = bitarray2dec(term_bits[i*k:(i+1)*k])
#             current_output = output_table[current_state][current_input]
#             outbits[j*n:(j+1)*n] = dec2bitarray(current_output, n)
#             current_state = next_state_table[current_state][current_input]
#             j += 1
# 
#     j = 0
#     for i in range(number_outbits):
#         if puncture_matrix[0][i % np.size(puncture_matrix, 1)] == 1:
#             p_outbits[j] = outbits[i]
#             j = j + 1
# 
#     return p_outbits
# 
# 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


from numpy import array, zeros, exp, log, empty
from commpy.channelcoding import conv_encode
from commpy.utilities import dec2bitarray
    msg_bits : 1D ndarray containing {0, 1}
        Stream of bits to be turbo encoded.

    trellis1 : Trellis object
        Trellis representation of the
        first code in the parallel concatenation.

    trellis2 : Trellis object
        Trellis representation of the
        second code in the parallel concatenation.

    interleaver : Interleaver object
        Interleaver used in the turbo code.

    Returns
    -------
    [sys_stream, non_sys_stream1, non_sys_stream2] : list of 1D ndarrays
        Encoded bit streams corresponding
        to the systematic output

        and the two non-systematic
        outputs from the two component codes.
    """

    stream = conv_encode(msg_bits, trellis1, 'rsc')
    sys_stream = stream[::2]
    non_sys_stream_1 = stream[1::2]

    interlv_msg_bits = interleaver.interlv(sys_stream)
    puncture_matrix = array([[0, 1]])

# Path: commpy/channelcoding/convcode.py
# def conv_encode(message_bits, trellis, termination = 'term', puncture_matrix=None):
#     """
#     Encode bits using a convolutional code.
#     Parameters
#     ----------
#     message_bits : 1D ndarray containing {0, 1}
#         Stream of bits to be convolutionally encoded.
#     trellis: pre-initialized Trellis structure.
#     termination: {'cont', 'term'}, optional
#         Create ('term') or not ('cont') termination bits.
#     puncture_matrix: 2D ndarray containing {0, 1}, optional
#         Matrix used for the puncturing algorithm
#     Returns
#     -------
#     coded_bits : 1D ndarray containing {0, 1}
#         Encoded bit stream.
#     """
# 
#     k = trellis.k
#     n = trellis.n
#     total_memory = trellis.total_memory
#     rate = float(k)/n
#     
#     code_type = trellis.code_type
# 
#     if puncture_matrix is None:
#         puncture_matrix = np.ones((trellis.k, trellis.n))
# 
#     number_message_bits = np.size(message_bits)
#     
#     if termination == 'cont':
#         inbits = message_bits
#         number_inbits = number_message_bits
#         number_outbits = int(number_inbits/rate)
#     else:
#         # Initialize an array to contain the message bits plus the truncation zeros
#         if code_type == 'rsc':
#             inbits = message_bits
#             number_inbits = number_message_bits
#             number_outbits = int((number_inbits + k * total_memory)/rate)
#         else:
#             number_inbits = number_message_bits + total_memory + total_memory % k
#             inbits = np.zeros(number_inbits, 'int')
#             # Pad the input bits with M zeros (L-th terminated truncation)
#             inbits[0:number_message_bits] = message_bits
#             number_outbits = int(number_inbits/rate)
# 
#     outbits = np.zeros(number_outbits, 'int')
#     if puncture_matrix is not None:
#         p_outbits = np.zeros(number_outbits, 'int')
#     else:
#         p_outbits = np.zeros(int(number_outbits*
#             puncture_matrix[0:].sum()/np.size(puncture_matrix, 1)), 'int')
#     next_state_table = trellis.next_state_table
#     output_table = trellis.output_table
# 
#     # Encoding process - Each iteration of the loop represents one clock cycle
#     current_state = 0
#     j = 0
# 
#     for i in range(int(number_inbits/k)): # Loop through all input bits
#         current_input = bitarray2dec(inbits[i*k:(i+1)*k])
#         current_output = output_table[current_state][current_input]
#         outbits[j*n:(j+1)*n] = dec2bitarray(current_output, n)
#         current_state = next_state_table[current_state][current_input]
#         j += 1
# 
#     if code_type == 'rsc' and termination == 'term':
#         term_bits = dec2bitarray(current_state, trellis.total_memory)
#         term_bits = term_bits[::-1]
#         for i in range(trellis.total_memory):
#             current_input = bitarray2dec(term_bits[i*k:(i+1)*k])
#             current_output = output_table[current_state][current_input]
#             outbits[j*n:(j+1)*n] = dec2bitarray(current_output, n)
#             current_state = next_state_table[current_state][current_input]
#             j += 1
# 
#     j = 0
#     for i in range(number_outbits):
#         if puncture_matrix[0][i % np.size(puncture_matrix, 1)] == 1:
#             p_outbits[j] = outbits[i]
#             j = j + 1
# 
#     return p_outbits
# 
# 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


# Path: commpy/channelcoding/turbo.py
from numpy import array, zeros, exp, log, empty
from commpy.channelcoding import conv_encode
from commpy.utilities import dec2bitarray

    msg_bits : 1D ndarray containing {0, 1}
        Stream of bits to be turbo encoded.

    trellis1 : Trellis object
        Trellis representation of the
        first code in the parallel concatenation.

    trellis2 : Trellis object
        Trellis representation of the
        second code in the parallel concatenation.

    interleaver : Interleaver object
        Interleaver used in the turbo code.

    Returns
    -------
    [sys_stream, non_sys_stream1, non_sys_stream2] : list of 1D ndarrays
        Encoded bit streams corresponding
        to the systematic output

        and the two non-systematic
        outputs from the two component codes.
    """

    stream = conv_encode(msg_bits, trellis1, 'rsc')
    sys_stream = stream[::2]
    non_sys_stream_1 = stream[1::2]

    interlv_msg_bits = interleaver.interlv(sys_stream)
    puncture_matrix = array([[0, 1]])

    non_sys_stream_2 = conv_encode(interlv_msg_bits, trellis2, 'rsc', puncture_matrix)