import math


def mutual_information(co_freq, s_freq, t_freq, total_instances, mitype=None):
    """Compute mutual information on a pair of terms.

    Parameters
    ----------
    co_freq : int
        Co-occurrence frequency of s & t
    s_freq : int
        Occurrence frequency of s
    t_freq : int
        Occurrence frequency of t
    total_instances : int
        Total number of all unique instances of the occurrence factor (for
        example, the total number of all scientific articles in the dataset).
    mitype : str, optional
        Mutual information score type. Possible types 'expected', 'normalized',
        'pmi2', 'pmi3', by default, no normalization is applied (i.e. positive
        pointwise mutual information is computed).
    """
    if co_freq > 0:
        if mitype is not None:
            if mitype == "expected":
                mi = math.log2(
                    (total_instances * co_freq) / (s_freq * t_freq)
                ) * (co_freq / total_instances)
            elif mitype == "normalized":
                alpha = - math.log2(co_freq / total_instances)
                mi = (
                    (math.log2(
                        (total_instances * co_freq) / (s_freq * t_freq)) / alpha)
                    if alpha != 0 else 0
                )
            elif mitype == "pmi2":
                mi = math.log2((co_freq ** 2) / (s_freq * t_freq))
            elif mitype == "pmi3":
                mi = math.log2(
                    (co_freq ** 3) / (s_freq * t_freq * total_instances))
            else:
                raise ValueError(
                    "Provided Mutual information score type (mitype) is not "
                    "supported. Provide one value from the following list "
                    "['expected', 'normalized','pmi2', 'pmi3'] ")
        else:
            mi = math.log2((total_instances * co_freq) / (s_freq * t_freq))
    else:
        mi = 0
    return mi if mi > 0 else 0