# Path: sdcit/utils.py
# def K2D(K: Union[None, np.ndarray]) -> np.ndarray:
#     """An RKHS distance matrix given a kernel matrix
# 
#     A distance matrix D of the same size of the given kernel matrix K
#      :math:`d^2(i,j)=k(i,i)+k(j,j)-2k(i,j)`.
#     """
#     if K is None:
#         return None
# 
#     Kd = repmat(diag(K).reshape((len(K), 1)), 1, len(K))
#     temp = Kd + Kd.transpose() - 2 * K
#     min_val = np.min(temp)
#     if min_val < 0.0:
#         if min_val < -1e-15:
#             warnings.warn('K2D: negative values will be treated as zero. Observed: {}'.format(min_val))
#         temp *= (temp > 0)
#     return np.sqrt(temp)
# 
# def p_value_of(val: float, data: typing.Iterable) -> float:
#     """The percentile of a value given a data"""
# 
#     data = np.sort(data)
#     return float(1 - np.searchsorted(data, val, side='right') / len(data))
# 
# def random_seeds(n=None):
#     """Random seeds of given size or a random seed if n is None"""
#     if n is None:
#         return np.random.randint(np.iinfo(np.int32).max)
#     else:
#         return [np.random.randint(np.iinfo(np.int32).max) for _ in range(n)]
# 
# def cythonize(*matrices):
#     return tuple(np.ascontiguousarray(matrix, dtype=np.float64) for matrix in matrices)


from typing import Tuple
from sdcit.cython_impl.cy_sdcit import cy_sdcit, cy_split_permutation, cy_dense_permutation
from sklearn.linear_model import LinearRegression
from sdcit.utils import K2D, p_value_of, random_seeds, cythonize
import numpy as np
import numpy.ma as ma
        N by N kernel matrix of X
    Ky : np.ndarray
        N by N kernel matrix of Y
    Kz : np.ndarray
        N by N kernel matrix of Z
    Dz : np.ndarray
        N by N pairwise distance matrix of Z
    size_of_null_sample : int
        The number of samples in a null distribution
    with_null : bool
        If true, a resulting null distribution is also returned
    seed : int
        Random seed
    n_jobs: int
        number of threads to be used
    adjust : bool
        whether to adjust null distribution and test statistics based on 'permutation error' information
    to_shuffle : bool
        shuffle the order of given data at the beginning, which minimize possible issues with getting a bad permutation


    References
    ----------
        Lee, S., Honavar, V. (2017). Self-Discrepancy Conditional Independence Test.
        In Proceedings of the Thirty-third Conference on Uncertainty in Artificial Intelligence. Corvallis, Oregon: AUAI Press.
    """
    if seed is not None:
        np.random.seed(seed)

    if Dz is None:

# Path: sdcit/utils.py
# def K2D(K: Union[None, np.ndarray]) -> np.ndarray:
#     """An RKHS distance matrix given a kernel matrix
# 
#     A distance matrix D of the same size of the given kernel matrix K
#      :math:`d^2(i,j)=k(i,i)+k(j,j)-2k(i,j)`.
#     """
#     if K is None:
#         return None
# 
#     Kd = repmat(diag(K).reshape((len(K), 1)), 1, len(K))
#     temp = Kd + Kd.transpose() - 2 * K
#     min_val = np.min(temp)
#     if min_val < 0.0:
#         if min_val < -1e-15:
#             warnings.warn('K2D: negative values will be treated as zero. Observed: {}'.format(min_val))
#         temp *= (temp > 0)
#     return np.sqrt(temp)
# 
# def p_value_of(val: float, data: typing.Iterable) -> float:
#     """The percentile of a value given a data"""
# 
#     data = np.sort(data)
#     return float(1 - np.searchsorted(data, val, side='right') / len(data))
# 
# def random_seeds(n=None):
#     """Random seeds of given size or a random seed if n is None"""
#     if n is None:
#         return np.random.randint(np.iinfo(np.int32).max)
#     else:
#         return [np.random.randint(np.iinfo(np.int32).max) for _ in range(n)]
# 
# def cythonize(*matrices):
#     return tuple(np.ascontiguousarray(matrix, dtype=np.float64) for matrix in matrices)


# Path: sdcit/sdcit_mod.py
from typing import Tuple
from sdcit.cython_impl.cy_sdcit import cy_sdcit, cy_split_permutation, cy_dense_permutation
from sklearn.linear_model import LinearRegression
from sdcit.utils import K2D, p_value_of, random_seeds, cythonize
import numpy as np
import numpy.ma as ma

        N by N kernel matrix of X
    Ky : np.ndarray
        N by N kernel matrix of Y
    Kz : np.ndarray
        N by N kernel matrix of Z
    Dz : np.ndarray
        N by N pairwise distance matrix of Z
    size_of_null_sample : int
        The number of samples in a null distribution
    with_null : bool
        If true, a resulting null distribution is also returned
    seed : int
        Random seed
    n_jobs: int
        number of threads to be used
    adjust : bool
        whether to adjust null distribution and test statistics based on 'permutation error' information
    to_shuffle : bool
        shuffle the order of given data at the beginning, which minimize possible issues with getting a bad permutation


    References
    ----------
        Lee, S., Honavar, V. (2017). Self-Discrepancy Conditional Independence Test.
        In Proceedings of the Thirty-third Conference on Uncertainty in Artificial Intelligence. Corvallis, Oregon: AUAI Press.
    """
    if seed is not None:
        np.random.seed(seed)

    if Dz is None:

        Dz = K2D(Kz)