# Path: blaspy/helpers.py
# def get_matrix_dimensions(name, matrix):
#     """
#     Return the number of rows and number of columns in a matrix.
# 
#     Args:
#         name:      string to print as the vector's name if an error occurs
#         vector:    numpy 2D ndarray or matrix representing the matrix
# 
#     Returns:
#         A tuple of two elements where each element is described in order below:
# 
#         - number of rows in matrix
#         - number of columns in matrix
# 
#     Raises:
#         TypeError: if matrix is not a 2D NumPy ndarray or matrix
#     """
# 
#     try:
#         rows, cols = matrix.shape
# 
#         return rows, cols
# 
#     except (AttributeError, TypeError):
#         raise_not_2d_numpy(name)
# 
# def create_zero_matrix(rows, cols, dtype, matrix_type):
#     """
#     Create and return a zero matrix with the given number of rows and columns, and of the
#     appropriate dtype and matrix type.
# 
#     Args:
#         rows:         number of rows in the new matrix
#         cols:         number of columns in the new matrix
#         dtype:        NumPy dtype for the elements of the new matrix
#         matrix_type:  either NumPy ndarray or matrix; the new matrix will be of the same type
# 
#     Returns:
#         A new NumPy ndarray or matrix filled with zeros of specified dimensions and dtype.
#     """
# 
#     new_matrix = zeros((rows, cols), dtype=dtype)
# 
#     if matrix_type == np_matrix:
#         return asmatrix(new_matrix)
#     else:
#         return new_matrix
# 
# def check_equal_sizes(name_1, size_1, name_2, size_2):
#     """
#     Check that size_1 and size_2 are equal.
# 
#     Args:
#         name_1:    string to print as the name of the first element
#         size_1:    size of the first element
#         name_2:    string to print as the name of the second element
#         size_2:    size of the second element
# 
#     Raises:
#         ValueError: if size_1 != size_2
#     """
# 
#     if size_1 != size_2:
#         raise_size_mismatch(name_1, size_1, name_2, size_2)
# 
# def convert_trans(trans):
#     if trans == 'n' or trans == 'N':
#         return NO_TRANS
#     elif trans == 't' or trans == 'T':
#         return TRANS
#     else:
#         raise_invalid_parameter('trans', ('n', 'N', 't', 'T'), trans)
# 
# def get_cblas_info(calling_func, dtypes):
#     """
#     Return the appropriate CBLAS subroutine and ctype data type based on the calling function and
#     dtypes of args.
# 
#     Args:
#         calling_func:    a string representation of the calling function
#         dtypes:          a tuple of the dtypes of all of the matrices or vectors passed into the
#                          calling function
# 
#     Returns:
#         A tuple of two elements where each element is described in order below:
# 
#         - appropriate CBLAS function
#         - appropriate ctypes data type
# 
#     Raises:
#         ValueError: if all matrices and/or vectors do not have the same dtype
#     """
# 
#     if all(dtype == 'float64' for dtype in dtypes):
#         return FUNC_DICT[calling_func][0], c_double
# 
#     elif all(dtype == 'float32' for dtype in dtypes):
#         return FUNC_DICT[calling_func][1], c_float
# 
#     else:
#         raise_invalid_dtypes(('float64', 'float32'))
# 
# ROW_MAJOR = 101
# 
# TRANS = 112


from ..helpers import (get_matrix_dimensions, create_zero_matrix, check_equal_sizes, convert_trans,
                       get_cblas_info, ROW_MAJOR, TRANS)
from ctypes import c_int, POINTER
    # convert to appropriate CBLAS value
    cblas_trans_a = convert_trans(trans_a)
    cblas_trans_b = convert_trans(trans_b)
    transpose_a = cblas_trans_a == TRANS
    transpose_b = cblas_trans_b == TRANS

    # get the dimensions of the parameters
    m_A, n_A = get_matrix_dimensions('A', A)
    m_B, n_B = get_matrix_dimensions('B', B)
    m, k_A = (m_A, n_A) if not transpose_a else (n_A, m_A)
    n, k_B = (n_B, m_B) if not transpose_b else (m_B, n_B)

    # if C is not given, create zero matrix with same type as A
    if C is None:
        C = create_zero_matrix(m, n, A.dtype, type(A))
        ldc = None

    # continue getting dimensions of the parameters
    m_C, n_C = get_matrix_dimensions('C', C)

    # assign a default value to lda, ldb, and ldc if necessary (assumes row-major order)
    if lda is None:
        lda = n_A
    if ldb is None:
        ldb = n_B
    if ldc is None:
        ldc = n_C

    # ensure the matrix dimensions conform for the desired operation
    check_equal_sizes('A', k_A, 'B', k_B)

# Path: blaspy/helpers.py
# def get_matrix_dimensions(name, matrix):
#     """
#     Return the number of rows and number of columns in a matrix.
# 
#     Args:
#         name:      string to print as the vector's name if an error occurs
#         vector:    numpy 2D ndarray or matrix representing the matrix
# 
#     Returns:
#         A tuple of two elements where each element is described in order below:
# 
#         - number of rows in matrix
#         - number of columns in matrix
# 
#     Raises:
#         TypeError: if matrix is not a 2D NumPy ndarray or matrix
#     """
# 
#     try:
#         rows, cols = matrix.shape
# 
#         return rows, cols
# 
#     except (AttributeError, TypeError):
#         raise_not_2d_numpy(name)
# 
# def create_zero_matrix(rows, cols, dtype, matrix_type):
#     """
#     Create and return a zero matrix with the given number of rows and columns, and of the
#     appropriate dtype and matrix type.
# 
#     Args:
#         rows:         number of rows in the new matrix
#         cols:         number of columns in the new matrix
#         dtype:        NumPy dtype for the elements of the new matrix
#         matrix_type:  either NumPy ndarray or matrix; the new matrix will be of the same type
# 
#     Returns:
#         A new NumPy ndarray or matrix filled with zeros of specified dimensions and dtype.
#     """
# 
#     new_matrix = zeros((rows, cols), dtype=dtype)
# 
#     if matrix_type == np_matrix:
#         return asmatrix(new_matrix)
#     else:
#         return new_matrix
# 
# def check_equal_sizes(name_1, size_1, name_2, size_2):
#     """
#     Check that size_1 and size_2 are equal.
# 
#     Args:
#         name_1:    string to print as the name of the first element
#         size_1:    size of the first element
#         name_2:    string to print as the name of the second element
#         size_2:    size of the second element
# 
#     Raises:
#         ValueError: if size_1 != size_2
#     """
# 
#     if size_1 != size_2:
#         raise_size_mismatch(name_1, size_1, name_2, size_2)
# 
# def convert_trans(trans):
#     if trans == 'n' or trans == 'N':
#         return NO_TRANS
#     elif trans == 't' or trans == 'T':
#         return TRANS
#     else:
#         raise_invalid_parameter('trans', ('n', 'N', 't', 'T'), trans)
# 
# def get_cblas_info(calling_func, dtypes):
#     """
#     Return the appropriate CBLAS subroutine and ctype data type based on the calling function and
#     dtypes of args.
# 
#     Args:
#         calling_func:    a string representation of the calling function
#         dtypes:          a tuple of the dtypes of all of the matrices or vectors passed into the
#                          calling function
# 
#     Returns:
#         A tuple of two elements where each element is described in order below:
# 
#         - appropriate CBLAS function
#         - appropriate ctypes data type
# 
#     Raises:
#         ValueError: if all matrices and/or vectors do not have the same dtype
#     """
# 
#     if all(dtype == 'float64' for dtype in dtypes):
#         return FUNC_DICT[calling_func][0], c_double
# 
#     elif all(dtype == 'float32' for dtype in dtypes):
#         return FUNC_DICT[calling_func][1], c_float
# 
#     else:
#         raise_invalid_dtypes(('float64', 'float32'))
# 
# ROW_MAJOR = 101
# 
# TRANS = 112


# Path: blaspy/level_3/gemm.py
from ..helpers import (get_matrix_dimensions, create_zero_matrix, check_equal_sizes, convert_trans,
                       get_cblas_info, ROW_MAJOR, TRANS)
from ctypes import c_int, POINTER

    # convert to appropriate CBLAS value
    cblas_trans_a = convert_trans(trans_a)
    cblas_trans_b = convert_trans(trans_b)
    transpose_a = cblas_trans_a == TRANS
    transpose_b = cblas_trans_b == TRANS

    # get the dimensions of the parameters
    m_A, n_A = get_matrix_dimensions('A', A)
    m_B, n_B = get_matrix_dimensions('B', B)
    m, k_A = (m_A, n_A) if not transpose_a else (n_A, m_A)
    n, k_B = (n_B, m_B) if not transpose_b else (m_B, n_B)

    # if C is not given, create zero matrix with same type as A
    if C is None:
        C = create_zero_matrix(m, n, A.dtype, type(A))
        ldc = None

    # continue getting dimensions of the parameters
    m_C, n_C = get_matrix_dimensions('C', C)

    # assign a default value to lda, ldb, and ldc if necessary (assumes row-major order)
    if lda is None:
        lda = n_A
    if ldb is None:
        ldb = n_B
    if ldc is None:
        ldc = n_C

    # ensure the matrix dimensions conform for the desired operation
    check_equal_sizes('A', k_A, 'B', k_B)

    check_equal_sizes('A', m, 'C', m_C)