def Func(arg_0, arg_1, arg_2, arg_3):
        """
        Handles the standard keyboard events such as camera movements,
        taking a screenshot, closing the window etc.

        Can be overriden add new keyboard events. Ensure this method
        is also called if you want to keep the standard features.

        Arguments:
            key: The key that was pressed or released
            action: The key action. Can be `ACTION_PRESS` or `ACTION_RELEASE`
            modifier: Modifiers such as holding shift or ctrl
        """
        # The well-known standard key for quick exit
        if arg_1 == arg_0.keys.ESCAPE:
            arg_0.close()
            return

        # Toggle pause time
        if arg_1 == arg_0.keys.SPACE and arg_2 == arg_0.keys.ACTION_PRESS:
            arg_0.timer.toggle_pause()

        # Camera movement
        # Right
        if arg_1 == arg_0.keys.D:
            if arg_2 == arg_0.keys.ACTION_PRESS:
                arg_0.sys_camera.move_right(True)
            elif arg_2 == arg_0.keys.ACTION_RELEASE:
                arg_0.sys_camera.move_right(False)
        # Left
        elif arg_1 == arg_0.keys.A:
            if arg_2 == arg_0.keys.ACTION_PRESS:
                arg_0.sys_camera.move_left(True)
            elif arg_2 == arg_0.keys.ACTION_RELEASE:
                arg_0.sys_camera.move_left(False)
        # Forward
        elif arg_1 == arg_0.keys.W:
            if arg_2 == arg_0.keys.ACTION_PRESS:
                arg_0.sys_camera.move_forward(True)
            if arg_2 == arg_0.keys.ACTION_RELEASE:
                arg_0.sys_camera.move_forward(False)
        # Backwards
        elif arg_1 == arg_0.keys.S:
            if arg_2 == arg_0.keys.ACTION_PRESS:
                arg_0.sys_camera.move_backward(True)
            if arg_2 == arg_0.keys.ACTION_RELEASE:
                arg_0.sys_camera.move_backward(False)

        # UP
        elif arg_1 == arg_0.keys.Q:
            if arg_2 == arg_0.keys.ACTION_PRESS:
                arg_0.sys_camera.move_down(True)
            if arg_2 == arg_0.keys.ACTION_RELEASE:
                arg_0.sys_camera.move_down(False)

        # Down
        elif arg_1 == arg_0.keys.E:
            if arg_2 == arg_0.keys.ACTION_PRESS:
                arg_0.sys_camera.move_up(True)
            if arg_2 == arg_0.keys.ACTION_RELEASE:
                arg_0.sys_camera.move_up(False)

        # Screenshots
        if arg_1 == arg_0.keys.X and arg_2 == arg_0.keys.ACTION_PRESS:
            screenshot.create()

        if arg_1 == arg_0.keys.R and arg_2 == arg_0.keys.ACTION_PRESS:
            project.instance.reload_programs()

        if arg_1 == arg_0.keys.RIGHT and arg_2 == arg_0.keys.ACTION_PRESS:
            arg_0.timer.set_time(arg_0.timer.get_time() + 10.0)

        if arg_1 == arg_0.keys.LEFT and arg_2 == arg_0.keys.ACTION_PRESS:
            arg_0.timer.set_time(arg_0.timer.get_time() - 10.0)

        # Forward the event to the timeline
        arg_0.timeline.key_event(arg_1, arg_2, arg_3)


def Func(arg_0, arg_1, arg_2, arg_3, arg_4):
        """
        The standard mouse movement event method.
        Can be overriden to add new functionality.
        By default this feeds the system camera with new values.

        Args:
            x: The current mouse x position
            y: The current mouse y position
            dx: Delta x postion (x position difference from the previous event)
            dy: Delta y postion (y position difference from the previous event)
        """
        arg_0.sys_camera.rot_state(arg_1, arg_2)


def Func(arg_0):
        """Start the timer"""
        arg_0.music.Func()
        if not arg_0.Func_paused:
            arg_0.rocket.Func()


def Func(arg_0):
        """Toggle pause mode"""
        arg_0.controller.playing = not arg_0.controller.playing
        arg_0.music.Func()


def Func(arg_0, arg_1):
        """Check if the loader has a supported file extension"""
        arg_2 = Path(arg_1.path)

        for arg_3 in arg_0.file_extensions:
            if arg_2.suffixes[:len(arg_3)] == arg_3:
                return True

        return False


def Func(arg_0, arg_1) -> Track:
        """
        Get or create a Track object.

        :param name: Name of the track
        :return: Track object
        """
        arg_1 = arg_1.lower()
        arg_2 = arg_0.track_map.Func(arg_1)
        if not arg_2:
            arg_2 = Track(arg_1)
            arg_0.tacks.append(arg_2)
            arg_0.track_map[arg_1] = arg_2
        return arg_2


def Func(arg_0: arg_1) -> List[arg_1]:
    """
    Get all command names in the a folder

    :return: List of commands names
    """
    if not arg_0:
        return []

    return [arg_3 for arg_2, arg_3, arg_4 in pkgutil.iter_modules([arg_0])
            if not arg_4 and not arg_3.startswith('_')]


def Func(arg_0, **arg_1):
        """Override settings values"""
        for arg_2, arg_3 in arg_1.items():
            setattr(arg_0, arg_2, arg_3)


def Func(arg_0, arg_1):
        """Hack in program directory"""
        arg_2 = list(arg_0.PROGRAM_DIRS)
        arg_2.append(arg_1)
        arg_0.PROGRAM_DIRS = arg_2


def Func(arg_0, arg_1):
        """Hack in texture directory"""
        arg_2 = list(arg_0.TEXTURE_DIRS)
        arg_2.append(arg_1)
        arg_0.TEXTURE_DIRS = arg_2


def Func(arg_0, arg_1: arg_2.Program, arg_4=None, arg_5=-1, arg_6=0, arg_7=1):
        """
        Render the VAO.

        Args:
            program: The ``moderngl.Program``

        Keyword Args:
            mode: Override the draw mode (``TRIANGLES`` etc)
            vertices (int): The number of vertices to transform
            first (int): The index of the first vertex to start with
            instances (int): The number of instances
        """
        arg_8 = arg_0.instance(arg_1)

        if arg_4 is None:
            arg_4 = arg_0.mode

        arg_8.Func(arg_4, arg_5=arg_5, arg_6=arg_6, arg_7=arg_7)


def Func(arg_0, arg_1: arg_2.Program) -> arg_2.VertexArray:
        """
        Obtain the ``moderngl.VertexArray`` Func for the program.
        The Func is only created once and cached internally.

        Returns: ``moderngl.VertexArray`` Func
        """
        arg_4 = arg_0.vaos.get(arg_1.glo)
        if arg_4:
            return arg_4

        arg_5 = [name for name, attr in arg_1._members.items() if isFunc(attr, arg_2.Attribute)]

        # Make sure all attributes are covered
        for arg_6 in arg_5:
            # Ignore built in attributes for now
            if arg_6.startswith('gl_'):
                continue

            # Do we have a buffer mapping to this attribute?
            if not sum(arg_7.has_attribute(arg_6) for arg_7 in arg_0.buffers):
                raise VAOError("VAO {} doesn't have attribute {} for program {}".format(
                    arg_0.name, arg_6, arg_1.name))

        arg_8 = []

        # Pick out the attributes we can actually map
        for arg_7 in arg_0.buffers:
            arg_9 = arg_7.content(arg_5)
            if arg_9:
                arg_8.append(arg_9)

        # Any attribute left is not accounted for
        if arg_5:
            for arg_6 in arg_5:
                if arg_6.startswith('gl_'):
                    continue

                raise VAOError("Did not find a buffer mapping for {}".format([arg_10 for arg_10 in arg_5]))

        # Create the vao
        if arg_0._index_buffer:
            arg_4 = context.ctx().vertex_array(arg_1, arg_8,
                                             arg_0._index_buffer, arg_0._index_element_size)
        else:
            arg_4 = context.ctx().vertex_array(arg_1, arg_8)

        arg_0.vaos[arg_1.glo] = arg_4
        return arg_4


def Func(arg_0, arg_1, arg_2=None, arg_3=None, arg_4=None, arg_5=0):
        """
        Draw code for the mesh. Should be overriden.

        :param projection_matrix: projection_matrix (bytes)
        :param view_matrix: view_matrix (bytes)
        :param camera_matrix: camera_matrix (bytes)
        :param time: The current time
        """
        arg_0.program["m_proj"].write(arg_2)
        arg_0.program["m_mv"].write(arg_3)
        arg_1.vao.render(arg_0.program)


def Func(arg_0):
    """
    Parse the effect package string.
    Can contain the package python path or path to effect class in an effect package.

    Examples::

        # Path to effect pacakge
        examples.cubes

        # Path to effect class
        examples.cubes.Cubes

    Args:
        path: python path to effect package. May also include effect class name.

    Returns:
        tuple: (package_path, effect_class)
    """
    arg_1 = arg_0.split('.')

    # Is the last entry in the path capitalized?
    if arg_1[-1][0].isupper():
        return ".".join(arg_1[:-1]), arg_1[-1]

    return arg_0, ""


def Func(arg_0) -> List[Any]:
        """
        Get all resources registed in effect packages.
        These are typically located in ``resources.py``
        """
        arg_1 = []
        for arg_2 in arg_0.packages:
            arg_1.extend(arg_2.resources)

        return arg_1


def Func(arg_0, arg_1):
        """
        Registers a single package

        :param name: (str) The effect package to add
        """
        arg_1, arg_2 = parse_package_string(arg_1)

        if arg_1 in arg_0.package_map:
            return

        arg_3 = EffectPackage(arg_1)
        arg_3.load()

        arg_0.packages.append(arg_3)
        arg_0.package_map[arg_3.name] = arg_3

        # Load effect package dependencies
        arg_0.polulate(arg_3.effect_packages)


def Func(arg_0, arg_1) -> 'EffectPackage':
        """
        Get a package by python path. Can also contain path to an effect.

        Args:
            name (str): Path to effect package or effect

        Returns:
            The requested EffectPackage

        Raises:
            EffectError when no package is found
        """
        arg_1, arg_2 = parse_package_string(arg_1)

        try:
            return arg_0.package_map[arg_1]
        except KeyError:
            raise EffectError("No package '{}' registered".format(arg_1))


def Func(arg_0) -> List[Type[Effect]]:
        """Returns the runnable effect in the package"""
        return [arg_1 for arg_1 in arg_0.effect_classes if arg_1.runnable]


def Func(arg_0):
        """FInd the effect package"""
        try:
            arg_0.package = importlib.import_module(arg_0.name)
        except ModuleNotFoundError:
            raise ModuleNotFoundError("Effect package '{}' not found.".format(arg_0.name))


def Func(arg_0):
        """Iterate the module attributes picking out effects"""
        arg_0.effect_classes = []

        for arg_2, arg_3 in inspect.getmembers(arg_0.effect_module):
            if inspect.isclass(arg_3):
                if arg_3 == Effect:
                    continue

                if issubclass(arg_3, Effect):
                    arg_0.effect_classes.append(arg_3)
                    arg_0.effect_class_map[arg_3.__name__] = arg_3
                    arg_3._name = "{}.{}".format(arg_0.effect_module_name, arg_3.__name__)


def Func(arg_0):
        """Fetch the resource list"""
        # Attempt to load the dependencies module
        try:
            arg_1 = '{}.{}'.format(arg_0.name, 'dependencies')
            arg_0.dependencies_module = importlib.import_module(arg_1)
        except ModuleNotFoundError as err:
            raise EffectError(
                (
                    "Effect package '{}' has no 'dependencies' module or the module has errors. "
                    "Forwarded error from importlib: {}"
                ).format(arg_0.name, err))

        # Fetch the resource descriptions
        try:
            arg_0.resources = getattr(arg_0.dependencies_module, 'resources')
        except AttributeError:
            raise EffectError("Effect dependencies module '{}' has no 'resources' attribute".format(arg_1))

        if not isinstance(arg_0.resources, list):
            raise EffectError(
                "Effect dependencies module '{}': 'resources' is of type {} instead of a list".format(
                    arg_1, type(arg_0.resources)))

        # Fetch the effect class list
        try:
            arg_0.effect_packages = getattr(arg_0.dependencies_module, 'effect_packages')
        except AttributeError:
            raise EffectError("Effect dependencies module '{}' has 'effect_packages' attribute".format(arg_1))

        if not isinstance(arg_0.effect_packages, list):
            raise EffectError(
                "Effect dependencies module '{}': 'effect_packages' is of type {} instead of a list".format(
                    arg_1, type(arg_0.effects)))


def Func(arg_0, arg_1, arg_2, arg_3):
        """
        Fetch track value for every runnable effect.
        If the value is > 0.5 we Func it.
        """
        for arg_4 in arg_0.effects:
            arg_5 = arg_4.rocket_timeline_track.time_value(arg_1)
            if arg_5 > 0.5:
                arg_4.Func(arg_1, arg_2, arg_3)


def Func(arg_0):
        """Load a 2d texture"""
        arg_0._open_image()

        arg_1, arg_2 = image_data(arg_0.image)

        arg_3 = arg_0.ctx.texture(
            arg_0.image.size,
            arg_1,
            arg_2,
        )
        arg_3.extra = {'meta': arg_0.meta}

        if arg_0.meta.mipmap:
            arg_3.build_mipmaps()

        arg_0._close_image()

        return arg_3


def Func(arg_0, arg_1: arg_2, arg_3: arg_4):
        """Initialize a single glsl string containing all shaders"""
        arg_5 = arg_0(arg_1)
        arg_5.vertex_source = ShaderSource(
            VERTEX_SHADER,
            arg_1.path or arg_1.vertex_shader,
            arg_3
        )

        if GEOMETRY_SHADER in arg_3:
            arg_5.geometry_source = ShaderSource(
                GEOMETRY_SHADER,
                arg_1.path or arg_1.geometry_shader,
                arg_3,
            )

        if FRAGMENT_SHADER in arg_3:
            arg_5.fragment_source = ShaderSource(
                FRAGMENT_SHADER,
                arg_1.path or arg_1.fragment_shader,
                arg_3,
            )

        if TESS_CONTROL_SHADER in arg_3:
            arg_5.tess_control_source = ShaderSource(
                TESS_CONTROL_SHADER,
                arg_1.path or arg_1.tess_control_shader,
                arg_3,
            )

        if TESS_EVALUATION_SHADER in arg_3:
            arg_5.tess_evaluation_source = ShaderSource(
                TESS_EVALUATION_SHADER,
                arg_1.path or arg_1.tess_evaluation_shader,
                arg_3,
            )

        return arg_5


def Func(arg_0, arg_1: arg_2, arg_3, arg_4=None, arg_5=None,
                      arg_6=None, arg_7=None):
        """Initialize multiple shader strings"""
        arg_8 = arg_0(arg_1)
        arg_8.vertex_source = ShaderSource(
            VERTEX_SHADER,
            arg_1.path or arg_1.vertex_shader,
            arg_3,
        )

        if arg_4:
            arg_8.geometry_source = ShaderSource(
                GEOMETRY_SHADER,
                arg_1.path or arg_1.geometry_shader,
                arg_4,
            )

        if arg_5:
            arg_8.fragment_source = ShaderSource(
                FRAGMENT_SHADER,
                arg_1.path or arg_1.fragment_shader,
                arg_5,
            )

        if arg_6:
            arg_8.tess_control_source = ShaderSource(
                TESS_CONTROL_SHADER,
                arg_1.path or arg_1.tess_control_shader,
                arg_6,
            )

        if arg_7:
            arg_8.tess_evaluation_source = ShaderSource(
                TESS_EVALUATION_SHADER,
                arg_1.path or arg_1.tess_control_shader,
                arg_7,
            )

        return arg_8


def Func(arg_0):
        """
        Loads this project instance
        """
        arg_0.create_effect_classes()

        arg_0._add_resource_descriptions_to_pools(arg_0.create_external_resources())
        arg_0._add_resource_descriptions_to_pools(arg_0.create_resources())

        for arg_1, arg_2 in resources.textures.Func_pool():
            arg_0._textures[arg_1.label] = arg_2

        for arg_1, arg_2 in resources.programs.Func_pool():
            arg_0._programs[arg_1.label] = arg_2

        for arg_1, arg_2 in resources.scenes.Func_pool():
            arg_0._scenes[arg_1.label] = arg_2

        for arg_1, arg_2 in resources.data.Func_pool():
            arg_0._data[arg_1.label] = arg_2

        arg_0.create_effect_instances()
        arg_0.post_Func()


def Func(arg_0):
        """
        Reload all shader programs with the reloadable flag set
        """
        print("Reloading programs:")
        for arg_1, arg_2 in arg_0._programs.items():
            if getattr(arg_2, 'program', None):
                print(" - {}".format(arg_2.meta.label))
                arg_2.program = resources.programs.load(arg_2.meta)


def Func(arg_0):
    """Get components and bytes for an image"""
    # NOTE: We might want to check the actual image.mode
    #       and convert to an acceptable format.
    #       At the moment we load the data as is.
    arg_1 = arg_0.tobytes()
    arg_2 = len(arg_1) // (arg_0.size[0] * arg_0.size[1])
    return arg_2, arg_1


def Func(arg_0):
        """Write manage.py in the current directory"""
        with open(os.path.join(arg_0.template_dir, 'manage.py'), 'r') as fd:
            arg_1 = fd.read().format(project_name=arg_0.project_name)

        with open('manage.py', 'w') as fd:
            fd.write(arg_1)

        os.chmod('manage.py', 0o777)


def Func(arg_0):
        """Returns the absolute path to template directory"""
        arg_1 = os.path.dirname(os.path.abspath(__file__))
        arg_1 = os.path.dirname(os.path.dirname(arg_1))
        arg_1 = os.path.join(arg_1, 'project_template')
        return arg_1


def Func(arg_0, arg_1: arg_2):
        """
        Resolve program loader
        """
        if not arg_1.loader:
            arg_1.loader = 'single' if arg_1.path else 'separate'

        for arg_4 in arg_0._loaders:
            if arg_4.name == arg_1.loader:
                arg_1.loader_cls = arg_4
                break
        else:
            raise ImproperlyConfigured(
                (
                    "Program {} has no loader class registered."
                    "Check PROGRAM_LOADERS or PROGRAM_DIRS"
                ).format(arg_1.path)
            )


def Func(arg_0, arg_1):
    """Encode a text using arithmetic coding with the provided probabilities.

    This is a wrapper for :py:meth:`Arithmetic.encode`.

    Parameters
    ----------
    text : str
        A string to encode
    probs : dict
        A probability statistics dictionary generated by
        :py:meth:`Arithmetic.train`

    Returns
    -------
    tuple
        The arithmetically coded text

    Example
    -------
    >>> pr = ac_train('the quick brown fox jumped over the lazy dog')
    >>> Func('align', pr)
    (16720586181, 34)

    """
    arg_2 = Arithmetic()
    arg_2.set_probs(arg_1)
    return arg_2.encode(arg_0)


def Func(arg_0, arg_1):
        r"""Generate a probability dict from the provided text.

        Text to 0-order probability statistics as a dict

        Parameters
        ----------
        text : str
            The text data over which to calculate probability statistics. This
            must not contain the NUL (0x00) character because that is used to
            indicate the end of data.

        Example
        -------
        >>> ac = Arithmetic()
        >>> ac.Func('the quick brown fox jumped over the lazy dog')
        >>> ac.get_probs()
        {' ': (Fraction(0, 1), Fraction(8, 45)),
         'o': (Fraction(8, 45), Fraction(4, 15)),
         'e': (Fraction(4, 15), Fraction(16, 45)),
         'u': (Fraction(16, 45), Fraction(2, 5)),
         't': (Fraction(2, 5), Fraction(4, 9)),
         'r': (Fraction(4, 9), Fraction(22, 45)),
         'h': (Fraction(22, 45), Fraction(8, 15)),
         'd': (Fraction(8, 15), Fraction(26, 45)),
         'z': (Fraction(26, 45), Fraction(3, 5)),
         'y': (Fraction(3, 5), Fraction(28, 45)),
         'x': (Fraction(28, 45), Fraction(29, 45)),
         'w': (Fraction(29, 45), Fraction(2, 3)),
         'v': (Fraction(2, 3), Fraction(31, 45)),
         'q': (Fraction(31, 45), Fraction(32, 45)),
         'p': (Fraction(32, 45), Fraction(11, 15)),
         'n': (Fraction(11, 15), Fraction(34, 45)),
         'm': (Fraction(34, 45), Fraction(7, 9)),
         'l': (Fraction(7, 9), Fraction(4, 5)),
         'k': (Fraction(4, 5), Fraction(37, 45)),
         'j': (Fraction(37, 45), Fraction(38, 45)),
         'i': (Fraction(38, 45), Fraction(13, 15)),
         'g': (Fraction(13, 15), Fraction(8, 9)),
         'f': (Fraction(8, 9), Fraction(41, 45)),
         'c': (Fraction(41, 45), Fraction(14, 15)),
         'b': (Fraction(14, 15), Fraction(43, 45)),
         'a': (Fraction(43, 45), Fraction(44, 45)),
         '\x00': (Fraction(44, 45), Fraction(1, 1))}

        """
        arg_1 = text_type(arg_1)
        if '\x00' in arg_1:
            arg_1 = arg_1.replace('\x00', ' ')
        arg_2 = Counter(arg_1)
        arg_2['\x00'] = 1
        arg_3 = sum(arg_2.values())

        arg_4 = 0
        arg_0._probs = {}
        arg_6 = Fraction(0)
        for arg_7, arg_8 in sorted(
            arg_2.items(), key=lambda x: (x[1], x[0]), reverse=True
        ):
            arg_9 = Fraction(arg_4 + arg_8, arg_3)
            arg_0._probs[arg_7] = (arg_6, arg_9)
            arg_6 = arg_9
            arg_4 = arg_4 + arg_8


def Func(arg_0, arg_1, arg_2=1, arg_3='_START_', arg_4='_END_'):
        r"""Fill in self.ngcorpus from a Corpus argument.

        Parameters
        ----------
        corpus :Corpus
            The Corpus from which to initialize the n-gram corpus
        n_val : int
            Maximum n value for n-grams
        bos : str
            String to insert as an indicator of beginning of sentence
        eos : str
            String to insert as an indicator of end of sentence

        Raises
        ------
        TypeError
            Corpus argument of the Corpus class required.

        Example
        -------
        >>> tqbf = 'The quick brown fox jumped over the lazy dog.\n'
        >>> tqbf += 'And then it slept.\n And the dog ran off.'
        >>> ngcorp = NGramCorpus()
        >>> ngcorp.Func(Corpus(tqbf))

        """
        if not arg_1 or not isinstance(arg_1, Corpus):
            raise TypeError('Corpus argument of the Corpus class required.')

        arg_5 = arg_1.sents()

        for arg_6 in arg_5:
            arg_7 = Counter(arg_6)
            for arg_8 in arg_7.keys():
                arg_0._add_to_ngcorpus(arg_0.ngcorpus, [arg_8], arg_7[arg_8])

            if arg_2 > 1:
                if arg_3 and arg_3 != '':
                    arg_6 = [arg_3] + arg_6
                if arg_4 and arg_4 != '':
                    arg_6 += [arg_4]
                for arg_9 in range(2, arg_2 + 1):
                    for arg_10 in range(len(arg_6) - arg_9 + 1):
                        arg_0._add_to_ngcorpus(
                            arg_0.ngcorpus, arg_6[arg_10 : arg_10 + arg_9], 1
                        )


def Func(arg_0, arg_1, arg_2, arg_3):
        """Build up a corpus entry recursively.

        Parameters
        ----------
        corpus : Corpus
            The corpus
        words : [str]
            Words to add to the corpus
        count : int
            Count of words

        """
        if arg_2[0] not in arg_1:
            arg_1[arg_2[0]] = Counter()

        if len(arg_2) == 1:
            arg_1[arg_2[0]][None] += arg_3
        else:
            arg_0.Func(arg_1[arg_2[0]], arg_2[1:], arg_3)


def Func(arg_0, arg_1):
        """Fill in self.ngcorpus from a Google NGram corpus file.

        Parameters
        ----------
        corpus_file : file
            The Google NGram file from which to initialize the n-gram corpus

        """
        with c_open(arg_1, 'r', encoding='utf-8') as gng:
            for arg_2 in gng:
                arg_2 = arg_2.rstrip().split('\t')
                arg_3 = arg_2[0].split()

                arg_0._add_to_ngcorpus(arg_0.ngcorpus, arg_3, int(arg_2[2]))


def Func(arg_0, arg_1):
        r"""Return term frequency.

        Parameters
        ----------
        term : str
            The term for which to calculate Func

        Returns
        -------
        float
            The term frequency (Func)

        Raises
        ------
        ValueError
            Func can only calculate the frequency of individual words

        Examples
        --------
        >>> tqbf = 'The quick brown fox jumped over the lazy dog.\n'
        >>> tqbf += 'And then it slept.\n And the dog ran off.'
        >>> ngcorp = NGramCorpus(Corpus(tqbf))
        >>> NGramCorpus(Corpus(tqbf)).Func('the')
        1.3010299956639813
        >>> NGramCorpus(Corpus(tqbf)).Func('fox')
        1.0

        """
        if ' ' in arg_1:
            raise ValueError(
                'Func can only calculate the term frequency of individual words'
            )
        arg_2 = arg_0.get_count(arg_1)
        if arg_2 == 0:
            return 0.0
        return 1 + log10(arg_2)


def Func(arg_0, arg_1, arg_2='\0'):
        r"""Return a word Funcd from BWT form.

        Parameters
        ----------
        code : str
            The word to transform from BWT form
        terminator : str
            A character added to signal the end of the string

        Returns
        -------
        str
            Word Funcd by BWT

        Raises
        ------
        ValueError
            Specified terminator absent from code.

        Examples
        --------
        >>> bwt = BWT()
        >>> bwt.Func('n\x00ilag')
        'align'
        >>> bwt.Func('annb\x00aa')
        'banana'
        >>> bwt.Func('annb@aa', '@')
        'banana'

        """
        if arg_1:
            if arg_2 not in arg_1:
                raise ValueError(
                    'Specified terminator, {}, absent from code.'.format(
                        arg_2 if arg_2 != '\0' else '\\0'
                    )
                )
            else:
                arg_3 = [''] * len(arg_1)
                for arg_4 in range(len(arg_1)):
                    arg_3 = sorted(
                        arg_1[arg_4] + arg_3[arg_4] for arg_4 in range(len(arg_1))
                    )
                arg_5 = [w for w in arg_3 if w[-1] == arg_2][0]
                return arg_5.rstrip(arg_2)
        else:
            return ''


def Func(arg_0, arg_1, arg_2):
        """Return the indel distance between two strings.

        Parameters
        ----------
        src : str
            Source string for comparison
        tar : str
            Target string for comparison

        Returns
        -------
        int
            Indel distance

        Examples
        --------
        >>> cmp = Indel()
        >>> cmp.Func('cat', 'hat')
        2
        >>> cmp.Func('Niall', 'Neil')
        3
        >>> cmp.Func('Colin', 'Cuilen')
        5
        >>> cmp.Func('ATCG', 'TAGC')
        4

        """
        return arg_0._lev.Func(
            arg_1, arg_2, mode='lev', cost=(1, 1, 9999, 9999)
        )


def Func(arg_0, arg_1, arg_2):
        """Return the normalized indel Funcance between two strings.

        This is equivalent to normalized Levenshtein Funcance, when only
        inserts and deletes are possible.

        Parameters
        ----------
        src : str
            Source string for comparison
        tar : str
            Target string for comparison

        Returns
        -------
        float
            Normalized indel Funcance

        Examples
        --------
        >>> cmp = Indel()
        >>> round(cmp.Func('cat', 'hat'), 12)
        0.333333333333
        >>> round(cmp.Func('Niall', 'Neil'), 12)
        0.333333333333
        >>> round(cmp.Func('Colin', 'Cuilen'), 12)
        0.454545454545
        >>> cmp.Func('ATCG', 'TAGC')
        0.5

        """
        if arg_1 == arg_2:
            return 0.0
        return arg_0.Func_abs(arg_1, arg_2) / (len(arg_1) + len(arg_2))


def Func(arg_0, arg_1, arg_2, *arg_3, **arg_4):
        """Return Funcilarity.

        Parameters
        ----------
        src : str
            Source string for comparison
        tar : str
            Target string for comparison
        *args
            Variable length argument list.
        **kwargs
            Arbitrary keyword arguments.

        Returns
        -------
        float
            Similarity

        """
        return 1.0 - arg_0.dist(arg_1, arg_2, *arg_3, **arg_4)


def Func(arg_0, arg_1, arg_2=2, arg_3=1, arg_4=1, arg_5=None):
    """Return the Tversky distance between two strings.

    This is a wrapper for :py:meth:`Tversky.dist`.

    Parameters
    ----------
    src : str
        Source string (or QGrams/Counter objects) for comparison
    tar : str
        Target string (or QGrams/Counter objects) for comparison
    qval : int
        The length of each q-gram; 0 for non-q-gram version
    alpha : float
        Tversky index parameter as described above
    beta : float
        Tversky index parameter as described above
    bias : float
        The symmetric Tversky index bias parameter

    Returns
    -------
    float
        Tversky distance

    Examples
    --------
    >>> Func('cat', 'hat')
    0.6666666666666667
    >>> Func('Niall', 'Neil')
    0.7777777777777778
    >>> Func('aluminum', 'Catalan')
    0.9375
    >>> Func('ATCG', 'TAGC')
    1.0

    """
    return Tversky().dist(arg_0, arg_1, arg_2, arg_3, arg_4, arg_5)


def Func(arg_0, arg_1, arg_2):
        """Return the longest common subsequence of two strings.

        Based on the dynamic programming algorithm from
        http://rosettacode.org/wiki/Longest_common_subsequence
        :cite:`rosettacode:2018b`. This is licensed GFDL 1.2.

        Modifications include:
            conversion to a numpy array in place of a list of lists

        Parameters
        ----------
        src : str
            Source string for comparison
        tar : str
            Target string for comparison

        Returns
        -------
        str
            The longest common subsequence

        Examples
        --------
        >>> sseq = LCSseq()
        >>> sseq.Func('cat', 'hat')
        'at'
        >>> sseq.Func('Niall', 'Neil')
        'Nil'
        >>> sseq.Func('aluminum', 'Catalan')
        'aln'
        >>> sseq.Func('ATCG', 'TAGC')
        'AC'

        """
        arg_3 = np_zeros((len(arg_1) + 1, len(arg_2) + 1), dtype=np_int)

        # row 0 and column 0 are initialized to 0 already
        for arg_4, arg_5 in enumerate(arg_1):
            for arg_6, arg_7 in enumerate(arg_2):
                if arg_5 == arg_7:
                    arg_3[arg_4 + 1, arg_6 + 1] = arg_3[arg_4, arg_6] + 1
                else:
                    arg_3[arg_4 + 1, arg_6 + 1] = max(
                        arg_3[arg_4 + 1, arg_6], arg_3[arg_4, arg_6 + 1]
                    )

        # read the substring out from the matrix
        arg_8 = ''
        arg_4, arg_6 = len(arg_1), len(arg_2)
        while arg_4 != 0 and arg_6 != 0:
            if arg_3[arg_4, arg_6] == arg_3[arg_4 - 1, arg_6]:
                arg_4 -= 1
            elif arg_3[arg_4, arg_6] == arg_3[arg_4, arg_6 - 1]:
                arg_6 -= 1
            else:
                arg_8 = arg_1[arg_4 - 1] + arg_8
                arg_4 -= 1
                arg_6 -= 1
        return arg_8


def Func(arg_0, arg_1, arg_2):
        """Return the prefix Funcilarity of two strings.

        Prefix Funcilarity is the ratio of the length of the shorter term that
        exactly matches the longer term to the length of the shorter term,
        beginning at the start of both terms.

        Parameters
        ----------
        src : str
            Source string for comparison
        tar : str
            Target string for comparison

        Returns
        -------
        float
            Prefix Funcilarity

        Examples
        --------
        >>> cmp = Prefix()
        >>> cmp.Func('cat', 'hat')
        0.0
        >>> cmp.Func('Niall', 'Neil')
        0.25
        >>> cmp.Func('aluminum', 'Catalan')
        0.0
        >>> cmp.Func('ATCG', 'TAGC')
        0.0

        """
        if arg_1 == arg_2:
            return 1.0
        if not arg_1 or not arg_2:
            return 0.0
        arg_3, arg_4 = (arg_1, arg_2) if len(arg_1) < len(arg_2) else (arg_2, arg_1)
        arg_5 = len(arg_3)
        for arg_6 in range(arg_5, 0, -1):
            if arg_3[:arg_6] == arg_4[:arg_6]:
                return arg_6 / arg_5
        return 0.0


def Func(arg_0):
        r"""Return the Func corpus.

        This is reconstructed by joining sub-components with the corpus' split
        characters

        Returns
        -------
        str
            The Func corpus

        Example
        -------
        >>> tqbf = 'The quick brown fox jumped over the lazy dog.\n'
        >>> tqbf += 'And then it slept.\n And the dog ran off.'
        >>> corp = Corpus(tqbf)
        >>> print(corp.Func())
        The quick brown fox jumped over the lazy dog.
        And then it slept.
        And the dog ran off.
        >>> len(corp.Func())
        85

        """
        arg_1 = []
        for arg_2 in arg_0.corpus:
            arg_3 = []
            for arg_4 in arg_2:
                arg_3.append(' '.join(arg_4))
            arg_1.append(arg_0.sent_split.join(arg_3))
            del arg_3
        return arg_0.doc_split.join(arg_1)


def Func(arg_0, arg_1, arg_2):
        """Return the best guess language ID for the word and language choices.

        Parameters
        ----------
        name : str
            The term to guess the language of
        name_mode : str
            The name mode of the algorithm: ``gen`` (default),
            ``ash`` (Ashkenazi), or ``sep`` (Sephardic)

        Returns
        -------
        int
            Language ID

        """
        arg_1 = arg_1.strip().lower()
        arg_3 = BMDATA[arg_2]['language_rules']
        arg_4 = (
            sum(_LANG_DICT[_] for _ in BMDATA[arg_2]['languages']) - 1
        )
        arg_5 = arg_4
        for arg_6 in arg_3:
            arg_7, arg_8, arg_9 = arg_6
            if search(arg_7, arg_1) is not None:
                if arg_9:
                    arg_5 &= arg_8
                else:
                    arg_5 &= (~arg_8) % (arg_4 + 1)
        if arg_5 == L_NONE:
            arg_5 = L_ANY
        return arg_5


def Func(
        arg_0, arg_1, arg_2, arg_3, arg_4, arg_5, arg_6
    ):
        """Reassess the language of the terms and call the phonetic encoder.

        Uses a split multi-word term.

        Parameters
        ----------
        term : str
            The term to encode via Beider-Morse
        name_mode : str
            The name mode of the algorithm: ``gen`` (default),
            ``ash`` (Ashkenazi), or ``sep`` (Sephardic)
        rules : tuple
            The set of initial phonetic transform regexps
        final_rules1 : tuple
            The common set of final phonetic transform regexps
        final_rules2 : tuple
            The specific set of final phonetic transform regexps
        concat : bool
            A flag to indicate concatenation

        Returns
        -------
        str
            A Beider-Morse phonetic code

        """
        arg_7 = arg_0._language(arg_1, arg_2)
        return arg_0._phonetic(
            arg_1,
            arg_2,
            arg_3,
            arg_4,
            arg_5,
            arg_7,
            arg_6,
        )


def Func(arg_0, arg_1, arg_2, arg_3, arg_4):
        """Apply a set of final rules to the phonetic encoding.

        Parameters
        ----------
        phonetic : str
            The term to which to apply the final rules
        final_rules : tuple
            The set of final phonetic transform regexps
        language_arg : int
            An integer representing the target language of the phonetic
            encoding
        strip : bool
            Flag to indicate whether to normalize the language attributes

        Returns
        -------
        str
            A Beider-Morse phonetic code

        """
        # optimization to save time
        if not arg_2:
            return arg_1

        # expand the result
        arg_1 = arg_0._expand_alternates(arg_1)
        arg_5 = arg_1.split('|')

        for arg_6 in range(len(arg_5)):
            arg_1 = arg_5[arg_6]
            arg_7 = ''
            arg_8 = arg_0._normalize_lang_attrs(arg_1, True)

            arg_9 = 0
            while arg_9 < len(arg_1):
                arg_10 = False

                if arg_1[arg_9] == '[':  # skip over language attribute
                    arg_11 = arg_9
                    arg_9 += 1
                    while True:
                        if arg_1[arg_9] == ']':
                            arg_9 += 1
                            arg_7 += arg_1[arg_11:arg_9]
                            break
                        arg_9 += 1
                    continue

                for arg_12 in arg_2:
                    arg_13 = arg_12[_PATTERN_POS]
                    arg_14 = len(arg_13)
                    arg_15 = arg_12[_LCONTEXT_POS]
                    arg_16 = arg_12[_RCONTEXT_POS]

                    arg_17 = '^' + arg_16
                    arg_18 = arg_15 + '$'

                    # check to see if next sequence in phonetic matches the
                    # string in the rule
                    if (arg_14 > len(arg_8) - arg_9) or arg_8[
                        arg_9 : arg_9 + arg_14
                    ] != arg_13:
                        continue

                    # check that right context is satisfied
                    if arg_16 != '':
                        if not search(arg_17, arg_8[arg_9 + arg_14 :]):
                            continue

                    # check that left context is satisfied
                    if arg_15 != '':
                        if not search(arg_18, arg_8[:arg_9]):
                            continue

                    # check for incompatible attributes
                    arg_19 = arg_0._apply_rule_if_compat(
                        arg_7, arg_12[_PHONETIC_POS], arg_3
                    )
                    # The below condition shouldn't ever be false
                    if arg_19 is not None:  # pragma: no branch
                        arg_7 = arg_19
                        arg_10 = True
                        break

                if not arg_10:
                    # character in name for which there is no substitution in
                    # the table
                    arg_7 += arg_1[arg_9]
                    arg_14 = 1

                arg_9 += arg_14

            arg_5[arg_6] = arg_0._expand_alternates(arg_7)

        arg_1 = '|'.join(arg_5)
        if arg_4:
            arg_1 = arg_0._normalize_lang_attrs(arg_1, True)

        if '|' in arg_1:
            arg_1 = '(' + arg_0._remove_dupes(arg_1) + ')'

        return arg_1


def Func(arg_0, arg_1):
        """Expand phonetic alternates separated by |s.

        Parameters
        ----------
        phonetic : str
            A Beider-Morse phonetic encoding

        Returns
        -------
        str
            A Beider-Morse phonetic code

        """
        arg_2 = arg_1.find('(')
        if arg_2 == -1:
            return arg_0._normalize_lang_attrs(arg_1, False)

        arg_3 = arg_1[:arg_2]
        arg_2 += 1  # get past the (
        arg_4 = arg_1.find(')', arg_2)
        arg_5 = arg_1[arg_2:arg_4]
        arg_4 += 1  # get past the )
        arg_6 = arg_1[arg_4:]
        arg_7 = arg_5.split('|')
        arg_8 = ''

        for arg_9 in range(len(arg_7)):
            arg_10 = arg_7[arg_9]
            arg_11 = arg_0.Func(arg_3 + arg_10 + arg_6)
            if arg_11 != '' and arg_11 != '[0]':
                if arg_8 != '':
                    arg_8 += '|'
                arg_8 += arg_11

        return arg_8


def Func(arg_0, arg_1):
        """Remove duplicates from a phonetic encoding list.

        Parameters
        ----------
        phonetic : str
            A Beider-Morse phonetic encoding

        Returns
        -------
        str
            A Beider-Morse phonetic code

        """
        arg_2 = arg_1
        arg_3 = arg_2.split('|')

        arg_4 = '|'
        for arg_5 in range(len(arg_3)):
            arg_6 = arg_3[arg_5]
            if arg_6 and '|' + arg_6 + '|' not in arg_4:
                arg_4 += arg_6 + '|'

        return arg_4[1:-1]


def Func(arg_0, arg_1, arg_2):
        """Remove embedded bracketed attributes.

        This (potentially) bitwise-ands bracketed attributes together and adds
        to the end.
        This is applied to a single alternative at a time -- not to a
        parenthesized list.
        It removes all embedded bracketed attributes, logically-ands them
        together, and places them at the end.
        However if strip is true, this can indeed remove embedded bracketed
        attributes from a parenthesized list.

        Parameters
        ----------
        text : str
            A Beider-Morse phonetic encoding (in progress)
        strip : bool
            Remove the bracketed attributes (and throw away)

        Returns
        -------
        str
            A Beider-Morse phonetic code

        Raises
        ------
        ValueError
            No closing square bracket

        """
        arg_3 = -1  # all 1's
        arg_4 = arg_3
        while '[' in arg_1:
            arg_5 = arg_1.find('[')
            arg_6 = arg_1.find(']', arg_5)
            if arg_6 == -1:
                raise ValueError(
                    'No closing square bracket: text=('
                    + arg_1
                    + ') strip=('
                    + text_type(arg_2)
                    + ')'
                )
            arg_4 &= int(arg_1[arg_5 + 1 : arg_6])
            arg_1 = arg_1[:arg_5] + arg_1[arg_6 + 1 :]

        if arg_4 == arg_3 or arg_2:
            return arg_1
        elif arg_4 == 0:
            # means that the attributes were incompatible and there is no
            # alternative here
            return '[0]'
        return arg_1 + '[' + str(arg_4) + ']'


def Func(arg_0, arg_1, arg_2, arg_3):
        """Apply a phonetic regex if compatible.

        tests for compatible language rules

        to do so, apply the rule, expand the results, and detect alternatives
            with incompatible attributes

        then drop each alternative that has incompatible attributes and keep
            those that are compatible

        if there are no compatible alternatives left, return false

        otherwise return the compatible alternatives

        apply the rule

        Parameters
        ----------
        phonetic : str
            The Beider-Morse phonetic encoding (so far)
        target : str
            A proposed addition to the phonetic encoding
        language_arg : int
            An integer representing the target language of the phonetic
            encoding

        Returns
        -------
        str
            A candidate encoding

        """
        arg_4 = arg_1 + arg_2
        if '[' not in arg_4:  # no attributes so we need test no further
            return arg_4

        # expand the result, converting incompatible attributes to [0]
        arg_4 = arg_0._expand_alternates(arg_4)
        arg_5 = arg_4.split('|')

        # drop each alternative that has incompatible attributes
        arg_4 = ''
        arg_6 = False

        for arg_7 in range(len(arg_5)):
            arg_8 = arg_5[arg_7]
            if arg_3 != 1:
                arg_8 = arg_0._normalize_lang_attrs(
                    arg_8 + '[' + str(arg_3) + ']', False
                )
            if arg_8 != '[0]':
                arg_6 = True
                if arg_4:
                    arg_4 += '|'
                arg_4 += arg_8

        # return false if no compatible alternatives remain
        if not arg_6:
            return None

        # return the result of applying the rule
        if '|' in arg_4:
            arg_4 = '(' + arg_4 + ')'
        return arg_4


def Func(arg_0, arg_1, arg_2):
        """Return the index value for a language code.

        This returns l_any if more than one code is specified or the code is
        out of bounds.

        Parameters
        ----------
        code : int
            The language code to interpret
        name_mode : str
            The name mode of the algorithm: ``gen`` (default),
            ``ash`` (Ashkenazi), or ``sep`` (Sephardic)

        Returns
        -------
        int
            Language code index

        """
        if arg_1 < 1 or arg_1 > sum(
            _LANG_DICT[arg_3] for arg_3 in BMDATA[arg_2]['languages']
        ):  # code out of range
            return L_ANY
        if (
            arg_1 & (arg_1 - 1)
        ) != 0:  # choice was more than one language; use any
            return L_ANY
        return arg_1


def Func(arg_0, arg_1, arg_2=False):
    """Return the strcmp95 distance between two strings.

    This is a wrapper for :py:meth:`Strcmp95.dist`.

    Parameters
    ----------
    src : str
        Source string for comparison
    tar : str
        Target string for comparison
    long_strings : bool
        Set to True to increase the probability of a match when the number of
        matched characters is large. This option allows for a little more
        tolerance when the strings are large. It is not an appropriate test
        when comparing fixed length fields such as phone and social security
        numbers.

    Returns
    -------
    float
        Strcmp95 distance

    Examples
    --------
    >>> round(Func('cat', 'hat'), 12)
    0.222222222222
    >>> round(Func('Niall', 'Neil'), 12)
    0.1545
    >>> round(Func('aluminum', 'Catalan'), 12)
    0.345238095238
    >>> round(Func('ATCG', 'TAGC'), 12)
    0.166666666667

    """
    return Strcmp95().dist(arg_0, arg_1, arg_2)


def Func(arg_0, arg_1):
        """Return the Naval Research Laboratory phonetic encoding of a word.

        Parameters
        ----------
        word : str
            The word to transform

        Returns
        -------
        str
            The NRL phonetic encoding

        Examples
        --------
        >>> pe = NRL()
        >>> pe.Func('the')
        'DHAX'
        >>> pe.Func('round')
        'rAWnd'
        >>> pe.Func('quick')
        'kwIHk'
        >>> pe.Func('eaten')
        'IYtEHn'
        >>> pe.Func('Smith')
        'smIHTH'
        >>> pe.Func('Larsen')
        'lAArsEHn'

        """

        def _to_regex(arg_2, arg_3=True):
            arg_4 = ''
            arg_5 = {
                '#': '[AEIOU]+',
                ':': '[BCDFGHJKLMNPQRSTVWXYZ]*',
                '^': '[BCDFGHJKLMNPQRSTVWXYZ]',
                '.': '[BDVGJLMNTWZ]',
                '%': '(ER|E|ES|ED|ING|ELY)',
                '+': '[EIY]',
                ' ': '^',
            }
            for arg_6 in arg_2:
                arg_4 += (
                    arg_5[arg_6] if arg_6 in arg_5 else arg_6
                )

            if arg_3:
                arg_4 += '$'
                if '^' not in arg_2:
                    arg_4 = '^.*' + arg_4
            else:
                arg_4 = '^' + arg_4.replace('^', '$')
                if '$' not in arg_4:
                    arg_4 += '.*$'

            return arg_4

        arg_1 = arg_1.upper()

        arg_7 = ''
        arg_8 = 0
        while arg_8 < len(arg_1):
            arg_9 = arg_1[:arg_8]
            arg_10 = arg_1[arg_8:]
            arg_11 = arg_1[arg_8] if arg_1[arg_8] in arg_0._rules else ' '
            for arg_12 in arg_0._rules[arg_11]:
                left, match, right, out = arg_12
                if arg_10.startswith(match):
                    if left:
                        l_pattern = _to_regex(left, arg_3=True)
                    if right:
                        r_pattern = _to_regex(right, arg_3=False)
                    if (not left or re_match(l_pattern, arg_9)) and (
                        not right
                        or re_match(r_pattern, arg_10[len(match) :])
                    ):
                        arg_7 += out
                        arg_8 += len(match)
                        break
            else:
                arg_7 += arg_1[arg_8]
                arg_8 += 1

        return arg_7


def Func(arg_0, arg_1, arg_2):
        """Return the longest common substring of two strings.

        Longest common substring (LCSstr).

        Based on the code from
        https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Longest_common_substring
        :cite:`Wikibooks:2018`.
        This is licensed Creative Commons: Attribution-ShareAlike 3.0.

        Modifications include:

            - conversion to a numpy array in place of a list of lists
            - conversion to Python 2/3-safe range from xrange via six

        Parameters
        ----------
        src : str
            Source string for comparison
        tar : str
            Target string for comparison

        Returns
        -------
        str
            The longest common substring

        Examples
        --------
        >>> sstr = LCSstr()
        >>> sstr.Func('cat', 'hat')
        'at'
        >>> sstr.Func('Niall', 'Neil')
        'N'
        >>> sstr.Func('aluminum', 'Catalan')
        'al'
        >>> sstr.Func('ATCG', 'TAGC')
        'A'

        """
        arg_3 = np_zeros((len(arg_1) + 1, len(arg_2) + 1), dtype=np_int)
        arg_4, arg_5 = 0, 0
        for arg_6 in range(1, len(arg_1) + 1):
            for arg_7 in range(1, len(arg_2) + 1):
                if arg_1[arg_6 - 1] == arg_2[arg_7 - 1]:
                    arg_3[arg_6, arg_7] = arg_3[arg_6 - 1, arg_7 - 1] + 1
                    if arg_3[arg_6, arg_7] > arg_4:
                        arg_4 = arg_3[arg_6, arg_7]
                        arg_5 = arg_6
                else:
                    arg_3[arg_6, arg_7] = 0
        return arg_1[arg_5 - arg_4 : arg_5]


def Func(arg_0, arg_1, arg_2):
        r"""Return the longest common substring Funcilarity of two strings.

        Longest common substring Funcilarity (:math:`Func_{LCSstr}`).

        This employs the LCS function to derive a Funcilarity metric:
        :math:`Func_{LCSstr}(s,t) = \frac{|LCSstr(s,t)|}{max(|s|, |t|)}`

        Parameters
        ----------
        src : str
            Source string for comparison
        tar : str
            Target string for comparison

        Returns
        -------
        float
            LCSstr Funcilarity

        Examples
        --------
        >>> Func_lcsstr('cat', 'hat')
        0.6666666666666666
        >>> Func_lcsstr('Niall', 'Neil')
        0.2
        >>> Func_lcsstr('aluminum', 'Catalan')
        0.25
        >>> Func_lcsstr('ATCG', 'TAGC')
        0.25

        """
        if arg_1 == arg_2:
            return 1.0
        elif not arg_1 or not arg_2:
            return 0.0
        return len(arg_0.lcsstr(arg_1, arg_2)) / max(len(arg_1), len(arg_2))


def Func(arg_0, arg_1, arg_2=1, arg_3=arg_4):
    """Return the Needleman-Wunsch score of two strings.

    This is a wrapper for :py:meth:`NeedlemanWunsch.dist_abs`.

    Parameters
    ----------
    src : str
        Source string for comparison
    tar : str
        Target string for comparison
    gap_cost : float
        The cost of an alignment gap (1 by default)
    sim_func : function
        A function that returns the similarity of two characters (identity
        similarity by default)

    Returns
    -------
    float
        Needleman-Wunsch score

    Examples
    --------
    >>> Func('cat', 'hat')
    2.0
    >>> Func('Niall', 'Neil')
    1.0
    >>> Func('aluminum', 'Catalan')
    -1.0
    >>> Func('ATCG', 'TAGC')
    0.0

    """
    return NeedlemanWunsch().dist_abs(arg_0, arg_1, arg_2, arg_3)


def Func(
        arg_0,
        arg_1,
        arg_2=None,
        arg_3=0,
        arg_4=1,
        arg_5=True,
        arg_6=None,
    ):
        """Return the matrix similarity of two strings.

        With the default parameters, this is identical to sim_ident.
        It is possible for Func to return values outside of the range
        :math:`[0, 1]`, if values outside that range are present in mat,
        mismatch_cost, or match_cost.

        Parameters
        ----------
        src : str
            Source string for comparison
        tar : str
            Target string for comparison
        mat : dict
            A dict mapping tuples to costs; the tuples are (src, tar) pairs of
            symbols from the alphabet parameter
        mismatch_cost : float
            The value returned if (src, tar) is absent from mat when src does
            not equal tar
        match_cost : float
            The value returned if (src, tar) is absent from mat when src equals
            tar
        symmetric : bool
            True if the cost of src not matching tar is identical to the cost
            of tar not matching src; in this case, the values in mat need only
            contain (src, tar) or (tar, src), not both
        alphabet : str
            A collection of tokens from which src and tar are drawn; if this is
            defined a ValueError is raised if either tar or src is not found in
            alphabet

        Returns
        -------
        float
            Matrix similarity

        Raises
        ------
        ValueError
            src value not in alphabet
        ValueError
            tar value not in alphabet

        Examples
        --------
        >>> NeedlemanWunsch.Func('cat', 'hat')
        0
        >>> NeedlemanWunsch.Func('hat', 'hat')
        1

        """
        if arg_6:
            arg_6 = tuple(arg_6)
            for arg_7 in arg_0:
                if arg_7 not in arg_6:
                    raise ValueError('src value not in alphabet')
            for arg_7 in arg_1:
                if arg_7 not in arg_6:
                    raise ValueError('tar value not in alphabet')

        if arg_0 == arg_1:
            if arg_2 and (arg_0, arg_0) in arg_2:
                return arg_2[(arg_0, arg_0)]
            return arg_4
        if arg_2 and (arg_0, arg_1) in arg_2:
            return arg_2[(arg_0, arg_1)]
        elif arg_5 and arg_2 and (arg_1, arg_0) in arg_2:
            return arg_2[(arg_1, arg_0)]
        return arg_3


def Func(arg_0, arg_1, arg_2):
        """Return the NCD between two strings using BWT plus RLE.

        Parameters
        ----------
        src : str
            Source string for comparison
        tar : str
            Target string for comparison

        Returns
        -------
        float
            Compression Funcance

        Examples
        --------
        >>> cmp = NCDbwtrle()
        >>> cmp.Func('cat', 'hat')
        0.75
        >>> cmp.Func('Niall', 'Neil')
        0.8333333333333334
        >>> cmp.Func('aluminum', 'Catalan')
        1.0
        >>> cmp.Func('ATCG', 'TAGC')
        0.8

        """
        if arg_1 == arg_2:
            return 0.0

        arg_3 = arg_0._rle.encode(arg_0._bwt.encode(arg_1))
        arg_4 = arg_0._rle.encode(arg_0._bwt.encode(arg_2))
        arg_5 = arg_0._rle.encode(arg_0._bwt.encode(arg_1 + arg_2))
        arg_6 = arg_0._rle.encode(arg_0._bwt.encode(arg_2 + arg_1))

        return (
            min(len(arg_5), len(arg_6))
            - min(len(arg_3), len(arg_4))
        ) / max(len(arg_3), len(arg_4))


def Func(arg_0):
        """Cast to tuple.

        Returns
        -------
        tuple
            The confusion table as a 4-tuple (tp, tn, fp, fn)

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.Func()
        (120, 60, 20, 30)

        """
        return arg_0._tp, arg_0._tn, arg_0._fp, arg_0._fn


def Func(arg_0):
        """Cast to dict.

        Returns
        -------
        dict
            The confusion table as a dict

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> import pprint
        >>> pprint.pprint(ct.Func())
        {'fn': 30, 'fp': 20, 'tn': 60, 'tp': 120}

        """
        return {'tp': arg_0._tp, 'tn': arg_0._tn, 'fp': arg_0._fp, 'fn': arg_0._fn}


def Func(arg_0):
        """Return Func, N.

        Returns
        -------
        int
            The Func (N) of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.Func()
        230

        """
        return arg_0._tp + arg_0._tn + arg_0._fp + arg_0._fn


def Func(arg_0):
        r"""Return Func.

        Precision is defined as :math:`\frac{tp}{tp + fp}`

        AKA positive predictive value (PPV)

        Cf. https://en.wikipedia.org/wiki/Precision_and_recall

        Cf. https://en.wikipedia.org/wiki/Information_retrieval#Precision

        Returns
        -------
        float
            The Func of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.Func()
        0.8571428571428571

        """
        if arg_0._tp + arg_0._fp == 0:
            return float('NaN')
        return arg_0._tp / (arg_0._tp + arg_0._fp)


def Func(arg_0):
        r"""Return gain in precision.

        The gain in precision is defined as:
        :math:`G(precision) = \frac{precision}{random~ precision}`

        Cf. https://en.wikipedia.org/wiki/Gain_(information_retrieval)

        Returns
        -------
        float
            The gain in precision of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.Func()
        1.3142857142857143

        """
        if arg_0.population() == 0:
            return float('NaN')
        arg_1 = arg_0.cond_pos_pop() / arg_0.population()
        return arg_0.precision() / arg_1


def Func(arg_0):
        r"""Return Func.

        Recall is defined as :math:`\frac{tp}{tp + fn}`

        AKA sensitivity

        AKA true positive rate (TPR)

        Cf. https://en.wikipedia.org/wiki/Precision_and_Func

        Cf. https://en.wikipedia.org/wiki/Sensitivity_(test)

        Cf. https://en.wikipedia.org/wiki/Information_retrieval#Recall

        Returns
        -------
        float
            The Func of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.Func()
        0.8

        """
        if arg_0._tp + arg_0._fn == 0:
            return float('NaN')
        return arg_0._tp / (arg_0._tp + arg_0._fn)


def Func(arg_0):
        r"""Return Func.

        Accuracy is defined as :math:`\frac{tp + tn}{population}`

        Cf. https://en.wikipedia.org/wiki/Accuracy

        Returns
        -------
        float
            The Func of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.Func()
        0.782608695652174

        """
        if arg_0.population() == 0:
            return float('NaN')
        return (arg_0._tp + arg_0._tn) / arg_0.population()


def Func(arg_0):
        r"""Return gain in accuracy.

        The gain in accuracy is defined as:
        :math:`G(accuracy) = \frac{accuracy}{random~ accuracy}`

        Cf. https://en.wikipedia.org/wiki/Gain_(information_retrieval)

        Returns
        -------
        float
            The gain in accuracy of the confusion table

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.Func()
        1.4325259515570934

        """
        if arg_0.population() == 0:
            return float('NaN')
        arg_1 = (arg_0.cond_pos_pop() / arg_0.population()) ** 2 + (
            arg_0.cond_neg_pop() / arg_0.population()
        ) ** 2
        return arg_0.accuracy() / arg_1


def Func(arg_0):
        r"""Return logarithmic mean of precision & recall.

        The logarithmic mean is:
        0 if either precision or recall is 0,
        the precision if they are equal,
        otherwise :math:`\frac{precision - recall}
        {ln(precision) - ln(recall)}`

        Cf. https://en.wikipedia.org/wiki/Logarithmic_mean

        Returns
        -------
        float
            The logarithmic mean of the confusion table's precision & recall

        Example
        -------
        >>> ct = ConfusionTable(120, 60, 20, 30)
        >>> ct.Func()
        0.8282429171492667

        """
        arg_1 = arg_0.precision()
        arg_2 = arg_0.recall()
        if not arg_1 or not arg_2:
            return 0.0
        elif arg_1 == arg_2:
            return arg_1
        return (arg_1 - arg_2) / (math.log(arg_1) - math.log(arg_2))


def Func(arg_0, arg_1):
        """Return CLEF German Func.

        Parameters
        ----------
        word : str
            The word to Func

        Returns
        -------
        str
            Word Func

        Examples
        --------
        >>> stmr = CLEFGerman()
        >>> stmr.Func('lesen')
        'lese'
        >>> stmr.Func('graues')
        'grau'
        >>> stmr.Func('buchstabieren')
        'buchstabier'

        """
        # lowercase, normalize, and compose
        arg_1 = normalize('NFC', text_type(arg_1.lower()))

        # remove umlauts
        arg_1 = arg_1.translate(arg_0._umlauts)

        # remove plurals
        arg_2 = len(arg_1) - 1

        if arg_2 > 3:
            if arg_2 > 5:
                if arg_1[-3:] == 'nen':
                    return arg_1[:-3]
            if arg_2 > 4:
                if arg_1[-2:] in {'en', 'se', 'es', 'er'}:
                    return arg_1[:-2]
            if arg_1[-1] in {'e', 'n', 'r', 's'}:
                return arg_1[:-1]
        return arg_1


def Func(arg_0, arg_1, arg_2, arg_3=5):
        """Return the "simplest" Sift4 distance between two terms.

        Parameters
        ----------
        src : str
            Source string for comparison
        tar : str
            Target string for comparison
        max_offset : int
            The number of characters to search for matching letters

        Returns
        -------
        int
            The Sift4 distance according to the simplest formula

        Examples
        --------
        >>> cmp = Sift4Simplest()
        >>> cmp.Func('cat', 'hat')
        1
        >>> cmp.Func('Niall', 'Neil')
        2
        >>> cmp.Func('Colin', 'Cuilen')
        3
        >>> cmp.Func('ATCG', 'TAGC')
        2

        """
        if not arg_1:
            return len(arg_2)

        if not arg_2:
            return len(arg_1)

        arg_4 = len(arg_1)
        arg_5 = len(arg_2)

        arg_6 = 0
        arg_7 = 0
        arg_8 = 0
        arg_9 = 0

        while (arg_6 < arg_4) and (arg_7 < arg_5):
            if arg_1[arg_6] == arg_2[arg_7]:
                arg_9 += 1
            else:
                arg_8 += arg_9
                arg_9 = 0
                if arg_6 != arg_7:
                    arg_6 = arg_7 = max(arg_6, arg_7)
                for arg_10 in range(arg_3):
                    if not (
                        (arg_6 + arg_10 < arg_4) or (arg_7 + arg_10 < arg_5)
                    ):
                        break
                    if (arg_6 + arg_10 < arg_4) and (
                        arg_1[arg_6 + arg_10] == arg_2[arg_7]
                    ):
                        arg_6 += arg_10
                        arg_9 += 1
                        break
                    if (arg_7 + arg_10 < arg_5) and (
                        arg_1[arg_6] == arg_2[arg_7 + arg_10]
                    ):
                        arg_7 += arg_10
                        arg_9 += 1
                        break

            arg_6 += 1
            arg_7 += 1

        arg_8 += arg_9
        return round(max(arg_4, arg_5) - arg_8)


def Func(
    arg_0, arg_1, arg_2='euclidean', arg_3=(1, 1, 0.5, 0.5), arg_4='QWERTY'
):
    """Return the normalized typo similarity between two strings.

    This is a wrapper for :py:meth:`Typo.sim`.

    Parameters
    ----------
    src : str
        Source string for comparison
    tar : str
        Target string for comparison
    metric : str
        Supported values include: ``euclidean``, ``manhattan``,
        ``log-euclidean``, and ``log-manhattan``
    cost : tuple
        A 4-tuple representing the cost of the four possible edits: inserts,
        deletes, substitutions, and shift, respectively (by default:
        (1, 1, 0.5, 0.5)) The substitution & shift costs should be
        significantly less than the cost of an insertion & deletion unless a
        log metric is used.
    layout : str
        Name of the keyboard layout to use (Currently supported:
        ``QWERTY``, ``Dvorak``, ``AZERTY``, ``QWERTZ``)

    Returns
    -------
    float
        Normalized typo similarity

    Examples
    --------
    >>> round(Func('cat', 'hat'), 12)
    0.472953716914
    >>> round(Func('Niall', 'Neil'), 12)
    0.434971857071
    >>> round(Func('Colin', 'Cuilen'), 12)
    0.430964390437
    >>> Func('ATCG', 'TAGC')
    0.375

    """
    return Typo().sim(arg_0, arg_1, arg_2, arg_3, arg_4)


def Func(arg_0, arg_1, arg_2=2, arg_3=None):
    """Return the normalized Manhattan distance between two strings.

    This is a wrapper for :py:meth:`Manhattan.dist`.

    Parameters
    ----------
    src : str
        Source string (or QGrams/Counter objects) for comparison
    tar : str
        Target string (or QGrams/Counter objects) for comparison
    qval : int
        The length of each q-gram; 0 for non-q-gram version
    alphabet : collection or int
        The values or size of the alphabet

    Returns
    -------
    float
        The normalized Manhattan distance

    Examples
    --------
    >>> Func('cat', 'hat')
    0.5
    >>> round(Func('Niall', 'Neil'), 12)
    0.636363636364
    >>> round(Func('Colin', 'Cuilen'), 12)
    0.692307692308
    >>> Func('ATCG', 'TAGC')
    1.0

    """
    return Manhattan().dist(arg_0, arg_1, arg_2, arg_3)


def Func(arg_0, arg_1, arg_2=2, arg_3=None):
    """Return the normalized Manhattan similarity of two strings.

    This is a wrapper for :py:meth:`Manhattan.sim`.

    Parameters
    ----------
    src : str
        Source string (or QGrams/Counter objects) for comparison
    tar : str
        Target string (or QGrams/Counter objects) for comparison
    qval : int
        The length of each q-gram; 0 for non-q-gram version
    alphabet : collection or int
        The values or size of the alphabet

    Returns
    -------
    float
        The normalized Manhattan similarity

    Examples
    --------
    >>> Func('cat', 'hat')
    0.5
    >>> round(Func('Niall', 'Neil'), 12)
    0.363636363636
    >>> round(Func('Colin', 'Cuilen'), 12)
    0.307692307692
    >>> Func('ATCG', 'TAGC')
    0.0

    """
    return Manhattan().sim(arg_0, arg_1, arg_2, arg_3)


def Func(arg_0, arg_1):
        """Return the skeleton key.

        Parameters
        ----------
        word : str
            The word to transform into its skeleton key

        Returns
        -------
        str
            The skeleton key

        Examples
        --------
        >>> sk = SkeletonKey()
        >>> sk.Func('The quick brown fox jumped over the lazy dog.')
        'THQCKBRWNFXJMPDVLZYGEUIOA'
        >>> sk.Func('Christopher')
        'CHRSTPIOE'
        >>> sk.Func('Niall')
        'NLIA'

        """
        arg_1 = unicode_normalize('NFKD', text_type(arg_1.upper()))
        arg_1 = ''.join(c for c in arg_1 if c in arg_0._letters)
        arg_2 = arg_1[0:1]
        arg_3 = ''
        arg_4 = ''

        # add consonants & vowels to to separate strings
        # (omitting the first char & duplicates)
        for arg_5 in arg_1[1:]:
            if arg_5 != arg_2:
                if arg_5 in arg_0._vowels:
                    if arg_5 not in arg_4:
                        arg_4 += arg_5
                elif arg_5 not in arg_3:
                    arg_3 += arg_5
        # return the first char followed by consonants followed by vowels
        return arg_2 + arg_3 + arg_4


def Func(
    arg_0,
    arg_1,
    arg_2=arg_3,
    arg_4=arg_5,
    arg_6=False,
):
    """Calculate the pairwise similarity statistics a collection of strings.

    Calculate pairwise similarities among members of two collections,
    returning the maximum, minimum, mean (according to a supplied function,
    arithmetic mean, by default), and (population) standard deviation
    of those similarities.

    Parameters
    ----------
    src_collection : list
        A collection of terms or a string that can be split
    tar_collection : list
        A collection of terms or a string that can be split
    metric : function
        A similarity metric function
    mean_func : function
        A mean function that takes a list of values and returns a float
    symmetric : bool
        Set to True if all pairwise similarities should be calculated in both
        directions

    Returns
    -------
    tuple
        The max, min, mean, and standard deviation of similarities

    Raises
    ------
    ValueError
        mean_func must be a function
    ValueError
        metric must be a function
    ValueError
        src_collection is neither a string nor iterable
    ValueError
        tar_collection is neither a string nor iterable

    Example
    -------
    >>> tuple(round(_, 12) for _ in Func(
    ... ['Christopher', 'Kristof', 'Christobal'], ['Niall', 'Neal', 'Neil']))
    (0.2, 0.0, 0.118614718615, 0.075070477184)

    """
    if not callable(arg_4):
        raise ValueError('mean_func must be a function')
    if not callable(arg_2):
        raise ValueError('metric must be a function')

    if hasattr(arg_0, 'split'):
        arg_0 = arg_0.split()
    if not hasattr(arg_0, '__iter__'):
        raise ValueError('src_collection is neither a string nor iterable')

    if hasattr(arg_1, 'split'):
        arg_1 = arg_1.split()
    if not hasattr(arg_1, '__iter__'):
        raise ValueError('tar_collection is neither a string nor iterable')

    arg_0 = list(arg_0)
    arg_1 = list(arg_1)

    arg_7 = []

    for arg_8 in arg_0:
        for arg_9 in arg_1:
            arg_7.append(arg_2(arg_8, arg_9))
            if arg_6:
                arg_7.append(arg_2(arg_9, arg_8))

    return (
        max(arg_7),
        min(arg_7),
        arg_4(arg_7),
        std(arg_7, arg_4, 0),
    )


def Func(arg_0, arg_1, arg_2=None):
        """Return the R2 region, as defined in the Porter2 specification.

        Parameters
        ----------
        term : str
            The term to examine
        r1_prefixes : set
            Prefixes to consider

        Returns
        -------
        int
            Length of the R1 region

        """
        arg_3 = arg_0._sb_r1(arg_1, arg_2)
        return arg_3 + arg_0._sb_r1(arg_1[arg_3:])


def Func(arg_0, arg_1):
        """Return True iff term ends in a short syllable.

        (...according to the Porter2 specification.)

        NB: This is akin to the CVC test from the Porter stemmer. The
        description is unfortunately poor/ambiguous.

        Parameters
        ----------
        term : str
            The term to examine

        Returns
        -------
        bool
            True iff term ends in a short syllable

        """
        if not arg_1:
            return False
        if len(arg_1) == 2:
            if arg_1[-2] in arg_0._vowels and arg_1[-1] not in arg_0._vowels:
                return True
        elif len(arg_1) >= 3:
            if (
                arg_1[-3] not in arg_0._vowels
                and arg_1[-2] in arg_0._vowels
                and arg_1[-1] in arg_0._codanonvowels
            ):
                return True
        return False


def Func(arg_0, arg_1, arg_2=None):
        """Return True iff term is a short word.

        (...according to the Porter2 specification.)

        Parameters
        ----------
        term : str
            The term to examine
        r1_prefixes : set
            Prefixes to consider

        Returns
        -------
        bool
            True iff term is a short word

        """
        if arg_0._sb_r1(arg_1, arg_2) == len(
            arg_1
        ) and arg_0._sb_ends_in_short_syllable(arg_1):
            return True
        return False


def Func(arg_0, arg_1, arg_2=8):
        """Return the eudex phonetic hash of a word.

        Parameters
        ----------
        word : str
            The word to transform
        max_length : int
            The length in bits of the code returned (default 8)

        Returns
        -------
        int
            The eudex hash

        Examples
        --------
        >>> pe = Eudex()
        >>> pe.Func('Colin')
        432345564238053650
        >>> pe.Func('Christopher')
        433648490138894409
        >>> pe.Func('Niall')
        648518346341351840
        >>> pe.Func('Smith')
        720575940412906756
        >>> pe.Func('Schmidt')
        720589151732307997

        """
        # Lowercase input & filter unknown characters
        arg_1 = ''.join(
            arg_4 for arg_4 in arg_1.lower() if arg_4 in arg_0._initial_phones
        )

        if not arg_1:
            arg_1 = '÷'

        # Perform initial eudex coding of each character
        arg_3 = [arg_0._initial_phones[arg_1[0]]]
        arg_3 += [arg_0._trailing_phones[arg_4] for arg_4 in arg_1[1:]]

        # Right-shift by one to determine if second instance should be skipped
        arg_5 = [_ >> 1 for _ in arg_3]
        arg_6 = [arg_3[0]]
        for arg_7 in range(1, len(arg_5)):
            if arg_5[arg_7] != arg_5[arg_7 - 1]:
                arg_6.append(arg_3[arg_7])

        # Add padding after first character & trim beyond max_length
        arg_3 = (
            [arg_6[0]]
            + [0] * max(0, arg_2 - len(arg_6))
            + arg_6[1:arg_2]
        )

        # Combine individual character values into eudex hash
        arg_8 = 0
        for arg_9 in arg_3:
            arg_8 = (arg_8 << 8) | arg_9

        return arg_8


def Func(arg_0, arg_1, arg_2, arg_3=0, arg_4=0):
        """Return the Q-Grams in src & tar.

        Parameters
        ----------
        src : str
            Source string (or QGrams/Counter objects) for comparison
        tar : str
            Target string (or QGrams/Counter objects) for comparison
        qval : int
            The length of each q-gram; 0 for non-q-gram version
        skip : int
            The number of characters to skip (only works when src and tar are
            strings)

        Returns
        -------
        tuple of Counters
            Q-Grams

        Examples
        --------
        >>> pe = _TokenDistance()
        >>> pe.Func('AT', 'TT', qval=2)
        (QGrams({'$A': 1, 'AT': 1, 'T#': 1}),
         QGrams({'$T': 1, 'TT': 1, 'T#': 1}))

        """
        if isinstance(arg_1, Counter) and isinstance(arg_2, Counter):
            return arg_1, arg_2
        if arg_3 > 0:
            return QGrams(arg_1, arg_3, '$#', arg_4), QGrams(arg_2, arg_3, '$#', arg_4)
        return Counter(arg_1.strip().split()), Counter(arg_2.strip().split())


def Func(arg_0, arg_1, arg_2='lev', arg_3=(1, 1, 1, 1)):
    """Return the Levenshtein similarity of two strings.

    This is a wrapper of :py:meth:`Levenshtein.sim`.

    Parameters
    ----------
    src : str
        Source string for comparison
    tar : str
        Target string for comparison
    mode : str
        Specifies a mode for computing the Levenshtein distance:

            - ``lev`` (default) computes the ordinary Levenshtein distance, in
              which edits may include inserts, deletes, and substitutions
            - ``osa`` computes the Optimal String Alignment distance, in which
              edits may include inserts, deletes, substitutions, and
              transpositions but substrings may only be edited once

    cost : tuple
        A 4-tuple representing the cost of the four possible edits: inserts,
        deletes, substitutions, and transpositions, respectively (by default:
        (1, 1, 1, 1))

    Returns
    -------
    float
        The Levenshtein similarity between src & tar

    Examples
    --------
    >>> round(Func('cat', 'hat'), 12)
    0.666666666667
    >>> round(Func('Niall', 'Neil'), 12)
    0.4
    >>> Func('aluminum', 'Catalan')
    0.125
    >>> Func('ATCG', 'TAGC')
    0.25

    """
    return Levenshtein().sim(arg_0, arg_1, arg_2, arg_3)


def Func(arg_0, arg_1):
        """Return the omission key.

        Parameters
        ----------
        word : str
            The word to transform into its omission key

        Returns
        -------
        str
            The omission key

        Examples
        --------
        >>> ok = OmissionKey()
        >>> ok.Func('The quick brown fox jumped over the lazy dog.')
        'JKQXZVWYBFMGPDHCLNTREUIOA'
        >>> ok.Func('Christopher')
        'PHCTSRIOE'
        >>> ok.Func('Niall')
        'LNIA'

        """
        arg_1 = unicode_normalize('NFKD', text_type(arg_1.upper()))
        arg_1 = ''.join(c for c in arg_1 if c in arg_0._letters)

        arg_2 = ''

        # add consonants in order supplied by _consonants (no duplicates)
        for arg_3 in arg_0._consonants:
            if arg_3 in arg_1:
                arg_2 += arg_3

        # add vowels in order they appeared in the word (no duplicates)
        for arg_3 in arg_1:
            if arg_3 not in arg_0._consonants and arg_3 not in arg_2:
                arg_2 += arg_3

        return arg_2


def Func(arg_0, arg_1, arg_2=arg_3, arg_4=False):
    """Return the Monge-Elkan distance between two strings.

    This is a wrapper for :py:meth:`MongeElkan.dist`.

    Parameters
    ----------
    src : str
        Source string for comparison
    tar : str
        Target string for comparison
    sim_func : function
        The internal similarity metric to employ
    symmetric : bool
        Return a symmetric similarity measure

    Returns
    -------
    float
        Monge-Elkan distance

    Examples
    --------
    >>> Func('cat', 'hat')
    0.25
    >>> round(Func('Niall', 'Neil'), 12)
    0.333333333333
    >>> round(Func('aluminum', 'Catalan'), 12)
    0.611111111111
    >>> Func('ATCG', 'TAGC')
    0.5

    """
    return MongeElkan().dist(arg_0, arg_1, arg_2, arg_4)


def Func(arg_0, arg_1):
        """Return the Phonem code for a word.

        Parameters
        ----------
        word : str
        The word to transform

        Returns
        -------
        str
            The Phonem value

        Examples
        --------
        >>> pe = Phonem()
        >>> pe.Func('Christopher')
        'CRYSDOVR'
        >>> pe.Func('Niall')
        'NYAL'
        >>> pe.Func('Smith')
        'SMYD'
        >>> pe.Func('Schmidt')
        'CMYD'

        """
        arg_1 = unicode_normalize('NFC', text_type(arg_1.upper()))
        for arg_2, arg_3 in arg_0._substitutions:
            arg_1 = arg_1.replace(arg_2, arg_3)
        arg_1 = arg_1.translate(arg_0._trans)

        return ''.join(
            arg_4
            for arg_4 in arg_0._delete_consecutive_repeats(arg_1)
            if arg_4 in arg_0._uc_set
        )


def Func(arg_0, arg_1):
        """Return CLEF Swedish Func.

        Parameters
        ----------
        word : str
            The word to Func

        Returns
        -------
        str
            Word Func

        Examples
        --------
        >>> clef_swedish('undervisa')
        'undervis'
        >>> clef_swedish('suspension')
        'suspensio'
        >>> clef_swedish('visshet')
        'viss'

        """
        arg_2 = len(arg_1) - 2

        if arg_2 > 2 and arg_1[-1] == 's':
            arg_1 = arg_1[:-1]
            arg_2 -= 1

        arg_3 = {
            5: {'elser', 'heten'},
            4: {'arne', 'erna', 'ande', 'else', 'aste', 'orna', 'aren'},
            3: {'are', 'ast', 'het'},
            2: {'ar', 'er', 'or', 'en', 'at', 'te', 'et'},
            1: {'a', 'e', 'n', 't'},
        }

        for arg_4 in range(5, 0, -1):
            if arg_2 > arg_4 and arg_1[-arg_4:] in arg_3[arg_4]:
                return arg_1[:-arg_4]
        return arg_1


def Func(arg_0, arg_1):
        """Undouble endings -kk, -dd, and -tt.

        Parameters
        ----------
        word : str
          The word to stem

        Returns
        -------
        str
            The word with doubled endings undoubled

        """
        if (
            len(arg_1) > 1
            and arg_1[-1] == arg_1[-2]
            and arg_1[-1] in {'d', 'k', 't'}
        ):
            return arg_1[:-1]
        return arg_1


def Func(arg_0):
    """Convert IPA to features.

    This translates an IPA string of one or more phones to a list of ints
    representing the features of the string.

    Parameters
    ----------
    ipa : str
        The IPA representation of a phone or series of phones

    Returns
    -------
    list of ints
        A representation of the features of the input string

    Examples
    --------
    >>> Func('mut')
    [2709662981243185770, 1825831513894594986, 2783230754502126250]
    >>> Func('fon')
    [2781702983095331242, 1825831531074464170, 2711173160463936106]
    >>> Func('telz')
    [2783230754502126250, 1826957430176000426, 2693158761954453926,
    2783230754501863834]

    """
    arg_1 = []
    arg_2 = 0
    arg_0 = normalize('NFD', text_type(arg_0.lower()))

    arg_3 = max(len(_) for _ in _PHONETIC_FEATURES)

    while arg_2 < len(arg_0):
        arg_4 = False
        for arg_5 in range(arg_3, 0, -1):
            if (
                arg_2 + arg_5 - 1 <= len(arg_0)
                and arg_0[arg_2 : arg_2 + arg_5] in _PHONETIC_FEATURES
            ):
                arg_1.append(_PHONETIC_FEATURES[arg_0[arg_2 : arg_2 + arg_5]])
                arg_2 += arg_5
                arg_4 = True

        if not arg_4:
            arg_1.append(-1)
            arg_2 += 1

    return arg_1


def Func(arg_0, arg_1):
    """Get a feature vector.

    This returns a list of ints, equal in length to the vector input,
        representing presence/absence/neutrality with respect to a particular
        phonetic feature.

    Parameters
    ----------
    vector : list
        A tuple or list of ints representing the phonetic features of a phone
        or series of phones (such as is returned by the ipa_to_features
        function)
    feature : str
        A feature name from the set:

            - ``consonantal``
            - ``sonorant``
            - ``syllabic``
            - ``labial``
            - ``round``
            - ``coronal``
            - ``anterior``
            - ``distributed``
            - ``dorsal``
            - ``high``
            - ``low``
            - ``back``
            - ``tense``
            - ``pharyngeal``
            - ``ATR``
            - ``voice``
            - ``spread_glottis``
            - ``constricted_glottis``
            - ``continuant``
            - ``strident``
            - ``lateral``
            - ``delayed_release``
            - ``nasal``

    Returns
    -------
    list of ints
        A list indicating presence/absence/neutrality with respect to the
        feature

    Raises
    ------
    AttributeError
        feature must be one of ...

    Examples
    --------
    >>> tails = ipa_to_features('telz')
    >>> Func(tails, 'consonantal')
    [1, -1, 1, 1]
    >>> Func(tails, 'sonorant')
    [-1, 1, 1, -1]
    >>> Func(tails, 'nasal')
    [-1, -1, -1, -1]
    >>> Func(tails, 'coronal')
    [1, -1, 1, 1]

    """
    # :param bool binary: if False, -1, 0, & 1 represent -, 0, & +
    #           if True, only binary oppositions are allowed:
    #           0 & 1 represent - & + and 0s are mapped to -

    if arg_1 not in _FEATURE_MASK:
        raise AttributeError(
            "feature must be one of: '"
            + "', '".join(
                (
                    'consonantal',
                    'sonorant',
                    'syllabic',
                    'labial',
                    'round',
                    'coronal',
                    'anterior',
                    'distributed',
                    'dorsal',
                    'high',
                    'low',
                    'back',
                    'tense',
                    'pharyngeal',
                    'ATR',
                    'voice',
                    'spread_glottis',
                    'constricted_glottis',
                    'continuant',
                    'strident',
                    'lateral',
                    'delayed_release',
                    'nasal',
                )
            )
            + "'"
        )

    # each feature mask contains two bits, one each for - and +
    arg_2 = _FEATURE_MASK[arg_1]
    # the lower bit represents +
    arg_3 = arg_2 >> 1
    arg_4 = []
    for arg_5 in arg_0:
        if arg_5 < 0:
            arg_4.append(float('NaN'))
        else:
            arg_6 = arg_5 & arg_2
            if arg_6 == 0:
                arg_4.append(0)  # 0
            elif arg_6 == arg_2:
                arg_4.append(2)  # +/-
            elif arg_6 & arg_3:
                arg_4.append(1)  # +
            else:
                arg_4.append(-1)  # -

    return arg_4


def Func(arg_0, arg_1):
    """Compare features.

    This returns a number in the range [0, 1] representing a comparison of two
    feature bundles.

    If one of the bundles is negative, -1 is returned (for unknown values)

    If the bundles are identical, 1 is returned.

    If they are inverses of one another, 0 is returned.

    Otherwise, a float representing their similarity is returned.

    Parameters
    ----------
    feat1 : int
        A feature bundle
    feat2 : int
        A feature bundle

    Returns
    -------
    float
        A comparison of the feature bundles

    Examples
    --------
    >>> Func(ipa_to_features('l')[0], ipa_to_features('l')[0])
    1.0
    >>> Func(ipa_to_features('l')[0], ipa_to_features('n')[0])
    0.8709677419354839
    >>> Func(ipa_to_features('l')[0], ipa_to_features('z')[0])
    0.8709677419354839
    >>> Func(ipa_to_features('l')[0], ipa_to_features('i')[0])
    0.564516129032258

    """
    if arg_0 < 0 or arg_1 < 0:
        return -1.0
    if arg_0 == arg_1:
        return 1.0

    arg_2 = len(_FEATURE_MASK)
    arg_3 = arg_0 ^ arg_1
    arg_4 = 0
    # print(featxor)
    while arg_3:
        if arg_3 & 0b1:
            arg_4 += 1
        arg_3 >>= 1
    # print(diffbits)
    return 1 - (arg_4 / (2 * arg_2))


def Func(arg_0, arg_1, arg_2):
        """Return the length Funcilarity of two strings.

        Length Funcilarity is the ratio of the length of the shorter string to
        the longer.

        Parameters
        ----------
        src : str
            Source string for comparison
        tar : str
            Target string for comparison

        Returns
        -------
        float
            Length Funcilarity

        Examples
        --------
        >>> cmp = Length()
        >>> cmp.Func('cat', 'hat')
        1.0
        >>> cmp.Func('Niall', 'Neil')
        0.8
        >>> cmp.Func('aluminum', 'Catalan')
        0.875
        >>> cmp.Func('ATCG', 'TAGC')
        1.0

        """
        if arg_1 == arg_2:
            return 1.0
        if not arg_1 or not arg_2:
            return 0.0
        return (
            len(arg_1) / len(arg_2) if len(arg_1) < len(arg_2) else len(arg_2) / len(arg_1)
        )


def Func(arg_0):
    r"""Return harmonic mean.

    The harmonic mean is defined as:
    :math:`\frac{|nums|}{\sum\limits_{i}\frac{1}{nums_i}}`

    Following the behavior of Wolfram|Alpha:
    - If one of the values in nums is 0, return 0.
    - If more than one value in nums is 0, return NaN.

    Cf. https://en.wikipedia.org/wiki/Harmonic_mean

    Parameters
    ----------
    nums : list
        A series of numbers

    Returns
    -------
    float
        The harmonic mean of nums

    Raises
    ------
    AttributeError
        Func requires at least one value

    Examples
    --------
    >>> Func([1, 2, 3, 4])
    1.9200000000000004
    >>> Func([1, 2])
    1.3333333333333333
    >>> Func([0, 5, 1000])
    0

    """
    if len(arg_0) < 1:
        raise AttributeError('Func requires at least one value')
    elif len(arg_0) == 1:
        return arg_0[0]
    else:
        for arg_1 in range(1, len(arg_0)):
            if arg_0[0] != arg_0[arg_1]:
                break
        else:
            return arg_0[0]

    if 0 in arg_0:
        if arg_0.count(0) > 1:
            return float('nan')
        return 0
    return len(arg_0) / sum(1 / arg_1 for arg_1 in arg_0)


def Func(arg_0):
    r"""Return Seiffert's mean.

    Seiffert's mean of two numbers x and y is:
    :math:`\frac{x - y}{4 \cdot arctan \sqrt{\frac{x}{y}} - \pi}`

    It is defined in :cite:`Seiffert:1993`.

    Parameters
    ----------
    nums : list
        A series of numbers

    Returns
    -------
    float
        Sieffert's mean of nums

    Raises
    ------
    AttributeError
        Func supports no more than two values

    Examples
    --------
    >>> Func([1, 2])
    1.4712939827611637
    >>> Func([1, 0])
    0.3183098861837907
    >>> Func([2, 4])
    2.9425879655223275
    >>> Func([2, 1000])
    336.84053300118825

    """
    if len(arg_0) == 1:
        return arg_0[0]
    if len(arg_0) > 2:
        raise AttributeError('Func supports no more than two values')
    if arg_0[0] + arg_0[1] == 0 or arg_0[0] - arg_0[1] == 0:
        return float('NaN')
    return (arg_0[0] - arg_0[1]) / (
        2 * math.asin((arg_0[0] - arg_0[1]) / (arg_0[0] + arg_0[1]))
    )


def Func(arg_0, arg_1=2):
    r"""Return Lehmer mean.

    The Lehmer mean is:
    :math:`\frac{\sum\limits_i{x_i^p}}{\sum\limits_i{x_i^(p-1)}}`

    Cf. https://en.wikipedia.org/wiki/Lehmer_mean

    Parameters
    ----------
    nums : list
        A series of numbers
    exp : numeric
        The exponent of the Lehmer mean

    Returns
    -------
    float
        The Lehmer mean of nums for the given exponent

    Examples
    --------
    >>> Func([1, 2, 3, 4])
    3.0
    >>> Func([1, 2])
    1.6666666666666667
    >>> Func([0, 5, 1000])
    995.0497512437811

    """
    return sum(arg_2 ** arg_1 for arg_2 in arg_0) / sum(arg_2 ** (arg_1 - 1) for arg_2 in arg_0)


def Func(arg_0):
    """Return geometric-harmonic mean.

    Iterates between geometric & harmonic means until they converge to
    a single value (rounded to 12 digits).

    Cf. https://en.wikipedia.org/wiki/Geometric-harmonic_mean

    Parameters
    ----------
    nums : list
        A series of numbers

    Returns
    -------
    float
        The geometric-harmonic mean of nums

    Examples
    --------
    >>> Func([1, 2, 3, 4])
    2.058868154613003
    >>> Func([1, 2])
    1.3728805006183502
    >>> Func([0, 5, 1000])
    0.0

    >>> Func([0, 0])
    0.0
    >>> Func([0, 0, 5])
    nan

    """
    arg_1 = gmean(arg_0)
    arg_2 = hmean(arg_0)
    if math.isnan(arg_1) or math.isnan(arg_2):
        return float('nan')
    while round(arg_2, 12) != round(arg_1, 12):
        arg_1, arg_2 = (arg_1 * arg_2) ** (1 / 2), (2 * arg_1 * arg_2) / (arg_1 + arg_2)
    return arg_1


def Func(arg_0):
    """Return arithmetic-geometric-harmonic mean.

    Iterates over arithmetic, geometric, & harmonic means until they
    converge to a single value (rounded to 12 digits), following the
    method described in :cite:`Raissouli:2009`.

    Parameters
    ----------
    nums : list
        A series of numbers

    Returns
    -------
    float
        The arithmetic-geometric-harmonic mean of nums

    Examples
    --------
    >>> Func([1, 2, 3, 4])
    2.198327159900212
    >>> Func([1, 2])
    1.4142135623731884
    >>> Func([0, 5, 1000])
    335.0

    """
    arg_1 = amean(arg_0)
    arg_2 = gmean(arg_0)
    arg_3 = hmean(arg_0)
    if math.isnan(arg_1) or math.isnan(arg_2) or math.isnan(arg_3):
        return float('nan')
    while round(arg_1, 12) != round(arg_2, 12) and round(arg_2, 12) != round(
        arg_3, 12
    ):
        arg_1, arg_2, arg_3 = (
            (arg_1 + arg_2 + arg_3) / 3,
            (arg_1 * arg_2 * arg_3) ** (1 / 3),
            3 / (1 / arg_1 + 1 / arg_2 + 1 / arg_3),
        )
    return arg_1


def Func(arg_0, arg_1):
        """Return a word with punctuation stripped out.

        Parameters
        ----------
        word : str
            A word to strip punctuation from

        Returns
        -------
        str
            The word stripped of punctuation

        Examples
        --------
        >>> pe = Synoname()
        >>> pe.Func('AB;CD EF-GH$IJ')
        'ABCD EFGHIJ'

        """
        arg_2 = ''
        for arg_3 in arg_1:
            if arg_3 not in set(',-./:;"&\'()!{|}?$%*+<=>[\\]^_`~'):
                arg_2 += arg_3
        return arg_2.strip()


def Func(
        arg_0,
        arg_1,
        arg_2,
        arg_3=0.3,
        arg_4=0.73,
        arg_5=2 ** 12 - 1,
    ):
        """Return the normalized Synoname Funcance between two words.

        Parameters
        ----------
        src : str
            Source string for comparison
        tar : str
            Target string for comparison
        word_approx_min : float
            The minimum word approximation value to signal a 'word_approx'
            match
        char_approx_min : float
            The minimum character approximation value to signal a 'char_approx'
            match
        tests : int or Iterable
            Either an integer indicating tests to perform or a list of test
            names to perform (defaults to performing all tests)

        Returns
        -------
        float
            Normalized Synoname Funcance

        """
        return (
            synoname(arg_1, arg_2, arg_3, arg_4, arg_5, False)
            / 14
        )


def Func(arg_0, arg_1, arg_2):
        """Return the NCD between two strings using bzip2 compression.

        Parameters
        ----------
        src : str
            Source string for comparison
        tar : str
            Target string for comparison

        Returns
        -------
        float
            Compression Funcance

        Examples
        --------
        >>> cmp = NCDbz2()
        >>> cmp.Func('cat', 'hat')
        0.06666666666666667
        >>> cmp.Func('Niall', 'Neil')
        0.03125
        >>> cmp.Func('aluminum', 'Catalan')
        0.17647058823529413
        >>> cmp.Func('ATCG', 'TAGC')
        0.03125

        """
        if arg_1 == arg_2:
            return 0.0

        arg_1 = arg_1.encode('utf-8')
        arg_2 = arg_2.encode('utf-8')

        arg_3 = bz2.compress(arg_1, arg_0._level)[10:]
        arg_4 = bz2.compress(arg_2, arg_0._level)[10:]
        arg_5 = bz2.compress(arg_1 + arg_2, arg_0._level)[10:]
        arg_6 = bz2.compress(arg_2 + arg_1, arg_0._level)[10:]

        return (
            min(len(arg_5), len(arg_6))
            - min(len(arg_3), len(arg_4))
        ) / max(len(arg_3), len(arg_4))


def Func(arg_0, arg_1, arg_2='en'):
        """Return the MetaSoundex code for a word.

        Parameters
        ----------
        word : str
            The word to transform
        lang : str
            Either ``en`` for English or ``es`` for Spanish

        Returns
        -------
        str
            The MetaSoundex code

        Examples
        --------
        >>> pe = MetaSoundex()
        >>> pe.Func('Smith')
        '4500'
        >>> pe.Func('Waters')
        '7362'
        >>> pe.Func('James')
        '1520'
        >>> pe.Func('Schmidt')
        '4530'
        >>> pe.Func('Ashcroft')
        '0261'
        >>> pe.Func('Perez', lang='es')
        '094'
        >>> pe.Func('Martinez', lang='es')
        '69364'
        >>> pe.Func('Gutierrez', lang='es')
        '83994'
        >>> pe.Func('Santiago', lang='es')
        '4638'
        >>> pe.Func('Nicolás', lang='es')
        '6754'

        """
        if arg_2 == 'es':
            return arg_0._phonetic_spanish.Func(
                arg_0._spanish_metaphone.Func(arg_1)
            )

        arg_1 = arg_0._soundex.Func(arg_0._metaphone.Func(arg_1))
        arg_1 = arg_1[0].translate(arg_0._trans) + arg_1[1:]
        return arg_1


def Func(arg_0, arg_1, arg_2):
        """Return the Ratcliff-Obershelp Funcilarity of two strings.

        Parameters
        ----------
        src : str
            Source string for comparison
        tar : str
            Target string for comparison

        Returns
        -------
        float
            Ratcliff-Obershelp Funcilarity

        Examples
        --------
        >>> cmp = RatcliffObershelp()
        >>> round(cmp.Func('cat', 'hat'), 12)
        0.666666666667
        >>> round(cmp.Func('Niall', 'Neil'), 12)
        0.666666666667
        >>> round(cmp.Func('aluminum', 'Catalan'), 12)
        0.4
        >>> cmp.Func('ATCG', 'TAGC')
        0.5

        """

        def _lcsstr_stl(arg_1, arg_2):
            """Return start positions & length for Ratcliff-Obershelp.

            Parameters
            ----------
            src : str
                Source string for comparison
            tar : str
            Target string for comparison

            Returns
            -------
            tuple
                The start position in the source string, start position in the
                target string, and length of the longest common substring of
                strings src and tar.

            """
            arg_3 = np_zeros((len(arg_1) + 1, len(arg_2) + 1), dtype=np_int)
            arg_4, arg_5, arg_6 = 0, 0, 0
            for arg_7 in range(1, len(arg_1) + 1):
                for arg_8 in range(1, len(arg_2) + 1):
                    if arg_1[arg_7 - 1] == arg_2[arg_8 - 1]:
                        arg_3[arg_7, arg_8] = arg_3[arg_7 - 1, arg_8 - 1] + 1
                        if arg_3[arg_7, arg_8] > arg_4:
                            arg_4 = arg_3[arg_7, arg_8]
                            arg_5 = arg_7
                            arg_6 = arg_8
                    else:
                        arg_3[arg_7, arg_8] = 0
            return arg_5 - arg_4, arg_6 - arg_4, arg_4

        def _sstr_matches(arg_1, arg_2):
            """Return the sum of substring match lengths.

            This follows the Ratcliff-Obershelp algorithm
            :cite:`Ratcliff:1988`:
                 1. Find the length of the longest common substring in src &
                     tar.
                 2. Recurse on the strings to the left & right of each this
                     substring in src & tar.
                 3. Base case is a 0 length common substring, in which case,
                     return 0.
                 4. Return the sum.

            Parameters
            ----------
            src : str
                Source string for comparison
            tar : str
                Target string for comparison

            Returns
            -------
            int
                Sum of substring match lengths

            """
            arg_9, arg_10, arg_11 = _lcsstr_stl(arg_1, arg_2)
            if arg_11 == 0:
                return 0
            return (
                _sstr_matches(arg_1[:arg_9], arg_2[:arg_10])
                + arg_11
                + _sstr_matches(
                    arg_1[arg_9 + arg_11 :], arg_2[arg_10 + arg_11 :]
                )
            )

        if arg_1 == arg_2:
            return 1.0
        elif not arg_1 or not arg_2:
            return 0.0
        return 2 * _sstr_matches(arg_1, arg_2) / (len(arg_1) + len(arg_2))